aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorGary Hade <garyhade@us.ibm.com>2009-05-27 15:41:44 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-06-16 17:53:32 -0400
commitf9cde5ffed17bf74f6bef042d99edb0622f58576 (patch)
tree1bd553e8624a5efe6c2a2de021eed2ad649bd33c /arch/x86
parentab7de999a2c771482698efa6fe7c7b7fcb1d482a (diff)
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 <garyhade@us.ibm.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/pci/acpi.c33
1 files changed, 27 insertions, 6 deletions
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 8d898e0d3609..16c3fda85bba 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)
38 struct acpi_resource_address64 addr; 38 struct acpi_resource_address64 addr;
39 acpi_status status; 39 acpi_status status;
40 40
41 if (info->res_num >= PCI_BUS_NUM_RESOURCES)
42 return AE_OK;
43
44 status = resource_to_addr(acpi_res, &addr); 41 status = resource_to_addr(acpi_res, &addr);
45 if (ACPI_SUCCESS(status)) 42 if (ACPI_SUCCESS(status))
46 info->res_num++; 43 info->res_num++;
47 return AE_OK; 44 return AE_OK;
48} 45}
49 46
47static int
48bus_has_transparent_bridge(struct pci_bus *bus)
49{
50 struct pci_dev *dev;
51
52 list_for_each_entry(dev, &bus->devices, bus_list) {
53 u16 class = dev->class >> 8;
54
55 if (class == PCI_CLASS_BRIDGE_PCI && dev->transparent)
56 return true;
57 }
58 return false;
59}
60
50static acpi_status 61static acpi_status
51setup_resource(struct acpi_resource *acpi_res, void *data) 62setup_resource(struct acpi_resource *acpi_res, void *data)
52{ 63{
@@ -56,9 +67,7 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
56 acpi_status status; 67 acpi_status status;
57 unsigned long flags; 68 unsigned long flags;
58 struct resource *root; 69 struct resource *root;
59 70 int max_root_bus_resources = PCI_BUS_NUM_RESOURCES;
60 if (info->res_num >= PCI_BUS_NUM_RESOURCES)
61 return AE_OK;
62 71
63 status = resource_to_addr(acpi_res, &addr); 72 status = resource_to_addr(acpi_res, &addr);
64 if (!ACPI_SUCCESS(status)) 73 if (!ACPI_SUCCESS(status))
@@ -82,6 +91,18 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
82 res->end = res->start + addr.address_length - 1; 91 res->end = res->start + addr.address_length - 1;
83 res->child = NULL; 92 res->child = NULL;
84 93
94 if (bus_has_transparent_bridge(info->bus))
95 max_root_bus_resources -= 3;
96 if (info->res_num >= max_root_bus_resources) {
97 printk(KERN_WARNING "PCI: Failed to allocate 0x%lx-0x%lx "
98 "from %s for %s due to _CRS returning more than "
99 "%d resource descriptors\n", (unsigned long) res->start,
100 (unsigned long) res->end, root->name, info->name,
101 max_root_bus_resources);
102 info->res_num++;
103 return AE_OK;
104 }
105
85 if (insert_resource(root, res)) { 106 if (insert_resource(root, res)) {
86 printk(KERN_ERR "PCI: Failed to allocate 0x%lx-0x%lx " 107 printk(KERN_ERR "PCI: Failed to allocate 0x%lx-0x%lx "
87 "from %s for %s\n", (unsigned long) res->start, 108 "from %s for %s\n", (unsigned long) res->start,