aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2011-10-28 18:28:14 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2012-01-06 15:11:14 -0500
commit2cd6975a4ff92a75e46240109d01c1daf4682e5d (patch)
treeec5ca0a025c31e54c5f4c6701dc8c79ce012f820
parent46fbade05ca0784ca3c959bd7bf2aae7d81306c2 (diff)
x86/PCI: convert to pci_create_root_bus() and pci_scan_root_bus()
x86 has two kinds of PCI root bus scanning: (1) ACPI-based, using _CRS resources. This used pci_create_bus(), not pci_scan_bus(), because ACPI hotplug needed to split the pci_bus_add_devices() into a separate host bridge .start() method. This patch parses the _CRS resources earlier, so we can build a list of resources and pass it to pci_create_root_bus(). Note that as before, we parse the _CRS even if we aren't going to use it so we can print it for debugging purposes. (2) All other, which used either default resources (ioport_resource and iomem_resource) or information read from the hardware via amd_bus.c or similar. This used pci_scan_bus(). This patch converts x86_pci_root_bus_res_quirks() (previously called from pcibios_fixup_bus()) to x86_pci_root_bus_resources(), which builds a list of resources before we call pci_scan_root_bus(). We also use x86_pci_root_bus_resources() if we have ACPI but are ignoring _CRS. CC: Yinghai Lu <yinghai.lu@oracle.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
-rw-r--r--arch/x86/include/asm/topology.h2
-rw-r--r--arch/x86/pci/acpi.c28
-rw-r--r--arch/x86/pci/bus_numa.c31
-rw-r--r--arch/x86/pci/common.c19
4 files changed, 45 insertions, 35 deletions
diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h
index c00692476e9f..5f83b136dda7 100644
--- a/arch/x86/include/asm/topology.h
+++ b/arch/x86/include/asm/topology.h
@@ -174,7 +174,7 @@ static inline void arch_fix_phys_package_id(int num, u32 slot)
174} 174}
175 175
176struct pci_bus; 176struct pci_bus;
177void x86_pci_root_bus_res_quirks(struct pci_bus *b); 177void x86_pci_root_bus_resources(int bus, struct list_head *resources);
178 178
179#ifdef CONFIG_SMP 179#ifdef CONFIG_SMP
180#define mc_capable() ((boot_cpu_data.x86_max_cores > 1) && \ 180#define mc_capable() ((boot_cpu_data.x86_max_cores > 1) && \
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 425500bb24e6..a312e76063a7 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -12,7 +12,7 @@ struct pci_root_info {
12 char *name; 12 char *name;
13 unsigned int res_num; 13 unsigned int res_num;
14 struct resource *res; 14 struct resource *res;
15 struct pci_bus *bus; 15 struct list_head *resources;
16 int busnum; 16 int busnum;
17}; 17};
18 18
@@ -304,23 +304,20 @@ static void add_resources(struct pci_root_info *info)
304 "ignoring host bridge window %pR (conflicts with %s %pR)\n", 304 "ignoring host bridge window %pR (conflicts with %s %pR)\n",
305 res, conflict->name, conflict); 305 res, conflict->name, conflict);
306 else 306 else
307 pci_bus_add_resource(info->bus, res, 0); 307 pci_add_resource(info->resources, res);
308 } 308 }
309} 309}
310 310
311static void 311static void
312get_current_resources(struct acpi_device *device, int busnum, 312get_current_resources(struct acpi_device *device, int busnum,
313 int domain, struct pci_bus *bus) 313 int domain, struct list_head *resources)
314{ 314{
315 struct pci_root_info info; 315 struct pci_root_info info;
316 size_t size; 316 size_t size;
317 317
318 if (pci_use_crs)
319 pci_bus_remove_resources(bus);
320
321 info.bridge = device; 318 info.bridge = device;
322 info.bus = bus;
323 info.res_num = 0; 319 info.res_num = 0;
320 info.resources = resources;
324 acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource, 321 acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource,
325 &info); 322 &info);
326 if (!info.res_num) 323 if (!info.res_num)
@@ -329,7 +326,7 @@ get_current_resources(struct acpi_device *device, int busnum,
329 size = sizeof(*info.res) * info.res_num; 326 size = sizeof(*info.res) * info.res_num;
330 info.res = kmalloc(size, GFP_KERNEL); 327 info.res = kmalloc(size, GFP_KERNEL);
331 if (!info.res) 328 if (!info.res)
332 goto res_alloc_fail; 329 return;
333 330
334 info.name = kasprintf(GFP_KERNEL, "PCI Bus %04x:%02x", domain, busnum); 331 info.name = kasprintf(GFP_KERNEL, "PCI Bus %04x:%02x", domain, busnum);
335 if (!info.name) 332 if (!info.name)
@@ -344,8 +341,6 @@ get_current_resources(struct acpi_device *device, int busnum,
344 341
345name_alloc_fail: 342name_alloc_fail:
346 kfree(info.res); 343 kfree(info.res);
347res_alloc_fail:
348 return;
349} 344}
350 345
351struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root) 346struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
@@ -353,6 +348,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
353 struct acpi_device *device = root->device; 348 struct acpi_device *device = root->device;
354 int domain = root->segment; 349 int domain = root->segment;
355 int busnum = root->secondary.start; 350 int busnum = root->secondary.start;
351 LIST_HEAD(resources);
356 struct pci_bus *bus; 352 struct pci_bus *bus;
357 struct pci_sysdata *sd; 353 struct pci_sysdata *sd;
358 int node; 354 int node;
@@ -407,11 +403,15 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
407 memcpy(bus->sysdata, sd, sizeof(*sd)); 403 memcpy(bus->sysdata, sd, sizeof(*sd));
408 kfree(sd); 404 kfree(sd);
409 } else { 405 } else {
410 bus = pci_create_bus(NULL, busnum, &pci_root_ops, sd); 406 get_current_resources(device, busnum, domain, &resources);
411 if (bus) { 407 if (list_empty(&resources))
412 get_current_resources(device, busnum, domain, bus); 408 x86_pci_root_bus_resources(busnum, &resources);
409 bus = pci_create_root_bus(NULL, busnum, &pci_root_ops, sd,
410 &resources);
411 if (bus)
413 bus->subordinate = pci_scan_child_bus(bus); 412 bus->subordinate = pci_scan_child_bus(bus);
414 } 413 else
414 pci_free_resource_list(&resources);
415 } 415 }
416 416
417 /* After the PCI-E bus has been walked and all devices discovered, 417 /* After the PCI-E bus has been walked and all devices discovered,
diff --git a/arch/x86/pci/bus_numa.c b/arch/x86/pci/bus_numa.c
index 64a122883896..fd3f65510e9d 100644
--- a/arch/x86/pci/bus_numa.c
+++ b/arch/x86/pci/bus_numa.c
@@ -7,45 +7,50 @@
7int pci_root_num; 7int pci_root_num;
8struct pci_root_info pci_root_info[PCI_ROOT_NR]; 8struct pci_root_info pci_root_info[PCI_ROOT_NR];
9 9
10void x86_pci_root_bus_res_quirks(struct pci_bus *b) 10void x86_pci_root_bus_resources(int bus, struct list_head *resources)
11{ 11{
12 int i; 12 int i;
13 int j; 13 int j;
14 struct pci_root_info *info; 14 struct pci_root_info *info;
15 15
16 /* don't go for it if _CRS is used already */
17 if (b->resource[0] != &ioport_resource ||
18 b->resource[1] != &iomem_resource)
19 return;
20
21 if (!pci_root_num) 16 if (!pci_root_num)
22 return; 17 goto default_resources;
23 18
24 for (i = 0; i < pci_root_num; i++) { 19 for (i = 0; i < pci_root_num; i++) {
25 if (pci_root_info[i].bus_min == b->number) 20 if (pci_root_info[i].bus_min == bus)
26 break; 21 break;
27 } 22 }
28 23
29 if (i == pci_root_num) 24 if (i == pci_root_num)
30 return; 25 goto default_resources;
31 26
32 printk(KERN_DEBUG "PCI: peer root bus %02x res updated from pci conf\n", 27 printk(KERN_DEBUG "PCI: root bus %02x: hardware-probed resources\n",
33 b->number); 28 bus);
34 29
35 pci_bus_remove_resources(b);
36 info = &pci_root_info[i]; 30 info = &pci_root_info[i];
37 for (j = 0; j < info->res_num; j++) { 31 for (j = 0; j < info->res_num; j++) {
38 struct resource *res; 32 struct resource *res;
39 struct resource *root; 33 struct resource *root;
40 34
41 res = &info->res[j]; 35 res = &info->res[j];
42 pci_bus_add_resource(b, res, 0); 36 pci_add_resource(resources, res);
43 if (res->flags & IORESOURCE_IO) 37 if (res->flags & IORESOURCE_IO)
44 root = &ioport_resource; 38 root = &ioport_resource;
45 else 39 else
46 root = &iomem_resource; 40 root = &iomem_resource;
47 insert_resource(root, res); 41 insert_resource(root, res);
48 } 42 }
43 return;
44
45default_resources:
46 /*
47 * We don't have any host bridge aperture information from the
48 * "native host bridge drivers," e.g., amd_bus or broadcom_bus,
49 * so fall back to the defaults historically used by pci_create_bus().
50 */
51 printk(KERN_DEBUG "PCI: root bus %02x: using default resources\n", bus);
52 pci_add_resource(resources, &ioport_resource);
53 pci_add_resource(resources, &iomem_resource);
49} 54}
50 55
51void __devinit update_res(struct pci_root_info *info, resource_size_t start, 56void __devinit update_res(struct pci_root_info *info, resource_size_t start,
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 07c55ce6fdf5..323481e06ef8 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -164,9 +164,6 @@ void __devinit pcibios_fixup_bus(struct pci_bus *b)
164{ 164{
165 struct pci_dev *dev; 165 struct pci_dev *dev;
166 166
167 /* root bus? */
168 if (!b->parent)
169 x86_pci_root_bus_res_quirks(b);
170 pci_read_bridge_bases(b); 167 pci_read_bridge_bases(b);
171 list_for_each_entry(dev, &b->devices, bus_list) 168 list_for_each_entry(dev, &b->devices, bus_list)
172 pcibios_fixup_device_resources(dev); 169 pcibios_fixup_device_resources(dev);
@@ -433,6 +430,7 @@ void __init dmi_check_pciprobe(void)
433 430
434struct pci_bus * __devinit pcibios_scan_root(int busnum) 431struct pci_bus * __devinit pcibios_scan_root(int busnum)
435{ 432{
433 LIST_HEAD(resources);
436 struct pci_bus *bus = NULL; 434 struct pci_bus *bus = NULL;
437 struct pci_sysdata *sd; 435 struct pci_sysdata *sd;
438 436
@@ -456,9 +454,12 @@ struct pci_bus * __devinit pcibios_scan_root(int busnum)
456 sd->node = get_mp_bus_to_node(busnum); 454 sd->node = get_mp_bus_to_node(busnum);
457 455
458 printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busnum); 456 printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busnum);
459 bus = pci_scan_bus(busnum, &pci_root_ops, sd); 457 x86_pci_root_bus_resources(busnum, &resources);
460 if (!bus) 458 bus = pci_scan_root_bus(NULL, busnum, &pci_root_ops, sd, &resources);
459 if (!bus) {
460 pci_free_resource_list(&resources);
461 kfree(sd); 461 kfree(sd);
462 }
462 463
463 return bus; 464 return bus;
464} 465}
@@ -639,6 +640,7 @@ int pci_ext_cfg_avail(struct pci_dev *dev)
639 640
640struct pci_bus * __devinit pci_scan_bus_on_node(int busno, struct pci_ops *ops, int node) 641struct pci_bus * __devinit pci_scan_bus_on_node(int busno, struct pci_ops *ops, int node)
641{ 642{
643 LIST_HEAD(resources);
642 struct pci_bus *bus = NULL; 644 struct pci_bus *bus = NULL;
643 struct pci_sysdata *sd; 645 struct pci_sysdata *sd;
644 646
@@ -653,9 +655,12 @@ struct pci_bus * __devinit pci_scan_bus_on_node(int busno, struct pci_ops *ops,
653 return NULL; 655 return NULL;
654 } 656 }
655 sd->node = node; 657 sd->node = node;
656 bus = pci_scan_bus(busno, ops, sd); 658 x86_pci_root_bus_resources(busno, &resources);
657 if (!bus) 659 bus = pci_scan_root_bus(NULL, busno, ops, sd, &resources);
660 if (!bus) {
661 pci_free_resource_list(&resources);
658 kfree(sd); 662 kfree(sd);
663 }
659 664
660 return bus; 665 return bus;
661} 666}