Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
[linux-2.6-block.git] / drivers / base / core.c
index f6947d0abc2f470e56f6b4b72f894cacd050efd3..334ec7ef1960cf46b69a27315a1dbcccbf39dd8b 100644 (file)
@@ -1301,6 +1301,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);
@@ -1389,6 +1402,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