diff options
Diffstat (limited to 'drivers/pci/probe.c')
-rw-r--r-- | drivers/pci/probe.c | 39 |
1 files changed, 37 insertions, 2 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 00ba6a03dca..3c9834d8085 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -433,7 +433,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, i; + u32 buses, i, j = 0; u16 bctl; pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses); @@ -543,10 +543,29 @@ 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. */ - for (i=0; i<CARDBUS_RESERVE_BUSNR; i++) + for (i=0; i<CARDBUS_RESERVE_BUSNR; i++) { + struct pci_bus *parent = bus; if (pci_find_bus(pci_domain_nr(bus), max+i+1)) break; + while (parent->parent) { + if ((!pcibios_assign_all_busses()) && + (parent->subordinate > max) && + (parent->subordinate <= max+i)) { + j = 1; + } + parent = parent->parent; + } + if (j) { + /* + * Often, there are two cardbus bridges + * -- try to leave one valid bus number + * for each one. + */ + i /= 2; + break; + } + } max += i; pci_fixup_parent_subordinate_busnr(child, max); } @@ -561,6 +580,22 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max sprintf(child->name, (is_cardbus ? "PCI CardBus #%02x" : "PCI Bus #%02x"), child->number); + while (bus->parent) { + if ((child->subordinate > bus->subordinate) || + (child->number > bus->subordinate) || + (child->number < bus->number) || + (child->subordinate < bus->number)) { + printk(KERN_WARNING "PCI: Bus #%02x (-#%02x) may be " + "hidden behind%s bridge #%02x (-#%02x)%s\n", + child->number, child->subordinate, + bus->self->transparent ? " transparent" : " ", + bus->number, bus->subordinate, + pcibios_assign_all_busses() ? " " : + " (try 'pci=assign-busses')"); + } + bus = bus->parent; + } + return max; } |