diff options
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/bus.c | 50 |
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 | } |
981 | EXPORT_SYMBOL_GPL(bus_get_device_klist); | 981 | EXPORT_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 | */ | ||
990 | static 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 | |||
1010 | void 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 | } | ||
1031 | EXPORT_SYMBOL_GPL(bus_sort_breadthfirst); | ||
1032 | |||
983 | int __init buses_init(void) | 1033 | int __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); |