diff options
Diffstat (limited to 'drivers/pci/probe.c')
-rw-r--r-- | drivers/pci/probe.c | 49 |
1 files changed, 44 insertions, 5 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index fce2cb2112d8..adfad4fd6a13 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -264,8 +264,10 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) if (base <= limit) { res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO; - res->start = base; - res->end = limit + 0xfff; + if (!res->start) + res->start = base; + if (!res->end) + res->end = limit + 0xfff; } res = child->resource[1]; @@ -431,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); @@ -541,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); } @@ -559,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; } @@ -571,6 +608,7 @@ static void pci_read_irq(struct pci_dev *dev) unsigned char irq; pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq); + dev->pin = irq; if (irq) pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); dev->irq = irq; @@ -624,6 +662,7 @@ static int pci_setup_device(struct pci_dev * dev) /* The PCI-to-PCI bridge spec requires that subtractive decoding (i.e. transparent) bridge must have programming interface code of 0x01. */ + pci_read_irq(dev); dev->transparent = ((dev->class & 0xff) == 1); pci_read_bases(dev, 2, PCI_ROM_ADDRESS1); break; @@ -678,7 +717,7 @@ static void pci_release_dev(struct device *dev) * reading the dword at 0x100 which must either be 0 or a valid extended * capability header. */ -static int pci_cfg_space_size(struct pci_dev *dev) +int pci_cfg_space_size(struct pci_dev *dev) { int pos; u32 status; |