aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/bus.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/bus.c')
-rw-r--r--drivers/base/bus.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 39b9b58c6974..5aee1c0169ea 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -980,6 +980,56 @@ struct klist *bus_get_device_klist(struct bus_type *bus)
980} 980}
981EXPORT_SYMBOL_GPL(bus_get_device_klist); 981EXPORT_SYMBOL_GPL(bus_get_device_klist);
982 982
983/*
984 * Yes, this forcably breaks the klist abstraction temporarily. It
985 * just wants to sort the klist, not change reference counts and
986 * take/drop locks rapidly in the process. It does all this while
987 * holding the lock for the list, so objects can't otherwise be
988 * added/removed while we're swizzling.
989 */
990static void device_insertion_sort_klist(struct device *a, struct list_head *list,
991 int (*compare)(const struct device *a,
992 const struct device *b))
993{
994 struct list_head *pos;
995 struct klist_node *n;
996 struct device *b;
997
998 list_for_each(pos, list) {
999 n = container_of(pos, struct klist_node, n_node);
1000 b = container_of(n, struct device, knode_bus);
1001 if (compare(a, b) <= 0) {
1002 list_move_tail(&a->knode_bus.n_node,
1003 &b->knode_bus.n_node);
1004 return;
1005 }
1006 }
1007 list_move_tail(&a->knode_bus.n_node, list);
1008}
1009
1010void bus_sort_breadthfirst(struct bus_type *bus,
1011 int (*compare)(const struct device *a,
1012 const struct device *b))
1013{
1014 LIST_HEAD(sorted_devices);
1015 struct list_head *pos, *tmp;
1016 struct klist_node *n;
1017 struct device *dev;
1018 struct klist *device_klist;
1019
1020 device_klist = bus_get_device_klist(bus);
1021
1022 spin_lock(&device_klist->k_lock);
1023 list_for_each_safe(pos, tmp, &device_klist->k_list) {
1024 n = container_of(pos, struct klist_node, n_node);
1025 dev = container_of(n, struct device, knode_bus);
1026 device_insertion_sort_klist(dev, &sorted_devices, compare);
1027 }
1028 list_splice(&sorted_devices, &device_klist->k_list);
1029 spin_unlock(&device_klist->k_lock);
1030}
1031EXPORT_SYMBOL_GPL(bus_sort_breadthfirst);
1032
983int __init buses_init(void) 1033int __init buses_init(void)
984{ 1034{
985 bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL); 1035 bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);