diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/alpha/kernel/pci.c | 5 | ||||
-rw-r--r-- | arch/ia64/pci/pci.c | 20 | ||||
-rw-r--r-- | arch/mn10300/unit-asb2305/pci.c | 7 | ||||
-rw-r--r-- | arch/powerpc/kernel/pci-common.c | 26 | ||||
-rw-r--r-- | arch/powerpc/kernel/pci_64.c | 18 | ||||
-rw-r--r-- | arch/powerpc/kernel/pci_of_scan.c | 7 | ||||
-rw-r--r-- | arch/powerpc/platforms/fsl_uli1575.c | 15 | ||||
-rw-r--r-- | arch/x86/pci/acpi.c | 33 | ||||
-rw-r--r-- | arch/x86/pci/bus_numa.c | 9 | ||||
-rw-r--r-- | arch/x86/pci/bus_numa.h | 3 |
10 files changed, 77 insertions, 66 deletions
diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c index e4bb1f380b61..c9ab94ee1ca8 100644 --- a/arch/alpha/kernel/pci.c +++ b/arch/alpha/kernel/pci.c @@ -292,9 +292,8 @@ pcibios_fixup_bus(struct pci_bus *bus) u32 sg_base = hose->sg_pci ? hose->sg_pci->dma_base : ~0; unsigned long end; - pci_bus_remove_resources(bus); - pci_bus_add_resource(bus, hose->io_space, 0); - pci_bus_add_resource(bus, hose->mem_space, 0); + bus->resource[0] = hose->io_space; + bus->resource[1] = hose->mem_space; /* Adjust hose mem_space limit to prevent PCI allocations in the iommu windows. */ diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index ad6455446a91..783c83bb2b49 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -320,9 +320,9 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data) static void __devinit pcibios_setup_root_windows(struct pci_bus *bus, struct pci_controller *ctrl) { - int i; + int i, j; - pci_bus_remove_resources(bus); + j = 0; for (i = 0; i < ctrl->windows; i++) { struct resource *res = &ctrl->window[i].resource; /* HP's firmware has a hack to work around a Windows bug. @@ -330,7 +330,13 @@ pcibios_setup_root_windows(struct pci_bus *bus, struct pci_controller *ctrl) if ((res->flags & IORESOURCE_MEM) && (res->end - res->start < 16)) continue; - pci_bus_add_resource(bus, res, 0); + if (j >= PCI_BUS_NUM_RESOURCES) { + dev_warn(&bus->dev, + "ignoring host bridge window %pR (no space)\n", + res); + continue; + } + bus->resource[j++] = res; } } @@ -445,15 +451,13 @@ EXPORT_SYMBOL(pcibios_bus_to_resource); static int __devinit is_valid_resource(struct pci_dev *dev, int idx) { - unsigned int type_mask = IORESOURCE_IO | IORESOURCE_MEM; + unsigned int i, type_mask = IORESOURCE_IO | IORESOURCE_MEM; struct resource *devr = &dev->resource[idx]; - struct pci_bus_resource *bus_res; if (!dev->bus) return 0; - - list_for_each_entry(bus_res, &dev->bus->resources, list) { - struct resource *busr = bus_res->res; + for (i=0; i<PCI_BUS_NUM_RESOURCES; i++) { + struct resource *busr = dev->bus->resource[i]; if (!busr || ((busr->flags ^ devr->flags) & type_mask)) continue; diff --git a/arch/mn10300/unit-asb2305/pci.c b/arch/mn10300/unit-asb2305/pci.c index 187adccec963..2cb7e75ba1c0 100644 --- a/arch/mn10300/unit-asb2305/pci.c +++ b/arch/mn10300/unit-asb2305/pci.c @@ -332,13 +332,12 @@ static int __devinit is_valid_resource(struct pci_dev *dev, int idx) { unsigned int i, type_mask = IORESOURCE_IO | IORESOURCE_MEM; struct resource *devr = &dev->resource[idx]; - struct pci_bus_resource *bus_res; if (dev->bus) { - list_for_each_entry(bus_res, &dev->bus->resources, list) { - struct resource *busr = bus_res->res; + for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { + struct resource *busr = dev->bus->resource[i]; - if ((busr->flags ^ devr->flags) & type_mask) + if (!busr || (busr->flags ^ devr->flags) & type_mask) continue; if (devr->start && diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index d75546eb15ec..e640810e813f 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -1042,15 +1042,14 @@ static int __devinit pcibios_uninitialized_bridge_resource(struct pci_bus *bus, /* Fixup resources of a PCI<->PCI bridge */ static void __devinit pcibios_fixup_bridge(struct pci_bus *bus) { - struct pci_bus_resource *bus_res; struct resource *res; - int i = -1; + int i; struct pci_dev *dev = bus->self; - list_for_each_entry(bus_res, &bus->resources, list) { - i++; - res = bus_res->res; + for (i = 0; i < PCI_BUS_NUM_RESOURCES; ++i) { + if ((res = bus->resource[i]) == NULL) + continue; if (!res->flags) continue; if (i >= 3 && bus->self->transparent) @@ -1272,17 +1271,15 @@ static int reparent_resources(struct resource *parent, void pcibios_allocate_bus_resources(struct pci_bus *bus) { struct pci_bus *b; - int i = -1; - struct pci_bus_resource *bus_res; + int i; struct resource *res, *pr; pr_debug("PCI: Allocating bus resources for %04x:%02x...\n", pci_domain_nr(bus), bus->number); - list_for_each_entry(bus_res, &bus->resources, list) { - i++; - res = bus_res->res; - if (!res->flags || res->start > res->end || res->parent) + for (i = 0; i < PCI_BUS_NUM_RESOURCES; ++i) { + if ((res = bus->resource[i]) == NULL || !res->flags + || res->start > res->end || res->parent) continue; if (bus->parent == NULL) pr = (res->flags & IORESOURCE_IO) ? @@ -1582,11 +1579,8 @@ void __devinit pcibios_setup_phb_resources(struct pci_controller *hose) struct resource *res; int i; - pci_bus_remove_resources(bus); - /* Hookup PHB IO resource */ - res = &hose->io_resource; - pci_bus_add_resource(bus, res, 0); + bus->resource[0] = res = &hose->io_resource; if (!res->flags) { printk(KERN_WARNING "PCI: I/O resource not set for host" @@ -1621,7 +1615,7 @@ void __devinit pcibios_setup_phb_resources(struct pci_controller *hose) res->flags = IORESOURCE_MEM; #endif /* CONFIG_PPC32 */ } - pci_bus_add_resource(bus, res, 0); + bus->resource[i+1] = res; pr_debug("PCI: PHB MEM resource %d = %016llx-%016llx [%lx]\n", i, (unsigned long long)res->start, diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 1bd881b613bd..d43fc65749c1 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -82,7 +82,6 @@ subsys_initcall(pcibios_init); int pcibios_unmap_io_space(struct pci_bus *bus) { - struct pci_dev *bridge = bus->self; struct pci_controller *hose; WARN_ON(bus == NULL); @@ -97,13 +96,13 @@ int pcibios_unmap_io_space(struct pci_bus *bus) * Note: If we ever support P2P hotplug on Book3E, we'll have * to do an appropriate TLB flush here too */ - if (bridge) { + if (bus->self) { #ifdef CONFIG_PPC_STD_MMU_64 - struct resource *res = &bridge->resource[PCI_BRIDGE_RESOURCES + 0]; + struct resource *res = bus->resource[0]; #endif pr_debug("IO unmapping for PCI-PCI bridge %s\n", - pci_name(bridge)); + pci_name(bus->self)); #ifdef CONFIG_PPC_STD_MMU_64 __flush_hash_table_range(&init_mm, res->start + _IO_BASE, @@ -133,7 +132,6 @@ EXPORT_SYMBOL_GPL(pcibios_unmap_io_space); int __devinit pcibios_map_io_space(struct pci_bus *bus) { - struct pci_dev *bridge = bus->self; struct vm_struct *area; unsigned long phys_page; unsigned long size_page; @@ -145,14 +143,12 @@ int __devinit pcibios_map_io_space(struct pci_bus *bus) /* If this not a PHB, nothing to do, page tables still exist and * thus HPTEs will be faulted in when needed */ - if (bridge) { - struct resource *res = &bridge->resource[PCI_BRIDGE_RESOURCES + 0]; - + if (bus->self) { pr_debug("IO mapping for PCI-PCI bridge %s\n", - pci_name(bridge)); + pci_name(bus->self)); pr_debug(" virt=0x%016llx...0x%016llx\n", - res->start + _IO_BASE, - res->end + _IO_BASE); + bus->resource[0]->start + _IO_BASE, + bus->resource[0]->end + _IO_BASE); return 0; } diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c index a4f8b68bb2ef..cd11d5ca80df 100644 --- a/arch/powerpc/kernel/pci_of_scan.c +++ b/arch/powerpc/kernel/pci_of_scan.c @@ -242,11 +242,10 @@ void __devinit of_scan_pci_bridge(struct device_node *node, /* parse ranges property */ /* PCI #address-cells == 3 and #size-cells == 2 always */ - pci_bus_remove_resources(bus); res = &dev->resource[PCI_BRIDGE_RESOURCES]; for (i = 0; i < PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES; ++i) { res->flags = 0; - pci_bus_add_resource(bus, res, PCI_POSITIVE_DECODE); + bus->resource[i] = res; ++res; } i = 1; @@ -256,7 +255,7 @@ void __devinit of_scan_pci_bridge(struct device_node *node, if (flags == 0 || size == 0) continue; if (flags & IORESOURCE_IO) { - res = &dev->resource[PCI_BRIDGE_RESOURCES + 0]; + res = bus->resource[0]; if (res->flags) { printk(KERN_ERR "PCI: ignoring extra I/O range" " for bridge %s\n", node->full_name); @@ -268,7 +267,7 @@ void __devinit of_scan_pci_bridge(struct device_node *node, " for bridge %s\n", node->full_name); continue; } - res = &dev->resource[PCI_BRIDGE_RESOURCES + i]; + res = bus->resource[i]; ++i; } res->start = of_read_number(&ranges[1], 2); diff --git a/arch/powerpc/platforms/fsl_uli1575.c b/arch/powerpc/platforms/fsl_uli1575.c index 04c546f67e02..fd23a1d4b39d 100644 --- a/arch/powerpc/platforms/fsl_uli1575.c +++ b/arch/powerpc/platforms/fsl_uli1575.c @@ -222,8 +222,6 @@ static void __devinit quirk_final_uli5249(struct pci_dev *dev) int i; u8 *dummy; struct pci_bus *bus = dev->bus; - struct pci_bus_resource *bus_res; - struct resource *res; resource_size_t end = 0; for (i = PCI_BRIDGE_RESOURCES; i < PCI_BRIDGE_RESOURCES+3; i++) { @@ -232,14 +230,13 @@ static void __devinit quirk_final_uli5249(struct pci_dev *dev) end = pci_resource_end(dev, i); } - list_for_each_entry(bus_res, &bus->resources, list) { - res = bus_res->res; - - if (res->flags & IORESOURCE_MEM) { - if (res->end == end) - dummy = ioremap(res->start, 0x4); + for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { + if ((bus->resource[i]) && + (bus->resource[i]->flags & IORESOURCE_MEM)) { + if (bus->resource[i]->end == end) + dummy = ioremap(bus->resource[i]->start, 0x4); else - dummy = ioremap(res->end - 3, 0x4); + dummy = ioremap(bus->resource[i]->end - 3, 0x4); if (dummy) { in_8(dummy); iounmap(dummy); diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index a2f8cdb8c1d5..959e548a7039 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -45,6 +45,20 @@ count_resource(struct acpi_resource *acpi_res, void *data) return AE_OK; } +static int +bus_has_transparent_bridge(struct pci_bus *bus) +{ + struct pci_dev *dev; + + list_for_each_entry(dev, &bus->devices, bus_list) { + u16 class = dev->class >> 8; + + if (class == PCI_CLASS_BRIDGE_PCI && dev->transparent) + return true; + } + return false; +} + static void align_resource(struct acpi_device *bridge, struct resource *res) { @@ -78,8 +92,12 @@ setup_resource(struct acpi_resource *acpi_res, void *data) acpi_status status; unsigned long flags; struct resource *root; + int max_root_bus_resources = PCI_BUS_NUM_RESOURCES; u64 start, end; + if (bus_has_transparent_bridge(info->bus)) + max_root_bus_resources -= 3; + status = resource_to_addr(acpi_res, &addr); if (!ACPI_SUCCESS(status)) return AE_OK; @@ -97,6 +115,15 @@ setup_resource(struct acpi_resource *acpi_res, void *data) start = addr.minimum + addr.translation_offset; end = start + addr.address_length - 1; + if (info->res_num >= max_root_bus_resources) { + if (pci_probe & PCI_USE__CRS) + printk(KERN_WARNING "PCI: Failed to allocate " + "0x%lx-0x%lx from %s for %s due to _CRS " + "returning more than %d resource descriptors\n", + (unsigned long) start, (unsigned long) end, + root->name, info->name, max_root_bus_resources); + return AE_OK; + } res = &info->res[info->res_num]; res->name = info->name; @@ -116,7 +143,7 @@ setup_resource(struct acpi_resource *acpi_res, void *data) dev_err(&info->bridge->dev, "can't allocate host bridge window %pR\n", res); } else { - pci_bus_add_resource(info->bus, res, 0); + info->bus->resource[info->res_num] = res; info->res_num++; if (addr.translation_offset) dev_info(&info->bridge->dev, "host bridge window %pR " @@ -137,9 +164,7 @@ get_current_resources(struct acpi_device *device, int busnum, struct pci_root_info info; size_t size; - if (pci_probe & PCI_USE__CRS) - pci_bus_remove_resources(bus); - else + if (!(pci_probe & PCI_USE__CRS)) dev_info(&device->dev, "ignoring host bridge windows from ACPI; " "boot with \"pci=use_crs\" to use them\n"); diff --git a/arch/x86/pci/bus_numa.c b/arch/x86/pci/bus_numa.c index 6999970ca753..f939d603adfa 100644 --- a/arch/x86/pci/bus_numa.c +++ b/arch/x86/pci/bus_numa.c @@ -12,12 +12,10 @@ void x86_pci_root_bus_res_quirks(struct pci_bus *b) int i; int j; struct pci_root_info *info; - struct pci_bus_resource *bus_res; /* don't go for it if _CRS is used already */ - bus_res = list_first_entry(&b->resources, struct pci_bus_resource, - list); - if (bus_res->res != &ioport_resource) + if (b->resource[0] != &ioport_resource || + b->resource[1] != &iomem_resource) return; if (!pci_root_num) @@ -38,14 +36,13 @@ void x86_pci_root_bus_res_quirks(struct pci_bus *b) printk(KERN_DEBUG "PCI: peer root bus %02x res updated from pci conf\n", b->number); - pci_bus_remove_resources(b); info = &pci_root_info[i]; for (j = 0; j < info->res_num; j++) { struct resource *res; struct resource *root; res = &info->res[j]; - pci_bus_add_resource(b, res, 0); + b->resource[j] = res; if (res->flags & IORESOURCE_IO) root = &ioport_resource; else diff --git a/arch/x86/pci/bus_numa.h b/arch/x86/pci/bus_numa.h index 731b64ee8d84..adbc23fe82ac 100644 --- a/arch/x86/pci/bus_numa.h +++ b/arch/x86/pci/bus_numa.h @@ -2,7 +2,8 @@ /* * sub bus (transparent) will use entres from 3 to store extra from - * root, so need to make sure we have enough slot there. + * root, so need to make sure we have enough slot there, Should we + * increase PCI_BUS_NUM_RESOURCES? */ #define RES_NUM 16 struct pci_root_info { |