diff options
author | Yinghai Lu <yinghai@kernel.org> | 2012-09-17 22:24:29 -0700 |
---|---|---|
committer | Yinghai Lu <yinghai@kernel.org> | 2012-09-17 22:24:29 -0700 |
commit | cd13456afb1fe18c415198a85dcfe8473946c3b7 (patch) | |
tree | 0d0e0c24ac879cfc99e85fa846c763649b497b15 | |
parent | ecebadc678993ea2cc1c477d0234bbfa9b0edba1 (diff) | |
download | linux-yinghai-cd13456afb1fe18c415198a85dcfe8473946c3b7.tar.gz |
PCI: Strict checking of valid range for bridge
Children bridges busn range should be allocated from parent bus range.
So we could avoid overlapping between sibling bridges on same bus.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
-rw-r--r-- | drivers/pci/probe.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 2178ceed01ef3e..c07a025934ece3 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -939,6 +939,28 @@ static int __devinit pci_bridge_probe_busn_res(struct pci_bus *bus, return ret; } +static int __devinit pci_bridge_check_busn_broken(struct pci_bus *bus, + struct pci_dev *dev, + int secondary, int subordinate) +{ + int ret; + struct resource busn_res; + + memset(&busn_res, 0, sizeof(struct resource)); + dev_printk(KERN_DEBUG, &dev->dev, + "check if busn %02x-%02x is in busn_res: %pR\n", + secondary, subordinate, &bus->busn_res); + ret = allocate_resource(&bus->busn_res, &busn_res, + (subordinate - secondary + 1), + secondary, subordinate, + 1, NULL, NULL); + if (ret) + return 1; + + release_resource(&busn_res); + + return 0; +} /* * If it's a bridge, configure it and scan the bus behind it. * For CardBus bridges, we don't scan behind as the devices will @@ -977,6 +999,11 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, (primary != bus->number || secondary <= bus->number)) broken = 1; + /* more strict checking */ + if (!pass && !broken && !dev->subordinate) + broken = pci_bridge_check_busn_broken(bus, dev, + secondary, subordinate); + if (broken) dev_dbg(&dev->dev, "bus configuration invalid, reconfiguring\n"); |