summaryrefslogtreecommitdiff
path: root/arch/x86/pci/acpi.c
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2010-02-16 18:16:39 +1100
committerStephen Rothwell <sfr@canb.auug.org.au>2010-02-16 18:16:39 +1100
commit4836d02cce0a6a54d8cac2211435d5a410fe4cce (patch)
tree0bf7cc735d3979570a26e434f2998dba1e4c804a /arch/x86/pci/acpi.c
parentb766a27a403e5961d27febf13347bbf8ebed2b8d (diff)
Revert "PCI: replace bus resource table with a list"
This reverts commit 94a8887c501b22a2818ee58197864e9eab983510.
Diffstat (limited to 'arch/x86/pci/acpi.c')
-rw-r--r--arch/x86/pci/acpi.c33
1 files changed, 29 insertions, 4 deletions
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");