diff options
-rw-r--r-- | drivers/base/bus.c | 34 | ||||
-rw-r--r-- | drivers/base/driver.c | 35 | ||||
-rw-r--r-- | include/linux/device.h | 5 |
3 files changed, 74 insertions, 0 deletions
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index c3fac7fd555e..2c64b792d074 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c | |||
@@ -177,6 +177,39 @@ int bus_for_each_dev(struct bus_type * bus, struct device * start, | |||
177 | return error; | 177 | return error; |
178 | } | 178 | } |
179 | 179 | ||
180 | /** | ||
181 | * bus_find_device - device iterator for locating a particular device. | ||
182 | * @bus: bus type | ||
183 | * @start: Device to begin with | ||
184 | * @data: Data to pass to match function | ||
185 | * @match: Callback function to check device | ||
186 | * | ||
187 | * This is similar to the bus_for_each_dev() function above, but it | ||
188 | * returns a reference to a device that is 'found' for later use, as | ||
189 | * determined by the @match callback. | ||
190 | * | ||
191 | * The callback should return 0 if the device doesn't match and non-zero | ||
192 | * if it does. If the callback returns non-zero, this function will | ||
193 | * return to the caller and not iterate over any more devices. | ||
194 | */ | ||
195 | struct device * bus_find_device(struct bus_type *bus, | ||
196 | struct device *start, void *data, | ||
197 | int (*match)(struct device *, void *)) | ||
198 | { | ||
199 | struct klist_iter i; | ||
200 | struct device *dev; | ||
201 | |||
202 | if (!bus) | ||
203 | return NULL; | ||
204 | |||
205 | klist_iter_init_node(&bus->klist_devices, &i, | ||
206 | (start ? &start->knode_bus : NULL)); | ||
207 | while ((dev = next_device(&i))) | ||
208 | if (match(dev, data) && get_device(dev)) | ||
209 | break; | ||
210 | klist_iter_exit(&i); | ||
211 | return dev; | ||
212 | } | ||
180 | 213 | ||
181 | 214 | ||
182 | static struct device_driver * next_driver(struct klist_iter * i) | 215 | static struct device_driver * next_driver(struct klist_iter * i) |
@@ -557,6 +590,7 @@ int __init buses_init(void) | |||
557 | 590 | ||
558 | 591 | ||
559 | EXPORT_SYMBOL_GPL(bus_for_each_dev); | 592 | EXPORT_SYMBOL_GPL(bus_for_each_dev); |
593 | EXPORT_SYMBOL_GPL(bus_find_device); | ||
560 | EXPORT_SYMBOL_GPL(bus_for_each_drv); | 594 | EXPORT_SYMBOL_GPL(bus_for_each_drv); |
561 | 595 | ||
562 | EXPORT_SYMBOL_GPL(bus_add_device); | 596 | EXPORT_SYMBOL_GPL(bus_add_device); |
diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 1b645886e9eb..291c5954a3af 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c | |||
@@ -56,6 +56,41 @@ EXPORT_SYMBOL_GPL(driver_for_each_device); | |||
56 | 56 | ||
57 | 57 | ||
58 | /** | 58 | /** |
59 | * driver_find_device - device iterator for locating a particular device. | ||
60 | * @driver: The device's driver | ||
61 | * @start: Device to begin with | ||
62 | * @data: Data to pass to match function | ||
63 | * @match: Callback function to check device | ||
64 | * | ||
65 | * This is similar to the driver_for_each_device() function above, but | ||
66 | * it returns a reference to a device that is 'found' for later use, as | ||
67 | * determined by the @match callback. | ||
68 | * | ||
69 | * The callback should return 0 if the device doesn't match and non-zero | ||
70 | * if it does. If the callback returns non-zero, this function will | ||
71 | * return to the caller and not iterate over any more devices. | ||
72 | */ | ||
73 | struct device * driver_find_device(struct device_driver *drv, | ||
74 | struct device * start, void * data, | ||
75 | int (*match)(struct device *, void *)) | ||
76 | { | ||
77 | struct klist_iter i; | ||
78 | struct device *dev; | ||
79 | |||
80 | if (!drv) | ||
81 | return NULL; | ||
82 | |||
83 | klist_iter_init_node(&drv->klist_devices, &i, | ||
84 | (start ? &start->knode_driver : NULL)); | ||
85 | while ((dev = next_device(&i))) | ||
86 | if (match(dev, data) && get_device(dev)) | ||
87 | break; | ||
88 | klist_iter_exit(&i); | ||
89 | return dev; | ||
90 | } | ||
91 | EXPORT_SYMBOL_GPL(driver_find_device); | ||
92 | |||
93 | /** | ||
59 | * driver_create_file - create sysfs file for driver. | 94 | * driver_create_file - create sysfs file for driver. |
60 | * @drv: driver. | 95 | * @drv: driver. |
61 | * @attr: driver attribute descriptor. | 96 | * @attr: driver attribute descriptor. |
diff --git a/include/linux/device.h b/include/linux/device.h index 7b781a72b293..07222c531d37 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
@@ -80,6 +80,8 @@ extern struct bus_type * find_bus(char * name); | |||
80 | 80 | ||
81 | int bus_for_each_dev(struct bus_type * bus, struct device * start, void * data, | 81 | int bus_for_each_dev(struct bus_type * bus, struct device * start, void * data, |
82 | int (*fn)(struct device *, void *)); | 82 | int (*fn)(struct device *, void *)); |
83 | struct device * bus_find_device(struct bus_type *bus, struct device *start, | ||
84 | void *data, int (*match)(struct device *, void *)); | ||
83 | 85 | ||
84 | int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, | 86 | int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, |
85 | void * data, int (*fn)(struct device_driver *, void *)); | 87 | void * data, int (*fn)(struct device_driver *, void *)); |
@@ -142,6 +144,9 @@ extern void driver_remove_file(struct device_driver *, struct driver_attribute * | |||
142 | 144 | ||
143 | extern int driver_for_each_device(struct device_driver * drv, struct device * start, | 145 | extern int driver_for_each_device(struct device_driver * drv, struct device * start, |
144 | void * data, int (*fn)(struct device *, void *)); | 146 | void * data, int (*fn)(struct device *, void *)); |
147 | struct device * driver_find_device(struct device_driver *drv, | ||
148 | struct device *start, void *data, | ||
149 | int (*match)(struct device *, void *)); | ||
145 | 150 | ||
146 | 151 | ||
147 | /* | 152 | /* |