driver-core: use klist for class device list and implement iterator
PATCH 1/1 driver-core: use klist for class device list and implement iterator
Iterating over entries using callback usually isn't too fun especially when the entry being iterated over can't be manipulated freely. This patch converts class->p->class_devices to klist and implements class device iterator so that the users can freely build their own control structure. The users are also free to call back into class code without worrying about locking.
class_for_each_device() and class_find_device() are converted to use the new iterators, so their users don't have to worry about locking anymore either.
Note: This depends on klist-dont-iterate-over-deleted-entries patch because class_intf->add/remove_dev() depends on proper synchronization with device removal.
---
As noted above this patch depends on the following patch.
http://article.gmane.org/gmane.linux.kernel/725706
As with the klist change, it would be most convenient to push this through blk-for-2.6.28. Thanks.
drivers/base/base.h | 2 +- drivers/base/class.c | 137 ++++++++++++++++++++++++++++++++++++------------ drivers/base/core.c | 6 +- include/linux/device.h | 14 +++++- 4 files changed, 121 insertions(+), 38 deletions(-)
drivers/base/base.h +1 -1
@@ -54,7 +54,7 @@ struct driver_private {*/ struct class_private {struct kset class_subsys; -struct list_head class_devices; +struct klist class_devices;struct list_head class_interfaces;struct kset class_dirs;struct mutex class_mutex;
drivers/base/class.c +104 -33
220 lines not on this page · raw message
drivers/base/core.c +3 -3
@@ -536,7 +536,6 @@ void device_initialize(struct device *dev)klist_init (&dev->klist_children, klist_children_get, klist_children_put);INIT_LIST_HEAD (&dev->dma_pools); -INIT_LIST_HEAD (&dev->node);init_MUTEX (&dev->sem);spin_lock_init (&dev->devres_lock);INIT_LIST_HEAD (&dev->devres_head);
@@ -908,7 +907,8 @@ int device_add(struct device *dev)if (dev->class) {mutex_lock (&dev->class->p->class_mutex);/* tie the class to the device */ -list_add_tail (&dev->node, &dev->class->p->class_devices); +klist_add_tail (&dev->knode_class, + &dev->class->p->class_devices);/* notify any interfaces that the device is here */ list_for_each_entry(class_intf,
@@ -1023,7 +1023,7 @@ void device_del(struct device *dev)if (class_intf->remove_dev) class_intf->remove_dev (dev, class_intf);/* remove the device from the class list */ -list_del_init (&dev->node); +klist_del (&dev->knode_class);mutex_unlock (&dev->class->p->class_mutex); }device_remove_file (dev, &uevent_attr);
include/linux/device.h +13 -1
@@ -199,6 +199,11 @@ struct class {struct class_private *p; }; +struct class_dev_iter { +struct klist_iter ki; +const struct device_type *type; +}; +extern struct kobject *sysfs_dev_block_kobj;extern struct kobject *sysfs_dev_char_kobj; extern int __must_check __class_register(struct class *class,
@@ -213,6 +218,13 @@ extern void class_unregister(struct class *class);__class_register (class, &__key); \ }) +extern void class_dev_iter_init (struct class_dev_iter *iter, +struct class *class, +struct device *start, +const struct device_type *type); +extern struct device *class_dev_iter_next (struct class_dev_iter *iter); +extern void class_dev_iter_exit (struct class_dev_iter *iter); +extern int class_for_each_device (struct class *class,struct device *start,void *data,int (*fn)(struct device *dev,void *data));
@@ -395,7 +407,7 @@ struct device {spinlock_t devres_lock;struct list_head devres_head; -struct list_head node; +struct klist_node knode_class;struct class *class;dev_t devt;/* dev_t, creates the sysfs "dev" */ struct attribute_group **groups;/* optional groups */
Signature · 1 line
1.5.4.5