device/pci_device: Do not break tree topology
Fix regression introduced with commit
ad7674e
device: Introduce pcidev_on_root() and friends
Function pci_scan_bus() breaks bus->children link
in the devicetree topology while scanning a bus.
While the scan is in progress, accessing PCI
devices with number higher than what is being probed
was not possible because new pcidev_on_root() relies
on having proper topology present at any time.
Change-Id: I7bb497f7390628dd2f0310b380f199783a888c4c
Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Reviewed-on: https://review.coreboot.org/c/30772
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Nico Huber <nico.h@gmx.de>
Reviewed-by: Tristan Corrick <tristan@corrick.kiwi>
This commit is contained in:
parent
82a4e27341
commit
8712aa107f
|
@ -989,33 +989,33 @@ bad:
|
||||||
/**
|
/**
|
||||||
* See if we have already allocated a device structure for a given devfn.
|
* See if we have already allocated a device structure for a given devfn.
|
||||||
*
|
*
|
||||||
* Given a linked list of PCI device structures and a devfn number, find the
|
* Given a PCI bus structure and a devfn number, find the device structure
|
||||||
* device structure correspond to the devfn, if present. This function also
|
* corresponding to the devfn, if present. Then move the device structure
|
||||||
* removes the device structure from the linked list.
|
* as the last child on the bus.
|
||||||
*
|
*
|
||||||
* @param list The device structure list.
|
* @param bus Pointer to the bus structure.
|
||||||
* @param devfn A device/function number.
|
* @param devfn A device/function number.
|
||||||
* @return Pointer to the device structure found or NULL if we have not
|
* @return Pointer to the device structure found or NULL if we have not
|
||||||
* allocated a device for this devfn yet.
|
* allocated a device for this devfn yet.
|
||||||
*/
|
*/
|
||||||
static struct device *pci_scan_get_dev(struct device **list, unsigned int devfn)
|
static struct device *pci_scan_get_dev(struct bus *bus, unsigned int devfn)
|
||||||
{
|
{
|
||||||
struct device *dev;
|
struct device *dev, **prev;
|
||||||
|
|
||||||
dev = 0;
|
prev = &bus->children;
|
||||||
for (; *list; list = &(*list)->sibling) {
|
for (dev = bus->children; dev; dev = dev->sibling) {
|
||||||
if ((*list)->path.type != DEVICE_PATH_PCI) {
|
if (dev->path.type == DEVICE_PATH_PCI) {
|
||||||
printk(BIOS_ERR, "child %s not a PCI device\n",
|
if (dev->path.pci.devfn == devfn) {
|
||||||
dev_path(*list));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ((*list)->path.pci.devfn == devfn) {
|
|
||||||
/* Unlink from the list. */
|
/* Unlink from the list. */
|
||||||
dev = *list;
|
*prev = dev->sibling;
|
||||||
*list = (*list)->sibling;
|
|
||||||
dev->sibling = NULL;
|
dev->sibling = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
printk(BIOS_ERR, "child %s not a PCI device\n",
|
||||||
|
dev_path(dev));
|
||||||
|
}
|
||||||
|
prev = &dev->sibling;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1027,15 +1027,15 @@ static struct device *pci_scan_get_dev(struct device **list, unsigned int devfn)
|
||||||
if (dev) {
|
if (dev) {
|
||||||
struct device *child;
|
struct device *child;
|
||||||
|
|
||||||
/* Find the last child of our parent. */
|
/* Find the last child on the bus. */
|
||||||
for (child = dev->bus->children; child && child->sibling;)
|
for (child = bus->children; child && child->sibling;)
|
||||||
child = child->sibling;
|
child = child->sibling;
|
||||||
|
|
||||||
/* Place the device on the list of children of its parent. */
|
/* Place the device as last on the bus. */
|
||||||
if (child)
|
if (child)
|
||||||
child->sibling = dev;
|
child->sibling = dev;
|
||||||
else
|
else
|
||||||
dev->bus->children = dev;
|
bus->children = dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
return dev;
|
return dev;
|
||||||
|
@ -1180,7 +1180,8 @@ void pci_scan_bus(struct bus *bus, unsigned min_devfn,
|
||||||
unsigned max_devfn)
|
unsigned max_devfn)
|
||||||
{
|
{
|
||||||
unsigned int devfn;
|
unsigned int devfn;
|
||||||
struct device *old_devices;
|
struct device *dev, **prev;
|
||||||
|
int once = 0;
|
||||||
|
|
||||||
printk(BIOS_DEBUG, "PCI: pci_scan_bus for bus %02x\n", bus->secondary);
|
printk(BIOS_DEBUG, "PCI: pci_scan_bus for bus %02x\n", bus->secondary);
|
||||||
|
|
||||||
|
@ -1193,9 +1194,6 @@ void pci_scan_bus(struct bus *bus, unsigned min_devfn,
|
||||||
max_devfn=0xff;
|
max_devfn=0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
old_devices = bus->children;
|
|
||||||
bus->children = NULL;
|
|
||||||
|
|
||||||
post_code(0x24);
|
post_code(0x24);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1203,10 +1201,8 @@ void pci_scan_bus(struct bus *bus, unsigned min_devfn,
|
||||||
* non-existence and single function devices.
|
* non-existence and single function devices.
|
||||||
*/
|
*/
|
||||||
for (devfn = min_devfn; devfn <= max_devfn; devfn++) {
|
for (devfn = min_devfn; devfn <= max_devfn; devfn++) {
|
||||||
struct device *dev;
|
|
||||||
|
|
||||||
/* First thing setup the device structure. */
|
/* First thing setup the device structure. */
|
||||||
dev = pci_scan_get_dev(&old_devices, devfn);
|
dev = pci_scan_get_dev(bus, devfn);
|
||||||
|
|
||||||
/* See if a device is present and setup the device structure. */
|
/* See if a device is present and setup the device structure. */
|
||||||
dev = pci_probe_dev(dev, bus, devfn);
|
dev = pci_probe_dev(dev, bus, devfn);
|
||||||
|
@ -1228,15 +1224,26 @@ void pci_scan_bus(struct bus *bus, unsigned min_devfn,
|
||||||
* Warn if any leftover static devices are are found.
|
* Warn if any leftover static devices are are found.
|
||||||
* There's probably a problem in devicetree.cb.
|
* There's probably a problem in devicetree.cb.
|
||||||
*/
|
*/
|
||||||
if (old_devices) {
|
|
||||||
struct device *left;
|
|
||||||
printk(BIOS_WARNING, "PCI: Left over static devices:\n");
|
|
||||||
for (left = old_devices; left; left = left->sibling)
|
|
||||||
printk(BIOS_WARNING, "%s\n", dev_path(left));
|
|
||||||
|
|
||||||
printk(BIOS_WARNING, "PCI: Check your devicetree.cb.\n");
|
prev = &bus->children;
|
||||||
|
for (dev = bus->children; dev; dev = dev->sibling) {
|
||||||
|
/* If we read valid vendor id, it is not leftover device. */
|
||||||
|
if (dev->vendor != 0) {
|
||||||
|
prev = &dev->sibling;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Unlink it from list. */
|
||||||
|
*prev = dev->sibling;
|
||||||
|
|
||||||
|
if (!once++)
|
||||||
|
printk(BIOS_WARNING, "PCI: Leftover static devices:\n");
|
||||||
|
printk(BIOS_WARNING, "%s\n", dev_path(dev));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (once)
|
||||||
|
printk(BIOS_WARNING, "PCI: Check your devicetree.cb.\n");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For all children that implement scan_bus() (i.e. bridges)
|
* For all children that implement scan_bus() (i.e. bridges)
|
||||||
* scan the bus behind that child.
|
* scan the bus behind that child.
|
||||||
|
|
Loading…
Reference in New Issue