[PATCH] Add a klist to struct bus_type for its devices.
authormochel@digitalimplant.org <mochel@digitalimplant.org>
Mon, 21 Mar 2005 19:49:14 +0000 (11:49 -0800)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 20 Jun 2005 22:15:14 +0000 (15:15 -0700)
- Use it for bus_for_each_dev().
- Use the klist spinlock instead of the bus rwsem.

Signed-off-by: Patrick Mochel <mochel@digitalimplant.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/base/bus.c
include/linux/device.h

index 1b05c1399e37e51c62d4522c34a6090cb8d933c7..c8da37230b3ec81465f8264e4ae1d22851f1ce5b 100644 (file)
@@ -134,28 +134,6 @@ static struct kobj_type ktype_bus = {
 
 decl_subsys(bus, &ktype_bus, NULL);
 
-static int __bus_for_each_dev(struct bus_type *bus, struct device *start,
-                             void *data, int (*fn)(struct device *, void *))
-{
-       struct list_head *head;
-       struct device *dev;
-       int error = 0;
-
-       if (!(bus = get_bus(bus)))
-               return -EINVAL;
-
-       head = &bus->devices.list;
-       dev = list_prepare_entry(start, head, bus_list);
-       list_for_each_entry_continue(dev, head, bus_list) {
-               get_device(dev);
-               error = fn(dev, data);
-               put_device(dev);
-               if (error)
-                       break;
-       }
-       put_bus(bus);
-       return error;
-}
 
 static int __bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
                              void * data, int (*fn)(struct device_driver *, void *))
@@ -180,6 +158,13 @@ static int __bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
        return error;
 }
 
+
+static struct device * next_device(struct klist_iter * i)
+{
+       struct klist_node * n = klist_next(i);
+       return n ? container_of(n, struct device, knode_bus) : NULL;
+}
+
 /**
  *     bus_for_each_dev - device iterator.
  *     @bus:   bus type.
@@ -203,12 +188,19 @@ static int __bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
 int bus_for_each_dev(struct bus_type * bus, struct device * start,
                     void * data, int (*fn)(struct device *, void *))
 {
-       int ret;
+       struct klist_iter i;
+       struct device * dev;
+       int error = 0;
 
-       down_read(&bus->subsys.rwsem);
-       ret = __bus_for_each_dev(bus, start, data, fn);
-       up_read(&bus->subsys.rwsem);
-       return ret;
+       if (!bus)
+               return -EINVAL;
+
+       klist_iter_init_node(&bus->klist_devices, &i,
+                            (start ? &start->knode_bus : NULL));
+       while ((dev = next_device(&i)) && !error)
+               error = fn(dev, data);
+       klist_iter_exit(&i);
+       return error;
 }
 
 /**
@@ -293,6 +285,7 @@ int bus_add_device(struct device * dev)
                list_add_tail(&dev->bus_list, &dev->bus->devices.list);
                device_attach(dev);
                up_write(&dev->bus->subsys.rwsem);
+               klist_add_tail(&bus->klist_devices, &dev->knode_bus);
                device_add_attrs(bus, dev);
                sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id);
                sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "bus");
@@ -315,6 +308,7 @@ void bus_remove_device(struct device * dev)
                sysfs_remove_link(&dev->kobj, "bus");
                sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id);
                device_remove_attrs(dev->bus, dev);
+               klist_remove(&dev->knode_bus);
                down_write(&dev->bus->subsys.rwsem);
                pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id);
                device_release_driver(dev);
@@ -439,9 +433,7 @@ int bus_rescan_devices(struct bus_type * bus)
 {
        int count = 0;
 
-       down_write(&bus->subsys.rwsem);
-       __bus_for_each_dev(bus, NULL, &count, bus_rescan_devices_helper);
-       up_write(&bus->subsys.rwsem);
+       bus_for_each_dev(bus, NULL, &count, bus_rescan_devices_helper);
 
        return count;
 }
@@ -542,6 +534,8 @@ int bus_register(struct bus_type * bus)
        retval = kset_register(&bus->drivers);
        if (retval)
                goto bus_drivers_fail;
+
+       klist_init(&bus->klist_devices);
        bus_add_attrs(bus);
 
        pr_debug("bus type '%s' registered\n", bus->name);
index 10f5aa20e041699cd1dbf9d694b27d7a3b8485f3..e36953cf7f142b730c12da1685cff1333fd32cb5 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/config.h>
 #include <linux/ioport.h>
 #include <linux/kobject.h>
+#include <linux/klist.h>
 #include <linux/list.h>
 #include <linux/types.h>
 #include <linux/module.h>
@@ -51,6 +52,7 @@ struct bus_type {
        struct subsystem        subsys;
        struct kset             drivers;
        struct kset             devices;
+       struct klist            klist_devices;
 
        struct bus_attribute    * bus_attrs;
        struct device_attribute * dev_attrs;
@@ -262,6 +264,7 @@ struct device {
        struct list_head bus_list;      /* node in bus's list */
        struct list_head driver_list;
        struct list_head children;
+       struct klist_node       knode_bus;
        struct device   * parent;
 
        struct kobject kobj;