mirror of https://gitee.com/openkylin/linux.git
Merge branch 'pci/scan-bridge' into next
* pci/scan-bridge: PCI: Don't scan random busses in pci_scan_bridge() PCI: Check for child busses which use more bus numbers than allocated PCI: Remove pci_fixup_parent_subordinate_busnr() PCI: Make sure bus number resources stay within their parents bounds PCI: Use request_resource_conflict() instead of insert_ for bus numbers PCI: Assign CardBus bus number only during the second pass PCI: Clarify the "scan anyway" comment in pci_scan_bridge() PCI: Increment max correctly in pci_scan_bridge()
This commit is contained in:
commit
25a712a49f
|
@ -731,22 +731,6 @@ struct pci_bus *__ref pci_add_new_bus(struct pci_bus *parent, struct pci_dev *de
|
|||
return child;
|
||||
}
|
||||
|
||||
static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
|
||||
{
|
||||
struct pci_bus *parent = child->parent;
|
||||
|
||||
/* Attempts to fix that up are really dangerous unless
|
||||
we're going to re-assign all bus numbers. */
|
||||
if (!pcibios_assign_all_busses())
|
||||
return;
|
||||
|
||||
while (parent->parent && parent->busn_res.end < max) {
|
||||
parent->busn_res.end = max;
|
||||
pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS, max);
|
||||
parent = parent->parent;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
@ -782,7 +766,7 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
|
|||
/* Check if setup is sensible at all */
|
||||
if (!pass &&
|
||||
(primary != bus->number || secondary <= bus->number ||
|
||||
secondary > subordinate)) {
|
||||
secondary > subordinate || subordinate > bus->busn_res.end)) {
|
||||
dev_info(&dev->dev, "bridge configuration invalid ([bus %02x-%02x]), reconfiguring\n",
|
||||
secondary, subordinate);
|
||||
broken = 1;
|
||||
|
@ -805,11 +789,10 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
|
|||
goto out;
|
||||
|
||||
/*
|
||||
* If we already got to this bus through a different bridge,
|
||||
* don't re-add it. This can happen with the i450NX chipset.
|
||||
*
|
||||
* However, we continue to descend down the hierarchy and
|
||||
* scan remaining child buses.
|
||||
* The bus might already exist for two reasons: Either we are
|
||||
* rescanning the bus or the bus is reachable through more than
|
||||
* one bridge. The second case can happen with the i450NX
|
||||
* chipset.
|
||||
*/
|
||||
child = pci_find_bus(pci_domain_nr(bus), secondary);
|
||||
if (!child) {
|
||||
|
@ -822,17 +805,19 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
|
|||
}
|
||||
|
||||
cmax = pci_scan_child_bus(child);
|
||||
if (cmax > max)
|
||||
max = cmax;
|
||||
if (child->busn_res.end > max)
|
||||
max = child->busn_res.end;
|
||||
if (cmax > subordinate)
|
||||
dev_warn(&dev->dev, "bridge has subordinate %02x but max busn %02x\n",
|
||||
subordinate, cmax);
|
||||
/* subordinate should equal child->busn_res.end */
|
||||
if (subordinate > max)
|
||||
max = subordinate;
|
||||
} else {
|
||||
/*
|
||||
* We need to assign a number to this bus which we always
|
||||
* do in the second pass.
|
||||
*/
|
||||
if (!pass) {
|
||||
if (pcibios_assign_all_busses() || broken)
|
||||
if (pcibios_assign_all_busses() || broken || is_cardbus)
|
||||
/* Temporarily disable forwarding of the
|
||||
configuration cycles on all bridges in
|
||||
this bus segment to avoid possible
|
||||
|
@ -844,19 +829,25 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (max >= bus->busn_res.end) {
|
||||
dev_warn(&dev->dev, "can't allocate child bus %02x from %pR\n",
|
||||
max, &bus->busn_res);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* 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, so in
|
||||
* this case we only re-scan this bus. */
|
||||
/* The bus will already exist if we are rescanning */
|
||||
child = pci_find_bus(pci_domain_nr(bus), max+1);
|
||||
if (!child) {
|
||||
child = pci_add_new_bus(bus, dev, ++max);
|
||||
child = pci_add_new_bus(bus, dev, max+1);
|
||||
if (!child)
|
||||
goto out;
|
||||
pci_bus_insert_busn_res(child, max, 0xff);
|
||||
pci_bus_insert_busn_res(child, max+1,
|
||||
bus->busn_res.end);
|
||||
}
|
||||
max++;
|
||||
buses = (buses & 0xff000000)
|
||||
| ((unsigned int)(child->primary) << 0)
|
||||
| ((unsigned int)(child->busn_res.start) << 8)
|
||||
|
@ -878,20 +869,7 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
|
|||
|
||||
if (!is_cardbus) {
|
||||
child->bridge_ctl = bctl;
|
||||
/*
|
||||
* Adjust subordinate busnr in parent buses.
|
||||
* We do this before scanning for children because
|
||||
* some devices may not be detected if the bios
|
||||
* was lazy.
|
||||
*/
|
||||
pci_fixup_parent_subordinate_busnr(child, max);
|
||||
/* Now we can scan all subordinate buses... */
|
||||
max = pci_scan_child_bus(child);
|
||||
/*
|
||||
* now fix it up again since we have found
|
||||
* the real value of max.
|
||||
*/
|
||||
pci_fixup_parent_subordinate_busnr(child, max);
|
||||
} else {
|
||||
/*
|
||||
* For CardBus bridges, we leave 4 bus numbers
|
||||
|
@ -922,11 +900,15 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
|
|||
}
|
||||
}
|
||||
max += i;
|
||||
pci_fixup_parent_subordinate_busnr(child, max);
|
||||
}
|
||||
/*
|
||||
* Set the subordinate bus number to its real value.
|
||||
*/
|
||||
if (max > bus->busn_res.end) {
|
||||
dev_warn(&dev->dev, "max busn %02x is outside %pR\n",
|
||||
max, &bus->busn_res);
|
||||
max = bus->busn_res.end;
|
||||
}
|
||||
pci_bus_update_busn_res_end(child, max);
|
||||
pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max);
|
||||
}
|
||||
|
@ -1835,7 +1817,7 @@ int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)
|
|||
res->flags |= IORESOURCE_PCI_FIXED;
|
||||
}
|
||||
|
||||
conflict = insert_resource_conflict(parent_res, res);
|
||||
conflict = request_resource_conflict(parent_res, res);
|
||||
|
||||
if (conflict)
|
||||
dev_printk(KERN_DEBUG, &b->dev,
|
||||
|
|
Loading…
Reference in New Issue