From foo@baz Tue Apr 9 12:12:43 2002 To: Greg KH Date: 24 Mar 2005 19:08:30 -08:00 From: mochel@digitalimplant.org Subject: [driver core] Use a klist for device child lists. - Use klist iterator in device_for_each_child(), making it safe to use for removing devices. - Remove unused list_to_dev() function. - Kills all usage of devices_subsys.rwsem. Signed-off-by: Patrick Mochel Signed-off-by: Greg Kroah-Hartman Index: linux-2.6.12-rc2/drivers/base/core.c =================================================================== --- linux-2.6.12-rc2.orig/drivers/base/core.c 2005-04-05 14:35:30.000000000 -0700 +++ linux-2.6.12-rc2/drivers/base/core.c 2005-04-05 14:35:41.000000000 -0700 @@ -210,8 +210,7 @@ { kobj_set_kset_s(dev, devices_subsys); kobject_init(&dev->kobj); - INIT_LIST_HEAD(&dev->node); - INIT_LIST_HEAD(&dev->children); + klist_init(&dev->klist_children); INIT_LIST_HEAD(&dev->dma_pools); init_MUTEX(&dev->sem); } @@ -251,10 +250,8 @@ goto PMError; if ((error = bus_add_device(dev))) goto BusError; - down_write(&devices_subsys.rwsem); if (parent) - list_add_tail(&dev->node, &parent->children); - up_write(&devices_subsys.rwsem); + klist_add_tail(&parent->klist_children, &dev->knode_parent); /* notify platform of device entry */ if (platform_notify) @@ -338,10 +335,8 @@ { struct device * parent = dev->parent; - down_write(&devices_subsys.rwsem); if (parent) - list_del_init(&dev->node); - up_write(&devices_subsys.rwsem); + klist_remove(&dev->knode_parent); /* Notify the platform of the removal, in case they * need to do anything... @@ -375,6 +370,12 @@ } +static struct device * next_device(struct klist_iter * i) +{ + struct klist_node * n = klist_next(i); + return n ? container_of(n, struct device, knode_parent) : NULL; +} + /** * device_for_each_child - device child iterator. * @dev: parent struct device. @@ -387,18 +388,17 @@ * We check the return of @fn each time. If it returns anything * other than 0, we break out and return that value. */ -int device_for_each_child(struct device * dev, void * data, +int device_for_each_child(struct device * parent, void * data, int (*fn)(struct device *, void *)) { + struct klist_iter i; struct device * child; int error = 0; - down_read(&devices_subsys.rwsem); - list_for_each_entry(child, &dev->children, node) { - if((error = fn(child, data))) - break; - } - up_read(&devices_subsys.rwsem); + klist_iter_init(&parent->klist_children, &i); + while ((child = next_device(&i)) && !error) + error = fn(child, data); + klist_iter_exit(&i); return error; } Index: linux-2.6.12-rc2/include/linux/device.h =================================================================== --- linux-2.6.12-rc2.orig/include/linux/device.h 2005-04-05 14:35:30.000000000 -0700 +++ linux-2.6.12-rc2/include/linux/device.h 2005-04-05 14:35:41.000000000 -0700 @@ -262,8 +262,8 @@ struct device { - struct list_head node; /* node in sibling list */ - struct list_head children; + struct klist klist_children; + struct klist_node knode_parent; /* node in sibling list */ struct klist_node knode_driver; struct klist_node knode_bus; struct device * parent; @@ -301,12 +301,6 @@ void (*release)(struct device * dev); }; -static inline struct device * -list_to_dev(struct list_head *node) -{ - return list_entry(node, struct device, node); -} - static inline void * dev_get_drvdata (struct device *dev) {