aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/pci/acpi.c
diff options
context:
space:
mode:
authorBjorn Helgaas <bjorn.helgaas@hp.com>2010-02-23 12:24:36 -0500
committerJesse Barnes <jbarnes@virtuousgeek.org>2010-02-23 12:43:37 -0500
commit2fe2abf896c1e7a0ee65faaf3ef0ce654848abbd (patch)
treef066d5c94bbed5ca3556b4d2f0c4b3a9795b6eff /arch/x86/pci/acpi.c
parent89a74ecccd1f78e51faf6287e5c0e93a92ac096e (diff)
PCI: augment bus resource table with a list
Previously we used a table of size PCI_BUS_NUM_RESOURCES (16) for resources forwarded to a bus by its upstream bridge. We've increased this size several times when the table overflowed. But there's no good limit on the number of resources because host bridges and subtractive decode bridges can forward any number of ranges to their secondary buses. This patch reduces the table to only PCI_BRIDGE_RESOURCE_NUM (4) entries, which corresponds to the number of windows a PCI-to-PCI (3) or CardBus (4) bridge can positively decode. Any additional resources, e.g., PCI host bridge windows or subtractively-decoded regions, are kept in a list. I'd prefer a single list rather than this split table/list approach, but that requires simultaneous changes to every architecture. This approach only requires immediate changes where we set up (a) host bridges with more than four windows and (b) subtractive-decode P2P bridges, and we can incrementally change other architectures to use the list. Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'arch/x86/pci/acpi.c')
-rw-r--r--arch/x86/pci/acpi.c33
1 files changed, 4 insertions, 29 deletions
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 959e548a7039..a2f8cdb8c1d5 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -45,20 +45,6 @@ count_resource(struct acpi_resource *acpi_res, void *data)
45 return AE_OK; 45 return AE_OK;
46} 46}
47 47
48static int
49bus_has_transparent_bridge(struct pci_bus *bus)
50{
51 struct pci_dev *dev;
52
53 list_for_each_entry(dev, &bus->devices, bus_list) {
54 u16 class = dev->class >> 8;
55
56 if (class == PCI_CLASS_BRIDGE_PCI && dev->transparent)
57 return true;
58 }
59 return false;
60}
61
62static void 48static void
63align_resource(struct acpi_device *bridge, struct resource *res) 49align_resource(struct acpi_device *bridge, struct resource *res)
64{ 50{
@@ -92,12 +78,8 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
92 acpi_status status; 78 acpi_status status;
93 unsigned long flags; 79 unsigned long flags;
94 struct resource *root; 80 struct resource *root;
95 int max_root_bus_resources = PCI_BUS_NUM_RESOURCES;
96 u64 start, end; 81 u64 start, end;
97 82
98 if (bus_has_transparent_bridge(info->bus))
99 max_root_bus_resources -= 3;
100
101 status = resource_to_addr(acpi_res, &addr); 83 status = resource_to_addr(acpi_res, &addr);
102 if (!ACPI_SUCCESS(status)) 84 if (!ACPI_SUCCESS(status))
103 return AE_OK; 85 return AE_OK;
@@ -115,15 +97,6 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
115 97
116 start = addr.minimum + addr.translation_offset; 98 start = addr.minimum + addr.translation_offset;
117 end = start + addr.address_length - 1; 99 end = start + addr.address_length - 1;
118 if (info->res_num >= max_root_bus_resources) {
119 if (pci_probe & PCI_USE__CRS)
120 printk(KERN_WARNING "PCI: Failed to allocate "
121 "0x%lx-0x%lx from %s for %s due to _CRS "
122 "returning more than %d resource descriptors\n",
123 (unsigned long) start, (unsigned long) end,
124 root->name, info->name, max_root_bus_resources);
125 return AE_OK;
126 }
127 100
128 res = &info->res[info->res_num]; 101 res = &info->res[info->res_num];
129 res->name = info->name; 102 res->name = info->name;
@@ -143,7 +116,7 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
143 dev_err(&info->bridge->dev, 116 dev_err(&info->bridge->dev,
144 "can't allocate host bridge window %pR\n", res); 117 "can't allocate host bridge window %pR\n", res);
145 } else { 118 } else {
146 info->bus->resource[info->res_num] = res; 119 pci_bus_add_resource(info->bus, res, 0);
147 info->res_num++; 120 info->res_num++;
148 if (addr.translation_offset) 121 if (addr.translation_offset)
149 dev_info(&info->bridge->dev, "host bridge window %pR " 122 dev_info(&info->bridge->dev, "host bridge window %pR "
@@ -164,7 +137,9 @@ get_current_resources(struct acpi_device *device, int busnum,
164 struct pci_root_info info; 137 struct pci_root_info info;
165 size_t size; 138 size_t size;
166 139
167 if (!(pci_probe & PCI_USE__CRS)) 140 if (pci_probe & PCI_USE__CRS)
141 pci_bus_remove_resources(bus);
142 else
168 dev_info(&device->dev, 143 dev_info(&device->dev,
169 "ignoring host bridge windows from ACPI; " 144 "ignoring host bridge windows from ACPI; "
170 "boot with \"pci=use_crs\" to use them\n"); 145 "boot with \"pci=use_crs\" to use them\n");