diff options
Diffstat (limited to 'drivers/pci/probe.c')
-rw-r--r-- | drivers/pci/probe.c | 53 |
1 files changed, 42 insertions, 11 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index fd48b201eb53..df3bdae2040f 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -239,9 +239,8 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) | |||
239 | 239 | ||
240 | if (dev->transparent) { | 240 | if (dev->transparent) { |
241 | printk(KERN_INFO "PCI: Transparent bridge - %s\n", pci_name(dev)); | 241 | printk(KERN_INFO "PCI: Transparent bridge - %s\n", pci_name(dev)); |
242 | for(i = 0; i < PCI_BUS_NUM_RESOURCES; i++) | 242 | for(i = 3; i < PCI_BUS_NUM_RESOURCES; i++) |
243 | child->resource[i] = child->parent->resource[i]; | 243 | child->resource[i] = child->parent->resource[i - 3]; |
244 | return; | ||
245 | } | 244 | } |
246 | 245 | ||
247 | for(i=0; i<3; i++) | 246 | for(i=0; i<3; i++) |
@@ -374,8 +373,11 @@ struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_de | |||
374 | struct pci_bus *child; | 373 | struct pci_bus *child; |
375 | 374 | ||
376 | child = pci_alloc_child_bus(parent, dev, busnr); | 375 | child = pci_alloc_child_bus(parent, dev, busnr); |
377 | if (child) | 376 | if (child) { |
377 | spin_lock(&pci_bus_lock); | ||
378 | list_add_tail(&child->node, &parent->children); | 378 | list_add_tail(&child->node, &parent->children); |
379 | spin_unlock(&pci_bus_lock); | ||
380 | } | ||
379 | return child; | 381 | return child; |
380 | } | 382 | } |
381 | 383 | ||
@@ -395,6 +397,16 @@ static void pci_enable_crs(struct pci_dev *dev) | |||
395 | pci_write_config_word(dev, rpcap + PCI_EXP_RTCTL, rpctl); | 397 | pci_write_config_word(dev, rpcap + PCI_EXP_RTCTL, rpctl); |
396 | } | 398 | } |
397 | 399 | ||
400 | static void __devinit pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max) | ||
401 | { | ||
402 | struct pci_bus *parent = child->parent; | ||
403 | while (parent->parent && parent->subordinate < max) { | ||
404 | parent->subordinate = max; | ||
405 | pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS, max); | ||
406 | parent = parent->parent; | ||
407 | } | ||
408 | } | ||
409 | |||
398 | unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus); | 410 | unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus); |
399 | 411 | ||
400 | /* | 412 | /* |
@@ -411,7 +423,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max | |||
411 | { | 423 | { |
412 | struct pci_bus *child; | 424 | struct pci_bus *child; |
413 | int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS); | 425 | int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS); |
414 | u32 buses; | 426 | u32 buses, i; |
415 | u16 bctl; | 427 | u16 bctl; |
416 | 428 | ||
417 | pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses); | 429 | pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses); |
@@ -447,7 +459,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max | |||
447 | return max; | 459 | return max; |
448 | } | 460 | } |
449 | 461 | ||
450 | child = pci_alloc_child_bus(bus, dev, busnr); | 462 | child = pci_add_new_bus(bus, dev, busnr); |
451 | if (!child) | 463 | if (!child) |
452 | return max; | 464 | return max; |
453 | child->primary = buses & 0xFF; | 465 | child->primary = buses & 0xFF; |
@@ -470,7 +482,11 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max | |||
470 | /* Clear errors */ | 482 | /* Clear errors */ |
471 | pci_write_config_word(dev, PCI_STATUS, 0xffff); | 483 | pci_write_config_word(dev, PCI_STATUS, 0xffff); |
472 | 484 | ||
473 | child = pci_alloc_child_bus(bus, dev, ++max); | 485 | /* Prevent assigning a bus number that already exists. |
486 | * This can happen when a bridge is hot-plugged */ | ||
487 | if (pci_find_bus(pci_domain_nr(bus), max+1)) | ||
488 | return max; | ||
489 | child = pci_add_new_bus(bus, dev, ++max); | ||
474 | buses = (buses & 0xff000000) | 490 | buses = (buses & 0xff000000) |
475 | | ((unsigned int)(child->primary) << 0) | 491 | | ((unsigned int)(child->primary) << 0) |
476 | | ((unsigned int)(child->secondary) << 8) | 492 | | ((unsigned int)(child->secondary) << 8) |
@@ -492,7 +508,13 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max | |||
492 | 508 | ||
493 | if (!is_cardbus) { | 509 | if (!is_cardbus) { |
494 | child->bridge_ctl = PCI_BRIDGE_CTL_NO_ISA; | 510 | child->bridge_ctl = PCI_BRIDGE_CTL_NO_ISA; |
495 | 511 | /* | |
512 | * Adjust subordinate busnr in parent buses. | ||
513 | * We do this before scanning for children because | ||
514 | * some devices may not be detected if the bios | ||
515 | * was lazy. | ||
516 | */ | ||
517 | pci_fixup_parent_subordinate_busnr(child, max); | ||
496 | /* Now we can scan all subordinate buses... */ | 518 | /* Now we can scan all subordinate buses... */ |
497 | max = pci_scan_child_bus(child); | 519 | max = pci_scan_child_bus(child); |
498 | } else { | 520 | } else { |
@@ -501,7 +523,12 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max | |||
501 | * as cards with a PCI-to-PCI bridge can be | 523 | * as cards with a PCI-to-PCI bridge can be |
502 | * inserted later. | 524 | * inserted later. |
503 | */ | 525 | */ |
504 | max += CARDBUS_RESERVE_BUSNR; | 526 | for (i=0; i<CARDBUS_RESERVE_BUSNR; i++) |
527 | if (pci_find_bus(pci_domain_nr(bus), | ||
528 | max+i+1)) | ||
529 | break; | ||
530 | max += i; | ||
531 | pci_fixup_parent_subordinate_busnr(child, max); | ||
505 | } | 532 | } |
506 | /* | 533 | /* |
507 | * Set the subordinate bus number to its real value. | 534 | * Set the subordinate bus number to its real value. |
@@ -757,7 +784,9 @@ pci_scan_single_device(struct pci_bus *bus, int devfn) | |||
757 | * and the bus list for fixup functions, etc. | 784 | * and the bus list for fixup functions, etc. |
758 | */ | 785 | */ |
759 | INIT_LIST_HEAD(&dev->global_list); | 786 | INIT_LIST_HEAD(&dev->global_list); |
787 | spin_lock(&pci_bus_lock); | ||
760 | list_add_tail(&dev->bus_list, &bus->devices); | 788 | list_add_tail(&dev->bus_list, &bus->devices); |
789 | spin_unlock(&pci_bus_lock); | ||
761 | 790 | ||
762 | return dev; | 791 | return dev; |
763 | } | 792 | } |
@@ -878,7 +907,9 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus, | |||
878 | pr_debug("PCI: Bus %04x:%02x already known\n", pci_domain_nr(b), bus); | 907 | pr_debug("PCI: Bus %04x:%02x already known\n", pci_domain_nr(b), bus); |
879 | goto err_out; | 908 | goto err_out; |
880 | } | 909 | } |
910 | spin_lock(&pci_bus_lock); | ||
881 | list_add_tail(&b->node, &pci_root_buses); | 911 | list_add_tail(&b->node, &pci_root_buses); |
912 | spin_unlock(&pci_bus_lock); | ||
882 | 913 | ||
883 | memset(dev, 0, sizeof(*dev)); | 914 | memset(dev, 0, sizeof(*dev)); |
884 | dev->parent = parent; | 915 | dev->parent = parent; |
@@ -911,8 +942,6 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus, | |||
911 | 942 | ||
912 | b->subordinate = pci_scan_child_bus(b); | 943 | b->subordinate = pci_scan_child_bus(b); |
913 | 944 | ||
914 | pci_bus_add_devices(b); | ||
915 | |||
916 | return b; | 945 | return b; |
917 | 946 | ||
918 | sys_create_link_err: | 947 | sys_create_link_err: |
@@ -922,7 +951,9 @@ class_dev_create_file_err: | |||
922 | class_dev_reg_err: | 951 | class_dev_reg_err: |
923 | device_unregister(dev); | 952 | device_unregister(dev); |
924 | dev_reg_err: | 953 | dev_reg_err: |
954 | spin_lock(&pci_bus_lock); | ||
925 | list_del(&b->node); | 955 | list_del(&b->node); |
956 | spin_unlock(&pci_bus_lock); | ||
926 | err_out: | 957 | err_out: |
927 | kfree(dev); | 958 | kfree(dev); |
928 | kfree(b); | 959 | kfree(b); |