diff options
author | Dave Young <hidave.darkstar@gmail.com> | 2008-01-22 02:27:08 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-01-24 23:40:44 -0500 |
commit | fd04897bb20be29d60f7e426a053545aebeaa61a (patch) | |
tree | 7cd86b2d9de79a70bdeb32997240af5e28be6d03 | |
parent | 63b6971a0876b744e2fcf3c9df15d130501e1deb (diff) |
Driver Core: add class iteration api
Add the following class iteration functions for driver use:
class_for_each_device
class_find_device
class_for_each_child
class_find_child
Signed-off-by: Dave Young <hidave.darkstar@gmail.com>
Acked-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/base/class.c | 133 | ||||
-rw-r--r-- | include/linux/device.h | 9 |
2 files changed, 140 insertions, 2 deletions
diff --git a/drivers/base/class.c b/drivers/base/class.c index b962a76875d2..9f737ff0fc71 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c | |||
@@ -809,6 +809,139 @@ void class_device_put(struct class_device *class_dev) | |||
809 | kobject_put(&class_dev->kobj); | 809 | kobject_put(&class_dev->kobj); |
810 | } | 810 | } |
811 | 811 | ||
812 | /** | ||
813 | * class_for_each_device - device iterator | ||
814 | * @class: the class we're iterating | ||
815 | * @data: data for the callback | ||
816 | * @fn: function to be called for each device | ||
817 | * | ||
818 | * Iterate over @class's list of devices, and call @fn for each, | ||
819 | * passing it @data. | ||
820 | * | ||
821 | * We check the return of @fn each time. If it returns anything | ||
822 | * other than 0, we break out and return that value. | ||
823 | * | ||
824 | * Note, we hold class->sem in this function, so it can not be | ||
825 | * re-acquired in @fn, otherwise it will self-deadlocking. For | ||
826 | * example, calls to add or remove class members would be verboten. | ||
827 | */ | ||
828 | int class_for_each_device(struct class *class, void *data, | ||
829 | int (*fn)(struct device *, void *)) | ||
830 | { | ||
831 | struct device *dev; | ||
832 | int error = 0; | ||
833 | |||
834 | if (!class) | ||
835 | return -EINVAL; | ||
836 | down(&class->sem); | ||
837 | list_for_each_entry(dev, &class->devices, node) { | ||
838 | dev = get_device(dev); | ||
839 | if (dev) { | ||
840 | error = fn(dev, data); | ||
841 | put_device(dev); | ||
842 | } else | ||
843 | error = -ENODEV; | ||
844 | if (error) | ||
845 | break; | ||
846 | } | ||
847 | up(&class->sem); | ||
848 | |||
849 | return error; | ||
850 | } | ||
851 | EXPORT_SYMBOL_GPL(class_for_each_device); | ||
852 | |||
853 | /** | ||
854 | * class_find_device - device iterator for locating a particular device | ||
855 | * @class: the class we're iterating | ||
856 | * @data: data for the match function | ||
857 | * @match: function to check device | ||
858 | * | ||
859 | * This is similar to the class_for_each_dev() function above, but it | ||
860 | * returns a reference to a device that is 'found' for later use, as | ||
861 | * determined by the @match callback. | ||
862 | * | ||
863 | * The callback should return 0 if the device doesn't match and non-zero | ||
864 | * if it does. If the callback returns non-zero, this function will | ||
865 | * return to the caller and not iterate over any more devices. | ||
866 | |||
867 | * Note, you will need to drop the reference with put_device() after use. | ||
868 | * | ||
869 | * We hold class->sem in this function, so it can not be | ||
870 | * re-acquired in @match, otherwise it will self-deadlocking. For | ||
871 | * example, calls to add or remove class members would be verboten. | ||
872 | */ | ||
873 | struct device *class_find_device(struct class *class, void *data, | ||
874 | int (*match)(struct device *, void *)) | ||
875 | { | ||
876 | struct device *dev; | ||
877 | int found = 0; | ||
878 | |||
879 | if (!class) | ||
880 | return NULL; | ||
881 | |||
882 | down(&class->sem); | ||
883 | list_for_each_entry(dev, &class->devices, node) { | ||
884 | dev = get_device(dev); | ||
885 | if (dev) { | ||
886 | if (match(dev, data)) { | ||
887 | found = 1; | ||
888 | break; | ||
889 | } else | ||
890 | put_device(dev); | ||
891 | } else | ||
892 | break; | ||
893 | } | ||
894 | up(&class->sem); | ||
895 | |||
896 | return found ? dev : NULL; | ||
897 | } | ||
898 | EXPORT_SYMBOL_GPL(class_find_device); | ||
899 | |||
900 | /** | ||
901 | * class_find_child - device iterator for locating a particular class_device | ||
902 | * @class: the class we're iterating | ||
903 | * @data: data for the match function | ||
904 | * @match: function to check class_device | ||
905 | * | ||
906 | * This function returns a reference to a class_device that is 'found' for | ||
907 | * later use, as determined by the @match callback. | ||
908 | * | ||
909 | * The callback should return 0 if the class_device doesn't match and non-zero | ||
910 | * if it does. If the callback returns non-zero, this function will | ||
911 | * return to the caller and not iterate over any more class_devices. | ||
912 | * | ||
913 | * Note, you will need to drop the reference with class_device_put() after use. | ||
914 | * | ||
915 | * We hold class->sem in this function, so it can not be | ||
916 | * re-acquired in @match, otherwise it will self-deadlocking. For | ||
917 | * example, calls to add or remove class members would be verboten. | ||
918 | */ | ||
919 | struct class_device *class_find_child(struct class *class, void *data, | ||
920 | int (*match)(struct class_device *, void *)) | ||
921 | { | ||
922 | struct class_device *dev; | ||
923 | int found = 0; | ||
924 | |||
925 | if (!class) | ||
926 | return NULL; | ||
927 | |||
928 | down(&class->sem); | ||
929 | list_for_each_entry(dev, &class->children, node) { | ||
930 | dev = class_device_get(dev); | ||
931 | if (dev) { | ||
932 | if (match(dev, data)) { | ||
933 | found = 1; | ||
934 | break; | ||
935 | } else | ||
936 | class_device_put(dev); | ||
937 | } else | ||
938 | break; | ||
939 | } | ||
940 | up(&class->sem); | ||
941 | |||
942 | return found ? dev : NULL; | ||
943 | } | ||
944 | EXPORT_SYMBOL_GPL(class_find_child); | ||
812 | 945 | ||
813 | int class_interface_register(struct class_interface *class_intf) | 946 | int class_interface_register(struct class_interface *class_intf) |
814 | { | 947 | { |
diff --git a/include/linux/device.h b/include/linux/device.h index 92ba3a874627..cdaf57bf4d19 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
@@ -177,8 +177,7 @@ struct class { | |||
177 | struct list_head devices; | 177 | struct list_head devices; |
178 | struct list_head interfaces; | 178 | struct list_head interfaces; |
179 | struct kset class_dirs; | 179 | struct kset class_dirs; |
180 | struct semaphore sem; /* locks both the children and interfaces lists */ | 180 | struct semaphore sem; /* locks children, devices, interfaces */ |
181 | |||
182 | struct class_attribute * class_attrs; | 181 | struct class_attribute * class_attrs; |
183 | struct class_device_attribute * class_dev_attrs; | 182 | struct class_device_attribute * class_dev_attrs; |
184 | struct device_attribute * dev_attrs; | 183 | struct device_attribute * dev_attrs; |
@@ -196,6 +195,12 @@ struct class { | |||
196 | 195 | ||
197 | extern int __must_check class_register(struct class *); | 196 | extern int __must_check class_register(struct class *); |
198 | extern void class_unregister(struct class *); | 197 | extern void class_unregister(struct class *); |
198 | extern int class_for_each_device(struct class *class, void *data, | ||
199 | int (*fn)(struct device *dev, void *data)); | ||
200 | extern struct device *class_find_device(struct class *class, void *data, | ||
201 | int (*match)(struct device *, void *)); | ||
202 | extern struct class_device *class_find_child(struct class *class, void *data, | ||
203 | int (*match)(struct class_device *, void *)); | ||
199 | 204 | ||
200 | 205 | ||
201 | struct class_attribute { | 206 | struct class_attribute { |