From 9e9f46c44e487af0a82eb61b624553e2f7118f5b Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 11 Jun 2009 10:58:28 -0700 Subject: PCI: use ACPI _CRS data by default At this point, it seems to solve more problems than it causes, so let's try using it by default. It's an easy revert if it ends up causing trouble. Reviewed-by: Yinghai Lu Acked-by: Bjorn Helgaas Signed-off-by: Jesse Barnes --- arch/x86/pci/acpi.c | 2 +- arch/x86/pci/amd_bus.c | 2 +- arch/x86/pci/common.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/x86/pci') diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index c0ecf25..8d898e0 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -217,7 +217,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do #endif } - if (bus && (pci_probe & PCI_USE__CRS)) + if (bus && !(pci_probe & PCI_NO_ROOT_CRS)) get_current_resources(device, busnum, domain, bus); return bus; } diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c index f893d6a..2255f88 100644 --- a/arch/x86/pci/amd_bus.c +++ b/arch/x86/pci/amd_bus.c @@ -101,7 +101,7 @@ void x86_pci_root_bus_res_quirks(struct pci_bus *b) struct pci_root_info *info; /* don't go for it if _CRS is used */ - if (pci_probe & PCI_USE__CRS) + if (!(pci_probe & PCI_NO_ROOT_CRS)) return; /* if only one root bus, don't need to anything */ diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 2202b62..4740119 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -515,8 +515,8 @@ char * __devinit pcibios_setup(char *str) } else if (!strcmp(str, "assign-busses")) { pci_probe |= PCI_ASSIGN_ALL_BUSSES; return NULL; - } else if (!strcmp(str, "use_crs")) { - pci_probe |= PCI_USE__CRS; + } else if (!strcmp(str, "nocrs")) { + pci_probe |= PCI_NO_ROOT_CRS; return NULL; } else if (!strcmp(str, "earlydump")) { pci_early_dump_regs = 1; -- cgit v1.1 From f9cde5ffed17bf74f6bef042d99edb0622f58576 Mon Sep 17 00:00:00 2001 From: Gary Hade Date: Wed, 27 May 2009 12:41:44 -0700 Subject: x86/ACPI: Correct maximum allowed _CRS returned resources and warn if exceeded Issue a warning if _CRS returns too many resource descriptors to be accommodated by the fixed size resource array instances. If there is no transparent bridge on the root bus "too many" is the PCI_BUS_NUM_RESOURCES size of the resource array. Otherwise, the last 3 slots of the resource array must be excluded making the maximum (PCI_BUS_NUM_RESOURCES - 3). The current code: - is silent when _CRS returns too many resource descriptors and - incorrectly allows use of the last 3 slots of the resource array for a root bus with a transparent bridge Signed-off-by: Gary Hade Signed-off-by: Jesse Barnes --- arch/x86/pci/acpi.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) (limited to 'arch/x86/pci') diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index 8d898e0..16c3fda 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -38,15 +38,26 @@ count_resource(struct acpi_resource *acpi_res, void *data) struct acpi_resource_address64 addr; acpi_status status; - if (info->res_num >= PCI_BUS_NUM_RESOURCES) - return AE_OK; - status = resource_to_addr(acpi_res, &addr); if (ACPI_SUCCESS(status)) info->res_num++; 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 acpi_status setup_resource(struct acpi_resource *acpi_res, void *data) { @@ -56,9 +67,7 @@ setup_resource(struct acpi_resource *acpi_res, void *data) acpi_status status; unsigned long flags; struct resource *root; - - if (info->res_num >= PCI_BUS_NUM_RESOURCES) - return AE_OK; + int max_root_bus_resources = PCI_BUS_NUM_RESOURCES; status = resource_to_addr(acpi_res, &addr); if (!ACPI_SUCCESS(status)) @@ -82,6 +91,18 @@ setup_resource(struct acpi_resource *acpi_res, void *data) res->end = res->start + addr.address_length - 1; res->child = NULL; + if (bus_has_transparent_bridge(info->bus)) + max_root_bus_resources -= 3; + if (info->res_num >= max_root_bus_resources) { + 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) res->start, + (unsigned long) res->end, root->name, info->name, + max_root_bus_resources); + info->res_num++; + return AE_OK; + } + if (insert_resource(root, res)) { printk(KERN_ERR "PCI: Failed to allocate 0x%lx-0x%lx " "from %s for %s\n", (unsigned long) res->start, -- cgit v1.1