This patch enhances PCI bus specific logic to support PCI bus lock mechanism. Signed-off-by: Jiang Liu <liuj97@xxxxxxxxx> --- drivers/pci/bus.c | 54 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index b6aacaa..371f20a 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -185,19 +185,20 @@ int pci_bus_add_device(struct pci_dev *dev) */ int pci_bus_add_child(struct pci_bus *bus) { - int retval; - - if (bus->bridge) - bus->dev.parent = bus->bridge; - - retval = device_add(&bus->dev); - if (retval) - return retval; - - bus->is_added = 1; - - /* Create legacy_io and legacy_mem files for this bus */ - pci_create_legacy_files(bus); + int retval = -EBUSY; + + if (pci_bus_get_state(bus) == PCI_BUS_STATE_INITIALIZED) { + if (bus->bridge) + bus->dev.parent = bus->bridge; + retval = device_add(&bus->dev); + if (retval == 0) { + /* Create legacy_io and legacy_mem files for this bus */ + pci_create_legacy_files(bus); + pci_bus_change_state(bus, PCI_BUS_STATE_INITIALIZED, + PCI_BUS_STATE_WORKING, false); + bus->is_added = 1; + } + } return retval; } @@ -232,13 +233,14 @@ void pci_bus_add_devices(const struct pci_bus *bus) list_for_each_entry(dev, &bus->devices, bus_list) { BUG_ON(!dev->is_added); - child = dev->subordinate; + child = pci_lock_subordinate(dev, PCI_BUS_STATE_STOPPING - 1); + if (!child) + continue; + /* * If there is an unattached subordinate bus, attach * it and then scan for unattached PCI devices. */ - if (!child) - continue; if (list_empty(&child->node)) { down_write(&pci_bus_sem); list_add_tail(&child->node, &dev->bus->children); @@ -250,28 +252,34 @@ void pci_bus_add_devices(const struct pci_bus *bus) * register the bus with sysfs as the parent is now * properly registered. */ - if (child->is_added) - continue; - retval = pci_bus_add_child(child); - if (retval) - dev_err(&dev->dev, "Error adding bus, continuing\n"); + if (pci_bus_get_state(child) == PCI_BUS_STATE_INITIALIZED) { + retval = pci_bus_add_child(child); + if (retval) + dev_err(&dev->dev, + "Error adding bus, continuing\n"); + } + + pci_bus_unlock(child); } } void pci_enable_bridges(struct pci_bus *bus) { struct pci_dev *dev; + struct pci_bus *child; int retval; list_for_each_entry(dev, &bus->devices, bus_list) { - if (dev->subordinate) { + child = pci_lock_subordinate(dev, PCI_BUS_STATE_STOPPING - 1); + if (child) { if (!pci_is_enabled(dev)) { retval = pci_enable_device(dev); if (retval) dev_err(&dev->dev, "Error enabling bridge (%d), continuing\n", retval); pci_set_master(dev); } - pci_enable_bridges(dev->subordinate); + pci_enable_bridges(child); + pci_bus_unlock(child); } } } -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html