diff options
author | Andy Shevchenko <andriy.shevchenko@linux.intel.com> | 2015-07-27 17:04:00 +0200 |
---|---|---|
committer | Lee Jones <lee.jones@linaro.org> | 2015-07-28 09:50:42 +0200 |
commit | 3d060aeb72113cda0acf906bfe26914fc689506a (patch) | |
tree | 683028071415f9724d618e8a4f84124a10111a6d /drivers/base | |
parent | klist: implement klist_prev() (diff) | |
download | linux-3d060aeb72113cda0acf906bfe26914fc689506a.tar.xz linux-3d060aeb72113cda0acf906bfe26914fc689506a.zip |
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>
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/core.c | 43 |
1 files changed, 43 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) } EXPORT_SYMBOL_GPL(device_unregister); +static struct device *prev_device(struct klist_iter *i) +{ + struct klist_node *n = klist_prev(i); + struct device *dev = NULL; + struct device_private *p; + + if (n) { + p = to_device_private_parent(n); + dev = p->device; + } + return dev; +} + static struct device *next_device(struct klist_iter *i) { struct klist_node *n = klist_next(i); @@ -1341,6 +1354,36 @@ int device_for_each_child(struct device *parent, void *data, EXPORT_SYMBOL_GPL(device_for_each_child); /** + * device_for_each_child_reverse - device child iterator in reversed order. + * @parent: parent struct device. + * @fn: function to be called for each device. + * @data: data for the callback. + * + * Iterate over @parent's child devices, and call @fn for each, + * passing it @data. + * + * We check the return of @fn each time. If it returns anything + * other than 0, we break out and return that value. + */ +int device_for_each_child_reverse(struct device *parent, void *data, + int (*fn)(struct device *dev, void *data)) +{ + struct klist_iter i; + struct device *child; + int error = 0; + + if (!parent->p) + return 0; + + klist_iter_init(&parent->p->klist_children, &i); + while ((child = prev_device(&i)) && !error) + error = fn(child, data); + klist_iter_exit(&i); + return error; +} +EXPORT_SYMBOL_GPL(device_for_each_child_reverse); + +/** * device_find_child - device iterator for locating a particular device. * @parent: parent struct device * @match: Callback function to check device |