Skip to contentSkip to conversation

driver-core: use klist for class device list and implement iterator

PATCH New Tejun Heo 1 participant 1 message Aug 25, 2008 Driver core

lore
Share & tools
lore

Tejun Heo

author
#0 lore raw

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.

Cc Greg Kroah-Hartman <[email protected]>
Cc Jens Axboe <[email protected]>

---
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
index 31dc0cd..0a5f055 100644
@@ -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
index 068aa1c..a77031a 100644
@@ -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
index d24a47f..4189044 100644
@@ -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