This patch enhances PCI bus specific logic to support PCI bus lock mechanism.

Signed-off-by: Jiang Liu <liu...@gmail.com>
---
 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-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to