summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/alpha/kernel/pci.c5
-rw-r--r--arch/ia64/pci/pci.c20
-rw-r--r--arch/mn10300/unit-asb2305/pci.c7
-rw-r--r--arch/powerpc/kernel/pci-common.c26
-rw-r--r--arch/powerpc/kernel/pci_64.c18
-rw-r--r--arch/powerpc/kernel/pci_of_scan.c7
-rw-r--r--arch/powerpc/platforms/fsl_uli1575.c15
-rw-r--r--arch/x86/pci/acpi.c33
-rw-r--r--arch/x86/pci/bus_numa.c9
-rw-r--r--arch/x86/pci/bus_numa.h3
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 {