diff options
| -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 { |
