aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2012-04-30 18:55:58 -0400
committerBjorn Helgaas <bhelgaas@google.com>2012-04-30 18:55:58 -0400
commit29473ec23aa79d401ffe06ec3f3ad3755382be13 (patch)
tree67b136cee8c5f407db94a73cb950ca421fba5759
parent977f857ca566a1e68045fcbb7cfc9c4acb077cf0 (diff)
parentc57ca65a6ea3171370cbb3010e5a3aea7399a5e1 (diff)
Merge branch 'topic/yinghai-hostbridge-cleanup' into next
-rw-r--r--arch/x86/pci/acpi.c116
-rw-r--r--arch/x86/pci/amd_bus.c76
-rw-r--r--arch/x86/pci/broadcom_bus.c12
-rw-r--r--arch/x86/pci/bus_numa.c69
-rw-r--r--arch/x86/pci/bus_numa.h18
-rw-r--r--arch/x86/pci/common.c27
-rw-r--r--drivers/pci/Makefile2
-rw-r--r--drivers/pci/host-bridge.c96
-rw-r--r--drivers/pci/probe.c146
-rw-r--r--include/linux/pci.h9
10 files changed, 304 insertions, 267 deletions
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index ed2835e148b5..8a17b23f8c84 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -9,11 +9,11 @@
9 9
10struct pci_root_info { 10struct pci_root_info {
11 struct acpi_device *bridge; 11 struct acpi_device *bridge;
12 char *name; 12 char name[16];
13 unsigned int res_num; 13 unsigned int res_num;
14 struct resource *res; 14 struct resource *res;
15 struct list_head *resources;
16 int busnum; 15 int busnum;
16 struct pci_sysdata sd;
17}; 17};
18 18
19static bool pci_use_crs = true; 19static bool pci_use_crs = true;
@@ -287,7 +287,8 @@ static void coalesce_windows(struct pci_root_info *info, unsigned long type)
287 } 287 }
288} 288}
289 289
290static void add_resources(struct pci_root_info *info) 290static void add_resources(struct pci_root_info *info,
291 struct list_head *resources)
291{ 292{
292 int i; 293 int i;
293 struct resource *res, *root, *conflict; 294 struct resource *res, *root, *conflict;
@@ -311,53 +312,74 @@ static void add_resources(struct pci_root_info *info)
311 "ignoring host bridge window %pR (conflicts with %s %pR)\n", 312 "ignoring host bridge window %pR (conflicts with %s %pR)\n",
312 res, conflict->name, conflict); 313 res, conflict->name, conflict);
313 else 314 else
314 pci_add_resource(info->resources, res); 315 pci_add_resource(resources, res);
315 } 316 }
316} 317}
317 318
319static void free_pci_root_info_res(struct pci_root_info *info)
320{
321 kfree(info->res);
322 info->res = NULL;
323 info->res_num = 0;
324}
325
326static void __release_pci_root_info(struct pci_root_info *info)
327{
328 int i;
329 struct resource *res;
330
331 for (i = 0; i < info->res_num; i++) {
332 res = &info->res[i];
333
334 if (!res->parent)
335 continue;
336
337 if (!(res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
338 continue;
339
340 release_resource(res);
341 }
342
343 free_pci_root_info_res(info);
344
345 kfree(info);
346}
347static void release_pci_root_info(struct pci_host_bridge *bridge)
348{
349 struct pci_root_info *info = bridge->release_data;
350
351 __release_pci_root_info(info);
352}
353
318static void 354static void
319get_current_resources(struct acpi_device *device, int busnum, 355probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
320 int domain, struct list_head *resources) 356 int busnum, int domain)
321{ 357{
322 struct pci_root_info info;
323 size_t size; 358 size_t size;
324 359
325 info.bridge = device; 360 info->bridge = device;
326 info.res_num = 0; 361 info->res_num = 0;
327 info.resources = resources;
328 acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource, 362 acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource,
329 &info); 363 info);
330 if (!info.res_num) 364 if (!info->res_num)
331 return; 365 return;
332 366
333 size = sizeof(*info.res) * info.res_num; 367 size = sizeof(*info->res) * info->res_num;
334 info.res = kmalloc(size, GFP_KERNEL); 368 info->res_num = 0;
335 if (!info.res) 369 info->res = kmalloc(size, GFP_KERNEL);
370 if (!info->res)
336 return; 371 return;
337 372
338 info.name = kasprintf(GFP_KERNEL, "PCI Bus %04x:%02x", domain, busnum); 373 sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum);
339 if (!info.name)
340 goto name_alloc_fail;
341 374
342 info.res_num = 0;
343 acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource, 375 acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
344 &info); 376 info);
345
346 if (pci_use_crs) {
347 add_resources(&info);
348
349 return;
350 }
351
352 kfree(info.name);
353
354name_alloc_fail:
355 kfree(info.res);
356} 377}
357 378
358struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root) 379struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
359{ 380{
360 struct acpi_device *device = root->device; 381 struct acpi_device *device = root->device;
382 struct pci_root_info *info = NULL;
361 int domain = root->segment; 383 int domain = root->segment;
362 int busnum = root->secondary.start; 384 int busnum = root->secondary.start;
363 LIST_HEAD(resources); 385 LIST_HEAD(resources);
@@ -389,17 +411,14 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
389 if (node != -1 && !node_online(node)) 411 if (node != -1 && !node_online(node))
390 node = -1; 412 node = -1;
391 413
392 /* Allocate per-root-bus (not per bus) arch-specific data. 414 info = kzalloc(sizeof(*info), GFP_KERNEL);
393 * TODO: leak; this memory is never freed. 415 if (!info) {
394 * It's arguable whether it's worth the trouble to care.
395 */
396 sd = kzalloc(sizeof(*sd), GFP_KERNEL);
397 if (!sd) {
398 printk(KERN_WARNING "pci_bus %04x:%02x: " 416 printk(KERN_WARNING "pci_bus %04x:%02x: "
399 "ignored (out of memory)\n", domain, busnum); 417 "ignored (out of memory)\n", domain, busnum);
400 return NULL; 418 return NULL;
401 } 419 }
402 420
421 sd = &info->sd;
403 sd->domain = domain; 422 sd->domain = domain;
404 sd->node = node; 423 sd->node = node;
405 /* 424 /*
@@ -413,22 +432,32 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
413 * be replaced by sd. 432 * be replaced by sd.
414 */ 433 */
415 memcpy(bus->sysdata, sd, sizeof(*sd)); 434 memcpy(bus->sysdata, sd, sizeof(*sd));
416 kfree(sd); 435 kfree(info);
417 } else { 436 } else {
418 get_current_resources(device, busnum, domain, &resources); 437 probe_pci_root_info(info, device, busnum, domain);
419 438
420 /* 439 /*
421 * _CRS with no apertures is normal, so only fall back to 440 * _CRS with no apertures is normal, so only fall back to
422 * defaults or native bridge info if we're ignoring _CRS. 441 * defaults or native bridge info if we're ignoring _CRS.
423 */ 442 */
424 if (!pci_use_crs) 443 if (pci_use_crs)
444 add_resources(info, &resources);
445 else {
446 free_pci_root_info_res(info);
425 x86_pci_root_bus_resources(busnum, &resources); 447 x86_pci_root_bus_resources(busnum, &resources);
448 }
449
426 bus = pci_create_root_bus(NULL, busnum, &pci_root_ops, sd, 450 bus = pci_create_root_bus(NULL, busnum, &pci_root_ops, sd,
427 &resources); 451 &resources);
428 if (bus) 452 if (bus) {
429 bus->subordinate = pci_scan_child_bus(bus); 453 bus->subordinate = pci_scan_child_bus(bus);
430 else 454 pci_set_host_bridge_release(
455 to_pci_host_bridge(bus->bridge),
456 release_pci_root_info, info);
457 } else {
431 pci_free_resource_list(&resources); 458 pci_free_resource_list(&resources);
459 __release_pci_root_info(info);
460 }
432 } 461 }
433 462
434 /* After the PCI-E bus has been walked and all devices discovered, 463 /* After the PCI-E bus has been walked and all devices discovered,
@@ -445,9 +474,6 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
445 } 474 }
446 } 475 }
447 476
448 if (!bus)
449 kfree(sd);
450
451 if (bus && node != -1) { 477 if (bus && node != -1) {
452#ifdef CONFIG_ACPI_NUMA 478#ifdef CONFIG_ACPI_NUMA
453 if (pxm >= 0) 479 if (pxm >= 0)
diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c
index 0567df3890e1..459a7316375c 100644
--- a/arch/x86/pci/amd_bus.c
+++ b/arch/x86/pci/amd_bus.c
@@ -32,6 +32,18 @@ static struct pci_hostbridge_probe pci_probes[] __initdata = {
32 32
33#define RANGE_NUM 16 33#define RANGE_NUM 16
34 34
35static struct pci_root_info __init *find_pci_root_info(int node, int link)
36{
37 struct pci_root_info *info;
38
39 /* find the position */
40 list_for_each_entry(info, &pci_root_infos, list)
41 if (info->node == node && info->link == link)
42 return info;
43
44 return NULL;
45}
46
35/** 47/**
36 * early_fill_mp_bus_to_node() 48 * early_fill_mp_bus_to_node()
37 * called before pcibios_scan_root and pci_scan_bus 49 * called before pcibios_scan_root and pci_scan_bus
@@ -50,7 +62,6 @@ static int __init early_fill_mp_bus_info(void)
50 int def_link; 62 int def_link;
51 struct pci_root_info *info; 63 struct pci_root_info *info;
52 u32 reg; 64 u32 reg;
53 struct resource *res;
54 u64 start; 65 u64 start;
55 u64 end; 66 u64 end;
56 struct range range[RANGE_NUM]; 67 struct range range[RANGE_NUM];
@@ -86,7 +97,6 @@ static int __init early_fill_mp_bus_info(void)
86 if (!found) 97 if (!found)
87 return 0; 98 return 0;
88 99
89 pci_root_num = 0;
90 for (i = 0; i < 4; i++) { 100 for (i = 0; i < 4; i++) {
91 int min_bus; 101 int min_bus;
92 int max_bus; 102 int max_bus;
@@ -105,13 +115,8 @@ static int __init early_fill_mp_bus_info(void)
105#endif 115#endif
106 link = (reg >> 8) & 0x03; 116 link = (reg >> 8) & 0x03;
107 117
108 info = &pci_root_info[pci_root_num]; 118 info = alloc_pci_root_info(min_bus, max_bus, node, link);
109 info->bus_min = min_bus;
110 info->bus_max = max_bus;
111 info->node = node;
112 info->link = link;
113 sprintf(info->name, "PCI Bus #%02x", min_bus); 119 sprintf(info->name, "PCI Bus #%02x", min_bus);
114 pci_root_num++;
115 } 120 }
116 121
117 /* get the default node and link for left over res */ 122 /* get the default node and link for left over res */
@@ -134,16 +139,10 @@ static int __init early_fill_mp_bus_info(void)
134 link = (reg >> 4) & 0x03; 139 link = (reg >> 4) & 0x03;
135 end = (reg & 0xfff000) | 0xfff; 140 end = (reg & 0xfff000) | 0xfff;
136 141
137 /* find the position */ 142 info = find_pci_root_info(node, link);
138 for (j = 0; j < pci_root_num; j++) { 143 if (!info)
139 info = &pci_root_info[j];
140 if (info->node == node && info->link == link)
141 break;
142 }
143 if (j == pci_root_num)
144 continue; /* not found */ 144 continue; /* not found */
145 145
146 info = &pci_root_info[j];
147 printk(KERN_DEBUG "node %d link %d: io port [%llx, %llx]\n", 146 printk(KERN_DEBUG "node %d link %d: io port [%llx, %llx]\n",
148 node, link, start, end); 147 node, link, start, end);
149 148
@@ -155,13 +154,8 @@ static int __init early_fill_mp_bus_info(void)
155 } 154 }
156 /* add left over io port range to def node/link, [0, 0xffff] */ 155 /* add left over io port range to def node/link, [0, 0xffff] */
157 /* find the position */ 156 /* find the position */
158 for (j = 0; j < pci_root_num; j++) { 157 info = find_pci_root_info(def_node, def_link);
159 info = &pci_root_info[j]; 158 if (info) {
160 if (info->node == def_node && info->link == def_link)
161 break;
162 }
163 if (j < pci_root_num) {
164 info = &pci_root_info[j];
165 for (i = 0; i < RANGE_NUM; i++) { 159 for (i = 0; i < RANGE_NUM; i++) {
166 if (!range[i].end) 160 if (!range[i].end)
167 continue; 161 continue;
@@ -214,16 +208,10 @@ static int __init early_fill_mp_bus_info(void)
214 end <<= 8; 208 end <<= 8;
215 end |= 0xffff; 209 end |= 0xffff;
216 210
217 /* find the position */ 211 info = find_pci_root_info(node, link);
218 for (j = 0; j < pci_root_num; j++) {
219 info = &pci_root_info[j];
220 if (info->node == node && info->link == link)
221 break;
222 }
223 if (j == pci_root_num)
224 continue; /* not found */
225 212
226 info = &pci_root_info[j]; 213 if (!info)
214 continue;
227 215
228 printk(KERN_DEBUG "node %d link %d: mmio [%llx, %llx]", 216 printk(KERN_DEBUG "node %d link %d: mmio [%llx, %llx]",
229 node, link, start, end); 217 node, link, start, end);
@@ -291,14 +279,8 @@ static int __init early_fill_mp_bus_info(void)
291 * add left over mmio range to def node/link ? 279 * add left over mmio range to def node/link ?
292 * that is tricky, just record range in from start_min to 4G 280 * that is tricky, just record range in from start_min to 4G
293 */ 281 */
294 for (j = 0; j < pci_root_num; j++) { 282 info = find_pci_root_info(def_node, def_link);
295 info = &pci_root_info[j]; 283 if (info) {
296 if (info->node == def_node && info->link == def_link)
297 break;
298 }
299 if (j < pci_root_num) {
300 info = &pci_root_info[j];
301
302 for (i = 0; i < RANGE_NUM; i++) { 284 for (i = 0; i < RANGE_NUM; i++) {
303 if (!range[i].end) 285 if (!range[i].end)
304 continue; 286 continue;
@@ -309,20 +291,16 @@ static int __init early_fill_mp_bus_info(void)
309 } 291 }
310 } 292 }
311 293
312 for (i = 0; i < pci_root_num; i++) { 294 list_for_each_entry(info, &pci_root_infos, list) {
313 int res_num;
314 int busnum; 295 int busnum;
296 struct pci_root_res *root_res;
315 297
316 info = &pci_root_info[i];
317 res_num = info->res_num;
318 busnum = info->bus_min; 298 busnum = info->bus_min;
319 printk(KERN_DEBUG "bus: [%02x, %02x] on node %x link %x\n", 299 printk(KERN_DEBUG "bus: [%02x, %02x] on node %x link %x\n",
320 info->bus_min, info->bus_max, info->node, info->link); 300 info->bus_min, info->bus_max, info->node, info->link);
321 for (j = 0; j < res_num; j++) { 301 list_for_each_entry(root_res, &info->resources, list)
322 res = &info->res[j]; 302 printk(KERN_DEBUG "bus: %02x %pR\n",
323 printk(KERN_DEBUG "bus: %02x index %x %pR\n", 303 busnum, &root_res->res);
324 busnum, j, res);
325 }
326 } 304 }
327 305
328 return 0; 306 return 0;
diff --git a/arch/x86/pci/broadcom_bus.c b/arch/x86/pci/broadcom_bus.c
index f3a7c569a403..614392ced7d6 100644
--- a/arch/x86/pci/broadcom_bus.c
+++ b/arch/x86/pci/broadcom_bus.c
@@ -22,19 +22,15 @@
22static void __init cnb20le_res(u8 bus, u8 slot, u8 func) 22static void __init cnb20le_res(u8 bus, u8 slot, u8 func)
23{ 23{
24 struct pci_root_info *info; 24 struct pci_root_info *info;
25 struct pci_root_res *root_res;
25 struct resource res; 26 struct resource res;
26 u16 word1, word2; 27 u16 word1, word2;
27 u8 fbus, lbus; 28 u8 fbus, lbus;
28 int i;
29
30 info = &pci_root_info[pci_root_num];
31 pci_root_num++;
32 29
33 /* read the PCI bus numbers */ 30 /* read the PCI bus numbers */
34 fbus = read_pci_config_byte(bus, slot, func, 0x44); 31 fbus = read_pci_config_byte(bus, slot, func, 0x44);
35 lbus = read_pci_config_byte(bus, slot, func, 0x45); 32 lbus = read_pci_config_byte(bus, slot, func, 0x45);
36 info->bus_min = fbus; 33 info = alloc_pci_root_info(fbus, lbus, 0, 0);
37 info->bus_max = lbus;
38 34
39 /* 35 /*
40 * Add the legacy IDE ports on bus 0 36 * Add the legacy IDE ports on bus 0
@@ -86,8 +82,8 @@ static void __init cnb20le_res(u8 bus, u8 slot, u8 func)
86 res.flags = IORESOURCE_BUS; 82 res.flags = IORESOURCE_BUS;
87 printk(KERN_INFO "CNB20LE PCI Host Bridge (domain 0000 %pR)\n", &res); 83 printk(KERN_INFO "CNB20LE PCI Host Bridge (domain 0000 %pR)\n", &res);
88 84
89 for (i = 0; i < info->res_num; i++) 85 list_for_each_entry(root_res, &info->resources, list)
90 printk(KERN_INFO "host bridge window %pR\n", &info->res[i]); 86 printk(KERN_INFO "host bridge window %pR\n", &root_res->res);
91} 87}
92 88
93static int __init broadcom_postcore_init(void) 89static int __init broadcom_postcore_init(void)
diff --git a/arch/x86/pci/bus_numa.c b/arch/x86/pci/bus_numa.c
index fd3f65510e9d..306579f7d0fd 100644
--- a/arch/x86/pci/bus_numa.c
+++ b/arch/x86/pci/bus_numa.c
@@ -4,35 +4,38 @@
4 4
5#include "bus_numa.h" 5#include "bus_numa.h"
6 6
7int pci_root_num; 7LIST_HEAD(pci_root_infos);
8struct pci_root_info pci_root_info[PCI_ROOT_NR];
9 8
10void x86_pci_root_bus_resources(int bus, struct list_head *resources) 9static struct pci_root_info *x86_find_pci_root_info(int bus)
11{ 10{
12 int i;
13 int j;
14 struct pci_root_info *info; 11 struct pci_root_info *info;
15 12
16 if (!pci_root_num) 13 if (list_empty(&pci_root_infos))
17 goto default_resources; 14 return NULL;
18 15
19 for (i = 0; i < pci_root_num; i++) { 16 list_for_each_entry(info, &pci_root_infos, list)
20 if (pci_root_info[i].bus_min == bus) 17 if (info->bus_min == bus)
21 break; 18 return info;
22 } 19
20 return NULL;
21}
23 22
24 if (i == pci_root_num) 23void x86_pci_root_bus_resources(int bus, struct list_head *resources)
24{
25 struct pci_root_info *info = x86_find_pci_root_info(bus);
26 struct pci_root_res *root_res;
27
28 if (!info)
25 goto default_resources; 29 goto default_resources;
26 30
27 printk(KERN_DEBUG "PCI: root bus %02x: hardware-probed resources\n", 31 printk(KERN_DEBUG "PCI: root bus %02x: hardware-probed resources\n",
28 bus); 32 bus);
29 33
30 info = &pci_root_info[i]; 34 list_for_each_entry(root_res, &info->resources, list) {
31 for (j = 0; j < info->res_num; j++) {
32 struct resource *res; 35 struct resource *res;
33 struct resource *root; 36 struct resource *root;
34 37
35 res = &info->res[j]; 38 res = &root_res->res;
36 pci_add_resource(resources, res); 39 pci_add_resource(resources, res);
37 if (res->flags & IORESOURCE_IO) 40 if (res->flags & IORESOURCE_IO)
38 root = &ioport_resource; 41 root = &ioport_resource;
@@ -53,11 +56,32 @@ default_resources:
53 pci_add_resource(resources, &iomem_resource); 56 pci_add_resource(resources, &iomem_resource);
54} 57}
55 58
59struct pci_root_info __init *alloc_pci_root_info(int bus_min, int bus_max,
60 int node, int link)
61{
62 struct pci_root_info *info;
63
64 info = kzalloc(sizeof(*info), GFP_KERNEL);
65
66 if (!info)
67 return info;
68
69 INIT_LIST_HEAD(&info->resources);
70 info->bus_min = bus_min;
71 info->bus_max = bus_max;
72 info->node = node;
73 info->link = link;
74
75 list_add_tail(&info->list, &pci_root_infos);
76
77 return info;
78}
79
56void __devinit update_res(struct pci_root_info *info, resource_size_t start, 80void __devinit update_res(struct pci_root_info *info, resource_size_t start,
57 resource_size_t end, unsigned long flags, int merge) 81 resource_size_t end, unsigned long flags, int merge)
58{ 82{
59 int i;
60 struct resource *res; 83 struct resource *res;
84 struct pci_root_res *root_res;
61 85
62 if (start > end) 86 if (start > end)
63 return; 87 return;
@@ -69,11 +93,11 @@ void __devinit update_res(struct pci_root_info *info, resource_size_t start,
69 goto addit; 93 goto addit;
70 94
71 /* try to merge it with old one */ 95 /* try to merge it with old one */
72 for (i = 0; i < info->res_num; i++) { 96 list_for_each_entry(root_res, &info->resources, list) {
73 resource_size_t final_start, final_end; 97 resource_size_t final_start, final_end;
74 resource_size_t common_start, common_end; 98 resource_size_t common_start, common_end;
75 99
76 res = &info->res[i]; 100 res = &root_res->res;
77 if (res->flags != flags) 101 if (res->flags != flags)
78 continue; 102 continue;
79 103
@@ -93,14 +117,15 @@ void __devinit update_res(struct pci_root_info *info, resource_size_t start,
93addit: 117addit:
94 118
95 /* need to add that */ 119 /* need to add that */
96 if (info->res_num >= RES_NUM) 120 root_res = kzalloc(sizeof(*root_res), GFP_KERNEL);
121 if (!root_res)
97 return; 122 return;
98 123
99 res = &info->res[info->res_num]; 124 res = &root_res->res;
100 res->name = info->name; 125 res->name = info->name;
101 res->flags = flags; 126 res->flags = flags;
102 res->start = start; 127 res->start = start;
103 res->end = end; 128 res->end = end;
104 res->child = NULL; 129
105 info->res_num++; 130 list_add_tail(&root_res->list, &info->resources);
106} 131}
diff --git a/arch/x86/pci/bus_numa.h b/arch/x86/pci/bus_numa.h
index 804a4b40c31a..226a466b2b2b 100644
--- a/arch/x86/pci/bus_numa.h
+++ b/arch/x86/pci/bus_numa.h
@@ -4,22 +4,24 @@
4 * sub bus (transparent) will use entres from 3 to store extra from 4 * sub bus (transparent) will use entres from 3 to store extra from
5 * root, so need to make sure we have enough slot there. 5 * root, so need to make sure we have enough slot there.
6 */ 6 */
7#define RES_NUM 16 7struct pci_root_res {
8 struct list_head list;
9 struct resource res;
10};
11
8struct pci_root_info { 12struct pci_root_info {
13 struct list_head list;
9 char name[12]; 14 char name[12];
10 unsigned int res_num; 15 struct list_head resources;
11 struct resource res[RES_NUM];
12 int bus_min; 16 int bus_min;
13 int bus_max; 17 int bus_max;
14 int node; 18 int node;
15 int link; 19 int link;
16}; 20};
17 21
18/* 4 at this time, it may become to 32 */ 22extern struct list_head pci_root_infos;
19#define PCI_ROOT_NR 4 23struct pci_root_info *alloc_pci_root_info(int bus_min, int bus_max,
20extern int pci_root_num; 24 int node, int link);
21extern struct pci_root_info pci_root_info[PCI_ROOT_NR];
22
23extern void update_res(struct pci_root_info *info, resource_size_t start, 25extern void update_res(struct pci_root_info *info, resource_size_t start,
24 resource_size_t end, unsigned long flags, int merge); 26 resource_size_t end, unsigned long flags, int merge);
25#endif 27#endif
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 323481e06ef8..8e04ec591543 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -430,9 +430,7 @@ void __init dmi_check_pciprobe(void)
430 430
431struct pci_bus * __devinit pcibios_scan_root(int busnum) 431struct pci_bus * __devinit pcibios_scan_root(int busnum)
432{ 432{
433 LIST_HEAD(resources);
434 struct pci_bus *bus = NULL; 433 struct pci_bus *bus = NULL;
435 struct pci_sysdata *sd;
436 434
437 while ((bus = pci_find_next_bus(bus)) != NULL) { 435 while ((bus = pci_find_next_bus(bus)) != NULL) {
438 if (bus->number == busnum) { 436 if (bus->number == busnum) {
@@ -441,28 +439,10 @@ struct pci_bus * __devinit pcibios_scan_root(int busnum)
441 } 439 }
442 } 440 }
443 441
444 /* Allocate per-root-bus (not per bus) arch-specific data. 442 return pci_scan_bus_on_node(busnum, &pci_root_ops,
445 * TODO: leak; this memory is never freed. 443 get_mp_bus_to_node(busnum));
446 * It's arguable whether it's worth the trouble to care.
447 */
448 sd = kzalloc(sizeof(*sd), GFP_KERNEL);
449 if (!sd) {
450 printk(KERN_ERR "PCI: OOM, not probing PCI bus %02x\n", busnum);
451 return NULL;
452 }
453
454 sd->node = get_mp_bus_to_node(busnum);
455
456 printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busnum);
457 x86_pci_root_bus_resources(busnum, &resources);
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);
462 }
463
464 return bus;
465} 444}
445
466void __init pcibios_set_cache_line_size(void) 446void __init pcibios_set_cache_line_size(void)
467{ 447{
468 struct cpuinfo_x86 *c = &boot_cpu_data; 448 struct cpuinfo_x86 *c = &boot_cpu_data;
@@ -656,6 +636,7 @@ struct pci_bus * __devinit pci_scan_bus_on_node(int busno, struct pci_ops *ops,
656 } 636 }
657 sd->node = node; 637 sd->node = node;
658 x86_pci_root_bus_resources(busno, &resources); 638 x86_pci_root_bus_resources(busno, &resources);
639 printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busno);
659 bus = pci_scan_root_bus(NULL, busno, ops, sd, &resources); 640 bus = pci_scan_root_bus(NULL, busno, ops, sd, &resources);
660 if (!bus) { 641 if (!bus) {
661 pci_free_resource_list(&resources); 642 pci_free_resource_list(&resources);
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 083a49fee56a..2c224edae1ac 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -2,7 +2,7 @@
2# Makefile for the PCI bus specific drivers. 2# Makefile for the PCI bus specific drivers.
3# 3#
4 4
5obj-y += access.o bus.o probe.o remove.o pci.o \ 5obj-y += access.o bus.o probe.o host-bridge.o remove.o pci.o \
6 pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \ 6 pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \
7 irq.o vpd.o 7 irq.o vpd.o
8obj-$(CONFIG_PROC_FS) += proc.o 8obj-$(CONFIG_PROC_FS) += proc.o
diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
new file mode 100644
index 000000000000..a68dc613a5be
--- /dev/null
+++ b/drivers/pci/host-bridge.c
@@ -0,0 +1,96 @@
1/*
2 * host bridge related code
3 */
4
5#include <linux/kernel.h>
6#include <linux/init.h>
7#include <linux/pci.h>
8#include <linux/module.h>
9
10#include "pci.h"
11
12static struct pci_bus *find_pci_root_bus(struct pci_dev *dev)
13{
14 struct pci_bus *bus;
15
16 bus = dev->bus;
17 while (bus->parent)
18 bus = bus->parent;
19
20 return bus;
21}
22
23static struct pci_host_bridge *find_pci_host_bridge(struct pci_dev *dev)
24{
25 struct pci_bus *bus = find_pci_root_bus(dev);
26
27 return to_pci_host_bridge(bus->bridge);
28}
29
30void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
31 void (*release_fn)(struct pci_host_bridge *),
32 void *release_data)
33{
34 bridge->release_fn = release_fn;
35 bridge->release_data = release_data;
36}
37
38static bool resource_contains(struct resource *res1, struct resource *res2)
39{
40 return res1->start <= res2->start && res1->end >= res2->end;
41}
42
43void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
44 struct resource *res)
45{
46 struct pci_host_bridge *bridge = find_pci_host_bridge(dev);
47 struct pci_host_bridge_window *window;
48 resource_size_t offset = 0;
49
50 list_for_each_entry(window, &bridge->windows, list) {
51 if (resource_type(res) != resource_type(window->res))
52 continue;
53
54 if (resource_contains(window->res, res)) {
55 offset = window->offset;
56 break;
57 }
58 }
59
60 region->start = res->start - offset;
61 region->end = res->end - offset;
62}
63EXPORT_SYMBOL(pcibios_resource_to_bus);
64
65static bool region_contains(struct pci_bus_region *region1,
66 struct pci_bus_region *region2)
67{
68 return region1->start <= region2->start && region1->end >= region2->end;
69}
70
71void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
72 struct pci_bus_region *region)
73{
74 struct pci_host_bridge *bridge = find_pci_host_bridge(dev);
75 struct pci_host_bridge_window *window;
76 resource_size_t offset = 0;
77
78 list_for_each_entry(window, &bridge->windows, list) {
79 struct pci_bus_region bus_region;
80
81 if (resource_type(res) != resource_type(window->res))
82 continue;
83
84 bus_region.start = window->res->start - window->offset;
85 bus_region.end = window->res->end - window->offset;
86
87 if (region_contains(&bus_region, region)) {
88 offset = window->offset;
89 break;
90 }
91 }
92
93 res->start = region->start + offset;
94 res->end = region->end + offset;
95}
96EXPORT_SYMBOL(pcibios_bus_to_resource);
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 5e1ca3c58a7d..4c2f22668ea7 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -15,13 +15,10 @@
15#define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */ 15#define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */
16#define CARDBUS_RESERVE_BUSNR 3 16#define CARDBUS_RESERVE_BUSNR 3
17 17
18static LIST_HEAD(pci_host_bridges);
19
20/* Ugh. Need to stop exporting this to modules. */ 18/* Ugh. Need to stop exporting this to modules. */
21LIST_HEAD(pci_root_buses); 19LIST_HEAD(pci_root_buses);
22EXPORT_SYMBOL(pci_root_buses); 20EXPORT_SYMBOL(pci_root_buses);
23 21
24
25static int find_anything(struct device *dev, void *data) 22static int find_anything(struct device *dev, void *data)
26{ 23{
27 return 1; 24 return 1;
@@ -44,82 +41,6 @@ int no_pci_devices(void)
44} 41}
45EXPORT_SYMBOL(no_pci_devices); 42EXPORT_SYMBOL(no_pci_devices);
46 43
47static struct pci_host_bridge *pci_host_bridge(struct pci_dev *dev)
48{
49 struct pci_bus *bus;
50 struct pci_host_bridge *bridge;
51
52 bus = dev->bus;
53 while (bus->parent)
54 bus = bus->parent;
55
56 list_for_each_entry(bridge, &pci_host_bridges, list) {
57 if (bridge->bus == bus)
58 return bridge;
59 }
60
61 return NULL;
62}
63
64static bool resource_contains(struct resource *res1, struct resource *res2)
65{
66 return res1->start <= res2->start && res1->end >= res2->end;
67}
68
69void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
70 struct resource *res)
71{
72 struct pci_host_bridge *bridge = pci_host_bridge(dev);
73 struct pci_host_bridge_window *window;
74 resource_size_t offset = 0;
75
76 list_for_each_entry(window, &bridge->windows, list) {
77 if (resource_type(res) != resource_type(window->res))
78 continue;
79
80 if (resource_contains(window->res, res)) {
81 offset = window->offset;
82 break;
83 }
84 }
85
86 region->start = res->start - offset;
87 region->end = res->end - offset;
88}
89EXPORT_SYMBOL(pcibios_resource_to_bus);
90
91static bool region_contains(struct pci_bus_region *region1,
92 struct pci_bus_region *region2)
93{
94 return region1->start <= region2->start && region1->end >= region2->end;
95}
96
97void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
98 struct pci_bus_region *region)
99{
100 struct pci_host_bridge *bridge = pci_host_bridge(dev);
101 struct pci_host_bridge_window *window;
102 struct pci_bus_region bus_region;
103 resource_size_t offset = 0;
104
105 list_for_each_entry(window, &bridge->windows, list) {
106 if (resource_type(res) != resource_type(window->res))
107 continue;
108
109 bus_region.start = window->res->start - window->offset;
110 bus_region.end = window->res->end - window->offset;
111
112 if (region_contains(&bus_region, region)) {
113 offset = window->offset;
114 break;
115 }
116 }
117
118 res->start = region->start + offset;
119 res->end = region->end + offset;
120}
121EXPORT_SYMBOL(pcibios_bus_to_resource);
122
123/* 44/*
124 * PCI Bus Class 45 * PCI Bus Class
125 */ 46 */
@@ -501,6 +422,19 @@ static struct pci_bus * pci_alloc_bus(void)
501 return b; 422 return b;
502} 423}
503 424
425static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b)
426{
427 struct pci_host_bridge *bridge;
428
429 bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
430 if (bridge) {
431 INIT_LIST_HEAD(&bridge->windows);
432 bridge->bus = b;
433 }
434
435 return bridge;
436}
437
504static unsigned char pcix_bus_speed[] = { 438static unsigned char pcix_bus_speed[] = {
505 PCI_SPEED_UNKNOWN, /* 0 */ 439 PCI_SPEED_UNKNOWN, /* 0 */
506 PCI_SPEED_66MHz_PCIX, /* 1 */ 440 PCI_SPEED_66MHz_PCIX, /* 1 */
@@ -1201,7 +1135,14 @@ int pci_cfg_space_size(struct pci_dev *dev)
1201 1135
1202static void pci_release_bus_bridge_dev(struct device *dev) 1136static void pci_release_bus_bridge_dev(struct device *dev)
1203{ 1137{
1204 kfree(dev); 1138 struct pci_host_bridge *bridge = to_pci_host_bridge(dev);
1139
1140 if (bridge->release_fn)
1141 bridge->release_fn(bridge);
1142
1143 pci_free_resource_list(&bridge->windows);
1144
1145 kfree(bridge);
1205} 1146}
1206 1147
1207struct pci_dev *alloc_pci_dev(void) 1148struct pci_dev *alloc_pci_dev(void)
@@ -1650,28 +1591,19 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
1650 int error; 1591 int error;
1651 struct pci_host_bridge *bridge; 1592 struct pci_host_bridge *bridge;
1652 struct pci_bus *b, *b2; 1593 struct pci_bus *b, *b2;
1653 struct device *dev;
1654 struct pci_host_bridge_window *window, *n; 1594 struct pci_host_bridge_window *window, *n;
1655 struct resource *res; 1595 struct resource *res;
1656 resource_size_t offset; 1596 resource_size_t offset;
1657 char bus_addr[64]; 1597 char bus_addr[64];
1658 char *fmt; 1598 char *fmt;
1659 1599
1660 bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
1661 if (!bridge)
1662 return NULL;
1663 1600
1664 b = pci_alloc_bus(); 1601 b = pci_alloc_bus();
1665 if (!b) 1602 if (!b)
1666 goto err_bus; 1603 return NULL;
1667
1668 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
1669 if (!dev)
1670 goto err_dev;
1671 1604
1672 b->sysdata = sysdata; 1605 b->sysdata = sysdata;
1673 b->ops = ops; 1606 b->ops = ops;
1674
1675 b2 = pci_find_bus(pci_domain_nr(b), bus); 1607 b2 = pci_find_bus(pci_domain_nr(b), bus);
1676 if (b2) { 1608 if (b2) {
1677 /* If we already got to this bus through a different bridge, ignore it */ 1609 /* If we already got to this bus through a different bridge, ignore it */
@@ -1679,13 +1611,17 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
1679 goto err_out; 1611 goto err_out;
1680 } 1612 }
1681 1613
1682 dev->parent = parent; 1614 bridge = pci_alloc_host_bridge(b);
1683 dev->release = pci_release_bus_bridge_dev; 1615 if (!bridge)
1684 dev_set_name(dev, "pci%04x:%02x", pci_domain_nr(b), bus); 1616 goto err_out;
1685 error = device_register(dev); 1617
1618 bridge->dev.parent = parent;
1619 bridge->dev.release = pci_release_bus_bridge_dev;
1620 dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
1621 error = device_register(&bridge->dev);
1686 if (error) 1622 if (error)
1687 goto dev_reg_err; 1623 goto bridge_dev_reg_err;
1688 b->bridge = get_device(dev); 1624 b->bridge = get_device(&bridge->dev);
1689 device_enable_async_suspend(b->bridge); 1625 device_enable_async_suspend(b->bridge);
1690 pci_set_bus_of_node(b); 1626 pci_set_bus_of_node(b);
1691 1627
@@ -1704,9 +1640,6 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
1704 1640
1705 b->number = b->secondary = bus; 1641 b->number = b->secondary = bus;
1706 1642
1707 bridge->bus = b;
1708 INIT_LIST_HEAD(&bridge->windows);
1709
1710 if (parent) 1643 if (parent)
1711 dev_info(parent, "PCI host bridge to bus %s\n", dev_name(&b->dev)); 1644 dev_info(parent, "PCI host bridge to bus %s\n", dev_name(&b->dev));
1712 else 1645 else
@@ -1732,25 +1665,18 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
1732 } 1665 }
1733 1666
1734 down_write(&pci_bus_sem); 1667 down_write(&pci_bus_sem);
1735 list_add_tail(&bridge->list, &pci_host_bridges);
1736 list_add_tail(&b->node, &pci_root_buses); 1668 list_add_tail(&b->node, &pci_root_buses);
1737 up_write(&pci_bus_sem); 1669 up_write(&pci_bus_sem);
1738 1670
1739 return b; 1671 return b;
1740 1672
1741class_dev_reg_err: 1673class_dev_reg_err:
1742 device_unregister(dev); 1674 put_device(&bridge->dev);
1743dev_reg_err: 1675 device_unregister(&bridge->dev);
1744 down_write(&pci_bus_sem); 1676bridge_dev_reg_err:
1745 list_del(&bridge->list); 1677 kfree(bridge);
1746 list_del(&b->node);
1747 up_write(&pci_bus_sem);
1748err_out: 1678err_out:
1749 kfree(dev);
1750err_dev:
1751 kfree(b); 1679 kfree(b);
1752err_bus:
1753 kfree(bridge);
1754 return NULL; 1680 return NULL;
1755} 1681}
1756 1682
diff --git a/include/linux/pci.h b/include/linux/pci.h
index e444f5b49118..17b7b5b01b4a 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -375,11 +375,18 @@ struct pci_host_bridge_window {
375}; 375};
376 376
377struct pci_host_bridge { 377struct pci_host_bridge {
378 struct list_head list; 378 struct device dev;
379 struct pci_bus *bus; /* root bus */ 379 struct pci_bus *bus; /* root bus */
380 struct list_head windows; /* pci_host_bridge_windows */ 380 struct list_head windows; /* pci_host_bridge_windows */
381 void (*release_fn)(struct pci_host_bridge *);
382 void *release_data;
381}; 383};
382 384
385#define to_pci_host_bridge(n) container_of(n, struct pci_host_bridge, dev)
386void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
387 void (*release_fn)(struct pci_host_bridge *),
388 void *release_data);
389
383/* 390/*
384 * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond 391 * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond
385 * to P2P or CardBus bridge windows) go in a table. Additional ones (for 392 * to P2P or CardBus bridge windows) go in a table. Additional ones (for