]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/base/bus.c
Driver core: add bus_sort_breadthfirst() function
[linux-2.6-omap-h63xx.git] / drivers / base / bus.c
index 39b9b58c6974c72c75e8d2a5293a4ab3adc13819..5aee1c0169eafed102c699281b5bb4875fefd20c 100644 (file)
@@ -980,6 +980,56 @@ struct klist *bus_get_device_klist(struct bus_type *bus)
 }
 EXPORT_SYMBOL_GPL(bus_get_device_klist);
 
+/*
+ * Yes, this forcably breaks the klist abstraction temporarily.  It
+ * just wants to sort the klist, not change reference counts and
+ * take/drop locks rapidly in the process.  It does all this while
+ * holding the lock for the list, so objects can't otherwise be
+ * added/removed while we're swizzling.
+ */
+static void device_insertion_sort_klist(struct device *a, struct list_head *list,
+                                       int (*compare)(const struct device *a,
+                                                       const struct device *b))
+{
+       struct list_head *pos;
+       struct klist_node *n;
+       struct device *b;
+
+       list_for_each(pos, list) {
+               n = container_of(pos, struct klist_node, n_node);
+               b = container_of(n, struct device, knode_bus);
+               if (compare(a, b) <= 0) {
+                       list_move_tail(&a->knode_bus.n_node,
+                                      &b->knode_bus.n_node);
+                       return;
+               }
+       }
+       list_move_tail(&a->knode_bus.n_node, list);
+}
+
+void bus_sort_breadthfirst(struct bus_type *bus,
+                          int (*compare)(const struct device *a,
+                                         const struct device *b))
+{
+       LIST_HEAD(sorted_devices);
+       struct list_head *pos, *tmp;
+       struct klist_node *n;
+       struct device *dev;
+       struct klist *device_klist;
+
+       device_klist = bus_get_device_klist(bus);
+
+       spin_lock(&device_klist->k_lock);
+       list_for_each_safe(pos, tmp, &device_klist->k_list) {
+               n = container_of(pos, struct klist_node, n_node);
+               dev = container_of(n, struct device, knode_bus);
+               device_insertion_sort_klist(dev, &sorted_devices, compare);
+       }
+       list_splice(&sorted_devices, &device_klist->k_list);
+       spin_unlock(&device_klist->k_lock);
+}
+EXPORT_SYMBOL_GPL(bus_sort_breadthfirst);
+
 int __init buses_init(void)
 {
        bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);