diff options
Diffstat (limited to 'drivers/base/bus.c')
-rw-r--r-- | drivers/base/bus.c | 44 |
1 files changed, 30 insertions, 14 deletions
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 83f32b891fa9..dc030f1f00f1 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c | |||
@@ -198,7 +198,7 @@ static ssize_t driver_bind(struct device_driver *drv, | |||
198 | int err = -ENODEV; | 198 | int err = -ENODEV; |
199 | 199 | ||
200 | dev = bus_find_device_by_name(bus, NULL, buf); | 200 | dev = bus_find_device_by_name(bus, NULL, buf); |
201 | if (dev && dev->driver == NULL) { | 201 | if (dev && dev->driver == NULL && driver_match_device(drv, dev)) { |
202 | if (dev->parent) /* Needed for USB */ | 202 | if (dev->parent) /* Needed for USB */ |
203 | down(&dev->parent->sem); | 203 | down(&dev->parent->sem); |
204 | down(&dev->sem); | 204 | down(&dev->sem); |
@@ -253,7 +253,14 @@ static ssize_t store_drivers_probe(struct bus_type *bus, | |||
253 | static struct device *next_device(struct klist_iter *i) | 253 | static struct device *next_device(struct klist_iter *i) |
254 | { | 254 | { |
255 | struct klist_node *n = klist_next(i); | 255 | struct klist_node *n = klist_next(i); |
256 | return n ? container_of(n, struct device, knode_bus) : NULL; | 256 | struct device *dev = NULL; |
257 | struct device_private *dev_prv; | ||
258 | |||
259 | if (n) { | ||
260 | dev_prv = to_device_private_bus(n); | ||
261 | dev = dev_prv->device; | ||
262 | } | ||
263 | return dev; | ||
257 | } | 264 | } |
258 | 265 | ||
259 | /** | 266 | /** |
@@ -286,7 +293,7 @@ int bus_for_each_dev(struct bus_type *bus, struct device *start, | |||
286 | return -EINVAL; | 293 | return -EINVAL; |
287 | 294 | ||
288 | klist_iter_init_node(&bus->p->klist_devices, &i, | 295 | klist_iter_init_node(&bus->p->klist_devices, &i, |
289 | (start ? &start->knode_bus : NULL)); | 296 | (start ? &start->p->knode_bus : NULL)); |
290 | while ((dev = next_device(&i)) && !error) | 297 | while ((dev = next_device(&i)) && !error) |
291 | error = fn(dev, data); | 298 | error = fn(dev, data); |
292 | klist_iter_exit(&i); | 299 | klist_iter_exit(&i); |
@@ -320,7 +327,7 @@ struct device *bus_find_device(struct bus_type *bus, | |||
320 | return NULL; | 327 | return NULL; |
321 | 328 | ||
322 | klist_iter_init_node(&bus->p->klist_devices, &i, | 329 | klist_iter_init_node(&bus->p->klist_devices, &i, |
323 | (start ? &start->knode_bus : NULL)); | 330 | (start ? &start->p->knode_bus : NULL)); |
324 | while ((dev = next_device(&i))) | 331 | while ((dev = next_device(&i))) |
325 | if (match(dev, data) && get_device(dev)) | 332 | if (match(dev, data) && get_device(dev)) |
326 | break; | 333 | break; |
@@ -507,7 +514,8 @@ void bus_attach_device(struct device *dev) | |||
507 | ret = device_attach(dev); | 514 | ret = device_attach(dev); |
508 | WARN_ON(ret < 0); | 515 | WARN_ON(ret < 0); |
509 | if (ret >= 0) | 516 | if (ret >= 0) |
510 | klist_add_tail(&dev->knode_bus, &bus->p->klist_devices); | 517 | klist_add_tail(&dev->p->knode_bus, |
518 | &bus->p->klist_devices); | ||
511 | } | 519 | } |
512 | } | 520 | } |
513 | 521 | ||
@@ -528,8 +536,8 @@ void bus_remove_device(struct device *dev) | |||
528 | sysfs_remove_link(&dev->bus->p->devices_kset->kobj, | 536 | sysfs_remove_link(&dev->bus->p->devices_kset->kobj, |
529 | dev_name(dev)); | 537 | dev_name(dev)); |
530 | device_remove_attrs(dev->bus, dev); | 538 | device_remove_attrs(dev->bus, dev); |
531 | if (klist_node_attached(&dev->knode_bus)) | 539 | if (klist_node_attached(&dev->p->knode_bus)) |
532 | klist_del(&dev->knode_bus); | 540 | klist_del(&dev->p->knode_bus); |
533 | 541 | ||
534 | pr_debug("bus: '%s': remove device %s\n", | 542 | pr_debug("bus: '%s': remove device %s\n", |
535 | dev->bus->name, dev_name(dev)); | 543 | dev->bus->name, dev_name(dev)); |
@@ -831,14 +839,16 @@ static void bus_remove_attrs(struct bus_type *bus) | |||
831 | 839 | ||
832 | static void klist_devices_get(struct klist_node *n) | 840 | static void klist_devices_get(struct klist_node *n) |
833 | { | 841 | { |
834 | struct device *dev = container_of(n, struct device, knode_bus); | 842 | struct device_private *dev_prv = to_device_private_bus(n); |
843 | struct device *dev = dev_prv->device; | ||
835 | 844 | ||
836 | get_device(dev); | 845 | get_device(dev); |
837 | } | 846 | } |
838 | 847 | ||
839 | static void klist_devices_put(struct klist_node *n) | 848 | static void klist_devices_put(struct klist_node *n) |
840 | { | 849 | { |
841 | struct device *dev = container_of(n, struct device, knode_bus); | 850 | struct device_private *dev_prv = to_device_private_bus(n); |
851 | struct device *dev = dev_prv->device; | ||
842 | 852 | ||
843 | put_device(dev); | 853 | put_device(dev); |
844 | } | 854 | } |
@@ -932,6 +942,7 @@ bus_uevent_fail: | |||
932 | kset_unregister(&bus->p->subsys); | 942 | kset_unregister(&bus->p->subsys); |
933 | kfree(bus->p); | 943 | kfree(bus->p); |
934 | out: | 944 | out: |
945 | bus->p = NULL; | ||
935 | return retval; | 946 | return retval; |
936 | } | 947 | } |
937 | EXPORT_SYMBOL_GPL(bus_register); | 948 | EXPORT_SYMBOL_GPL(bus_register); |
@@ -953,6 +964,7 @@ void bus_unregister(struct bus_type *bus) | |||
953 | bus_remove_file(bus, &bus_attr_uevent); | 964 | bus_remove_file(bus, &bus_attr_uevent); |
954 | kset_unregister(&bus->p->subsys); | 965 | kset_unregister(&bus->p->subsys); |
955 | kfree(bus->p); | 966 | kfree(bus->p); |
967 | bus->p = NULL; | ||
956 | } | 968 | } |
957 | EXPORT_SYMBOL_GPL(bus_unregister); | 969 | EXPORT_SYMBOL_GPL(bus_unregister); |
958 | 970 | ||
@@ -993,18 +1005,20 @@ static void device_insertion_sort_klist(struct device *a, struct list_head *list | |||
993 | { | 1005 | { |
994 | struct list_head *pos; | 1006 | struct list_head *pos; |
995 | struct klist_node *n; | 1007 | struct klist_node *n; |
1008 | struct device_private *dev_prv; | ||
996 | struct device *b; | 1009 | struct device *b; |
997 | 1010 | ||
998 | list_for_each(pos, list) { | 1011 | list_for_each(pos, list) { |
999 | n = container_of(pos, struct klist_node, n_node); | 1012 | n = container_of(pos, struct klist_node, n_node); |
1000 | b = container_of(n, struct device, knode_bus); | 1013 | dev_prv = to_device_private_bus(n); |
1014 | b = dev_prv->device; | ||
1001 | if (compare(a, b) <= 0) { | 1015 | if (compare(a, b) <= 0) { |
1002 | list_move_tail(&a->knode_bus.n_node, | 1016 | list_move_tail(&a->p->knode_bus.n_node, |
1003 | &b->knode_bus.n_node); | 1017 | &b->p->knode_bus.n_node); |
1004 | return; | 1018 | return; |
1005 | } | 1019 | } |
1006 | } | 1020 | } |
1007 | list_move_tail(&a->knode_bus.n_node, list); | 1021 | list_move_tail(&a->p->knode_bus.n_node, list); |
1008 | } | 1022 | } |
1009 | 1023 | ||
1010 | void bus_sort_breadthfirst(struct bus_type *bus, | 1024 | void bus_sort_breadthfirst(struct bus_type *bus, |
@@ -1014,6 +1028,7 @@ void bus_sort_breadthfirst(struct bus_type *bus, | |||
1014 | LIST_HEAD(sorted_devices); | 1028 | LIST_HEAD(sorted_devices); |
1015 | struct list_head *pos, *tmp; | 1029 | struct list_head *pos, *tmp; |
1016 | struct klist_node *n; | 1030 | struct klist_node *n; |
1031 | struct device_private *dev_prv; | ||
1017 | struct device *dev; | 1032 | struct device *dev; |
1018 | struct klist *device_klist; | 1033 | struct klist *device_klist; |
1019 | 1034 | ||
@@ -1022,7 +1037,8 @@ void bus_sort_breadthfirst(struct bus_type *bus, | |||
1022 | spin_lock(&device_klist->k_lock); | 1037 | spin_lock(&device_klist->k_lock); |
1023 | list_for_each_safe(pos, tmp, &device_klist->k_list) { | 1038 | list_for_each_safe(pos, tmp, &device_klist->k_list) { |
1024 | n = container_of(pos, struct klist_node, n_node); | 1039 | n = container_of(pos, struct klist_node, n_node); |
1025 | dev = container_of(n, struct device, knode_bus); | 1040 | dev_prv = to_device_private_bus(n); |
1041 | dev = dev_prv->device; | ||
1026 | device_insertion_sort_klist(dev, &sorted_devices, compare); | 1042 | device_insertion_sort_klist(dev, &sorted_devices, compare); |
1027 | } | 1043 | } |
1028 | list_splice(&sorted_devices, &device_klist->k_list); | 1044 | list_splice(&sorted_devices, &device_klist->k_list); |