diff options
author | Andy Shevchenko <andriy.shevchenko@linux.intel.com> | 2015-07-27 11:04:00 -0400 |
---|---|---|
committer | Lee Jones <lee.jones@linaro.org> | 2015-07-28 03:50:42 -0400 |
commit | 3d060aeb72113cda0acf906bfe26914fc689506a (patch) | |
tree | 683028071415f9724d618e8a4f84124a10111a6d | |
parent | 2e0fed7f7cdc41679e209c5636ad7537dc6210a9 (diff) |
driver core: implement device_for_each_child_reverse()
The new function device_for_each_child_reverse() is helpful to traverse the
registered devices in a reversed order, e.g. in the case when an operation on
each device should be done first on the last added device, then on one before
last and so on.
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
-rw-r--r-- | drivers/base/core.c | 43 | ||||
-rw-r--r-- | include/linux/device.h | 2 |
2 files changed, 45 insertions, 0 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index dafae6d2f7ac..7d6279554afc 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -1252,6 +1252,19 @@ void device_unregister(struct device *dev) | |||
1252 | } | 1252 | } |
1253 | EXPORT_SYMBOL_GPL(device_unregister); | 1253 | EXPORT_SYMBOL_GPL(device_unregister); |
1254 | 1254 | ||
1255 | static struct device *prev_device(struct klist_iter *i) | ||
1256 | { | ||
1257 | struct klist_node *n = klist_prev(i); | ||
1258 | struct device *dev = NULL; | ||
1259 | struct device_private *p; | ||
1260 | |||
1261 | if (n) { | ||
1262 | p = to_device_private_parent(n); | ||
1263 | dev = p->device; | ||
1264 | } | ||
1265 | return dev; | ||
1266 | } | ||
1267 | |||
1255 | static struct device *next_device(struct klist_iter *i) | 1268 | static struct device *next_device(struct klist_iter *i) |
1256 | { | 1269 | { |
1257 | struct klist_node *n = klist_next(i); | 1270 | struct klist_node *n = klist_next(i); |
@@ -1341,6 +1354,36 @@ int device_for_each_child(struct device *parent, void *data, | |||
1341 | EXPORT_SYMBOL_GPL(device_for_each_child); | 1354 | EXPORT_SYMBOL_GPL(device_for_each_child); |
1342 | 1355 | ||
1343 | /** | 1356 | /** |
1357 | * device_for_each_child_reverse - device child iterator in reversed order. | ||
1358 | * @parent: parent struct device. | ||
1359 | * @fn: function to be called for each device. | ||
1360 | * @data: data for the callback. | ||
1361 | * | ||
1362 | * Iterate over @parent's child devices, and call @fn for each, | ||
1363 | * passing it @data. | ||
1364 | * | ||
1365 | * We check the return of @fn each time. If it returns anything | ||
1366 | * other than 0, we break out and return that value. | ||
1367 | */ | ||
1368 | int device_for_each_child_reverse(struct device *parent, void *data, | ||
1369 | int (*fn)(struct device *dev, void *data)) | ||
1370 | { | ||
1371 | struct klist_iter i; | ||
1372 | struct device *child; | ||
1373 | int error = 0; | ||
1374 | |||
1375 | if (!parent->p) | ||
1376 | return 0; | ||
1377 | |||
1378 | klist_iter_init(&parent->p->klist_children, &i); | ||
1379 | while ((child = prev_device(&i)) && !error) | ||
1380 | error = fn(child, data); | ||
1381 | klist_iter_exit(&i); | ||
1382 | return error; | ||
1383 | } | ||
1384 | EXPORT_SYMBOL_GPL(device_for_each_child_reverse); | ||
1385 | |||
1386 | /** | ||
1344 | * device_find_child - device iterator for locating a particular device. | 1387 | * device_find_child - device iterator for locating a particular device. |
1345 | * @parent: parent struct device | 1388 | * @parent: parent struct device |
1346 | * @match: Callback function to check device | 1389 | * @match: Callback function to check device |
diff --git a/include/linux/device.h b/include/linux/device.h index 5a31bf3a4024..af6fbc35d8a6 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
@@ -958,6 +958,8 @@ extern int __must_check device_add(struct device *dev); | |||
958 | extern void device_del(struct device *dev); | 958 | extern void device_del(struct device *dev); |
959 | extern int device_for_each_child(struct device *dev, void *data, | 959 | extern int device_for_each_child(struct device *dev, void *data, |
960 | int (*fn)(struct device *dev, void *data)); | 960 | int (*fn)(struct device *dev, void *data)); |
961 | extern int device_for_each_child_reverse(struct device *dev, void *data, | ||
962 | int (*fn)(struct device *dev, void *data)); | ||
961 | extern struct device *device_find_child(struct device *dev, void *data, | 963 | extern struct device *device_find_child(struct device *dev, void *data, |
962 | int (*match)(struct device *dev, void *data)); | 964 | int (*match)(struct device *dev, void *data)); |
963 | extern int device_rename(struct device *dev, const char *new_name); | 965 | extern int device_rename(struct device *dev, const char *new_name); |