aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/pci/probe.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 3dc00f0ca8a..6186f4d7b11 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -411,7 +411,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
{
struct pci_bus *child;
int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS);
- u32 buses;
+ u32 buses, i;
u16 bctl;
pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses);
@@ -470,6 +470,10 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
/* Clear errors */
pci_write_config_word(dev, PCI_STATUS, 0xffff);
+ /* Prevent assigning a bus number that already exists.
+ * This can happen when a bridge is hot-plugged */
+ if (pci_find_bus(pci_domain_nr(bus), max+1))
+ return max;
child = pci_alloc_child_bus(bus, dev, ++max);
buses = (buses & 0xff000000)
| ((unsigned int)(child->primary) << 0)
@@ -501,7 +505,11 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
* as cards with a PCI-to-PCI bridge can be
* inserted later.
*/
- max += CARDBUS_RESERVE_BUSNR;
+ for (i=0; i<CARDBUS_RESERVE_BUSNR; i++)
+ if (pci_find_bus(pci_domain_nr(bus),
+ max+i+1))
+ break;
+ max += i;
}
/*
* Set the subordinate bus number to its real value.