diff options
Diffstat (limited to 'drivers/base/bus.c')
-rw-r--r-- | drivers/base/bus.c | 116 |
1 files changed, 65 insertions, 51 deletions
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 9c9027b2c44e..04d3850ff4b7 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include "power/power.h" | 17 | #include "power/power.h" |
18 | 18 | ||
19 | #define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr) | 19 | #define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr) |
20 | #define to_bus(obj) container_of(obj, struct bus_type, subsys.kobj) | 20 | #define to_bus(obj) container_of(obj, struct bus_type_private, subsys.kobj) |
21 | 21 | ||
22 | /* | 22 | /* |
23 | * sysfs bindings for drivers | 23 | * sysfs bindings for drivers |
@@ -32,13 +32,17 @@ static int __must_check bus_rescan_devices_helper(struct device *dev, | |||
32 | 32 | ||
33 | static struct bus_type *bus_get(struct bus_type *bus) | 33 | static struct bus_type *bus_get(struct bus_type *bus) |
34 | { | 34 | { |
35 | return bus ? container_of(kset_get(&bus->subsys), | 35 | if (bus) { |
36 | struct bus_type, subsys) : NULL; | 36 | kset_get(&bus->p->subsys); |
37 | return bus; | ||
38 | } | ||
39 | return NULL; | ||
37 | } | 40 | } |
38 | 41 | ||
39 | static void bus_put(struct bus_type *bus) | 42 | static void bus_put(struct bus_type *bus) |
40 | { | 43 | { |
41 | kset_put(&bus->subsys); | 44 | if (bus) |
45 | kset_put(&bus->p->subsys); | ||
42 | } | 46 | } |
43 | 47 | ||
44 | static ssize_t | 48 | static ssize_t |
@@ -104,11 +108,11 @@ static ssize_t | |||
104 | bus_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) | 108 | bus_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) |
105 | { | 109 | { |
106 | struct bus_attribute * bus_attr = to_bus_attr(attr); | 110 | struct bus_attribute * bus_attr = to_bus_attr(attr); |
107 | struct bus_type * bus = to_bus(kobj); | 111 | struct bus_type_private *bus_priv = to_bus(kobj); |
108 | ssize_t ret = 0; | 112 | ssize_t ret = 0; |
109 | 113 | ||
110 | if (bus_attr->show) | 114 | if (bus_attr->show) |
111 | ret = bus_attr->show(bus, buf); | 115 | ret = bus_attr->show(bus_priv->bus, buf); |
112 | return ret; | 116 | return ret; |
113 | } | 117 | } |
114 | 118 | ||
@@ -117,11 +121,11 @@ bus_attr_store(struct kobject * kobj, struct attribute * attr, | |||
117 | const char * buf, size_t count) | 121 | const char * buf, size_t count) |
118 | { | 122 | { |
119 | struct bus_attribute * bus_attr = to_bus_attr(attr); | 123 | struct bus_attribute * bus_attr = to_bus_attr(attr); |
120 | struct bus_type * bus = to_bus(kobj); | 124 | struct bus_type_private *bus_priv = to_bus(kobj); |
121 | ssize_t ret = 0; | 125 | ssize_t ret = 0; |
122 | 126 | ||
123 | if (bus_attr->store) | 127 | if (bus_attr->store) |
124 | ret = bus_attr->store(bus, buf, count); | 128 | ret = bus_attr->store(bus_priv->bus, buf, count); |
125 | return ret; | 129 | return ret; |
126 | } | 130 | } |
127 | 131 | ||
@@ -134,7 +138,7 @@ int bus_create_file(struct bus_type * bus, struct bus_attribute * attr) | |||
134 | { | 138 | { |
135 | int error; | 139 | int error; |
136 | if (bus_get(bus)) { | 140 | if (bus_get(bus)) { |
137 | error = sysfs_create_file(&bus->subsys.kobj, &attr->attr); | 141 | error = sysfs_create_file(&bus->p->subsys.kobj, &attr->attr); |
138 | bus_put(bus); | 142 | bus_put(bus); |
139 | } else | 143 | } else |
140 | error = -EINVAL; | 144 | error = -EINVAL; |
@@ -144,7 +148,7 @@ int bus_create_file(struct bus_type * bus, struct bus_attribute * attr) | |||
144 | void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr) | 148 | void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr) |
145 | { | 149 | { |
146 | if (bus_get(bus)) { | 150 | if (bus_get(bus)) { |
147 | sysfs_remove_file(&bus->subsys.kobj, &attr->attr); | 151 | sysfs_remove_file(&bus->p->subsys.kobj, &attr->attr); |
148 | bus_put(bus); | 152 | bus_put(bus); |
149 | } | 153 | } |
150 | } | 154 | } |
@@ -237,16 +241,16 @@ static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind); | |||
237 | 241 | ||
238 | static ssize_t show_drivers_autoprobe(struct bus_type *bus, char *buf) | 242 | static ssize_t show_drivers_autoprobe(struct bus_type *bus, char *buf) |
239 | { | 243 | { |
240 | return sprintf(buf, "%d\n", bus->drivers_autoprobe); | 244 | return sprintf(buf, "%d\n", bus->p->drivers_autoprobe); |
241 | } | 245 | } |
242 | 246 | ||
243 | static ssize_t store_drivers_autoprobe(struct bus_type *bus, | 247 | static ssize_t store_drivers_autoprobe(struct bus_type *bus, |
244 | const char *buf, size_t count) | 248 | const char *buf, size_t count) |
245 | { | 249 | { |
246 | if (buf[0] == '0') | 250 | if (buf[0] == '0') |
247 | bus->drivers_autoprobe = 0; | 251 | bus->p->drivers_autoprobe = 0; |
248 | else | 252 | else |
249 | bus->drivers_autoprobe = 1; | 253 | bus->p->drivers_autoprobe = 1; |
250 | return count; | 254 | return count; |
251 | } | 255 | } |
252 | 256 | ||
@@ -300,7 +304,7 @@ int bus_for_each_dev(struct bus_type * bus, struct device * start, | |||
300 | if (!bus) | 304 | if (!bus) |
301 | return -EINVAL; | 305 | return -EINVAL; |
302 | 306 | ||
303 | klist_iter_init_node(&bus->klist_devices, &i, | 307 | klist_iter_init_node(&bus->p->klist_devices, &i, |
304 | (start ? &start->knode_bus : NULL)); | 308 | (start ? &start->knode_bus : NULL)); |
305 | while ((dev = next_device(&i)) && !error) | 309 | while ((dev = next_device(&i)) && !error) |
306 | error = fn(dev, data); | 310 | error = fn(dev, data); |
@@ -333,7 +337,7 @@ struct device * bus_find_device(struct bus_type *bus, | |||
333 | if (!bus) | 337 | if (!bus) |
334 | return NULL; | 338 | return NULL; |
335 | 339 | ||
336 | klist_iter_init_node(&bus->klist_devices, &i, | 340 | klist_iter_init_node(&bus->p->klist_devices, &i, |
337 | (start ? &start->knode_bus : NULL)); | 341 | (start ? &start->knode_bus : NULL)); |
338 | while ((dev = next_device(&i))) | 342 | while ((dev = next_device(&i))) |
339 | if (match(dev, data) && get_device(dev)) | 343 | if (match(dev, data) && get_device(dev)) |
@@ -379,7 +383,7 @@ int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, | |||
379 | if (!bus) | 383 | if (!bus) |
380 | return -EINVAL; | 384 | return -EINVAL; |
381 | 385 | ||
382 | klist_iter_init_node(&bus->klist_drivers, &i, | 386 | klist_iter_init_node(&bus->p->klist_drivers, &i, |
383 | start ? &start->knode_bus : NULL); | 387 | start ? &start->knode_bus : NULL); |
384 | while ((drv = next_driver(&i)) && !error) | 388 | while ((drv = next_driver(&i)) && !error) |
385 | error = fn(drv, data); | 389 | error = fn(drv, data); |
@@ -420,7 +424,7 @@ static void device_remove_attrs(struct bus_type * bus, struct device * dev) | |||
420 | static int make_deprecated_bus_links(struct device *dev) | 424 | static int make_deprecated_bus_links(struct device *dev) |
421 | { | 425 | { |
422 | return sysfs_create_link(&dev->kobj, | 426 | return sysfs_create_link(&dev->kobj, |
423 | &dev->bus->subsys.kobj, "bus"); | 427 | &dev->bus->p->subsys.kobj, "bus"); |
424 | } | 428 | } |
425 | 429 | ||
426 | static void remove_deprecated_bus_links(struct device *dev) | 430 | static void remove_deprecated_bus_links(struct device *dev) |
@@ -449,12 +453,12 @@ int bus_add_device(struct device * dev) | |||
449 | error = device_add_attrs(bus, dev); | 453 | error = device_add_attrs(bus, dev); |
450 | if (error) | 454 | if (error) |
451 | goto out_put; | 455 | goto out_put; |
452 | error = sysfs_create_link(&bus->devices_kset->kobj, | 456 | error = sysfs_create_link(&bus->p->devices_kset->kobj, |
453 | &dev->kobj, dev->bus_id); | 457 | &dev->kobj, dev->bus_id); |
454 | if (error) | 458 | if (error) |
455 | goto out_id; | 459 | goto out_id; |
456 | error = sysfs_create_link(&dev->kobj, | 460 | error = sysfs_create_link(&dev->kobj, |
457 | &dev->bus->subsys.kobj, "subsystem"); | 461 | &dev->bus->p->subsys.kobj, "subsystem"); |
458 | if (error) | 462 | if (error) |
459 | goto out_subsys; | 463 | goto out_subsys; |
460 | error = make_deprecated_bus_links(dev); | 464 | error = make_deprecated_bus_links(dev); |
@@ -466,7 +470,7 @@ int bus_add_device(struct device * dev) | |||
466 | out_deprecated: | 470 | out_deprecated: |
467 | sysfs_remove_link(&dev->kobj, "subsystem"); | 471 | sysfs_remove_link(&dev->kobj, "subsystem"); |
468 | out_subsys: | 472 | out_subsys: |
469 | sysfs_remove_link(&bus->devices_kset->kobj, dev->bus_id); | 473 | sysfs_remove_link(&bus->p->devices_kset->kobj, dev->bus_id); |
470 | out_id: | 474 | out_id: |
471 | device_remove_attrs(bus, dev); | 475 | device_remove_attrs(bus, dev); |
472 | out_put: | 476 | out_put: |
@@ -488,11 +492,11 @@ void bus_attach_device(struct device * dev) | |||
488 | 492 | ||
489 | if (bus) { | 493 | if (bus) { |
490 | dev->is_registered = 1; | 494 | dev->is_registered = 1; |
491 | if (bus->drivers_autoprobe) | 495 | if (bus->p->drivers_autoprobe) |
492 | ret = device_attach(dev); | 496 | ret = device_attach(dev); |
493 | WARN_ON(ret < 0); | 497 | WARN_ON(ret < 0); |
494 | if (ret >= 0) | 498 | if (ret >= 0) |
495 | klist_add_tail(&dev->knode_bus, &bus->klist_devices); | 499 | klist_add_tail(&dev->knode_bus, &bus->p->klist_devices); |
496 | else | 500 | else |
497 | dev->is_registered = 0; | 501 | dev->is_registered = 0; |
498 | } | 502 | } |
@@ -512,7 +516,7 @@ void bus_remove_device(struct device * dev) | |||
512 | if (dev->bus) { | 516 | if (dev->bus) { |
513 | sysfs_remove_link(&dev->kobj, "subsystem"); | 517 | sysfs_remove_link(&dev->kobj, "subsystem"); |
514 | remove_deprecated_bus_links(dev); | 518 | remove_deprecated_bus_links(dev); |
515 | sysfs_remove_link(&dev->bus->devices_kset->kobj, dev->bus_id); | 519 | sysfs_remove_link(&dev->bus->p->devices_kset->kobj, dev->bus_id); |
516 | device_remove_attrs(dev->bus, dev); | 520 | device_remove_attrs(dev->bus, dev); |
517 | if (dev->is_registered) { | 521 | if (dev->is_registered) { |
518 | dev->is_registered = 0; | 522 | dev->is_registered = 0; |
@@ -638,18 +642,18 @@ int bus_add_driver(struct device_driver *drv) | |||
638 | error = kobject_set_name(&drv->kobj, "%s", drv->name); | 642 | error = kobject_set_name(&drv->kobj, "%s", drv->name); |
639 | if (error) | 643 | if (error) |
640 | goto out_put_bus; | 644 | goto out_put_bus; |
641 | drv->kobj.kset = bus->drivers_kset; | 645 | drv->kobj.kset = bus->p->drivers_kset; |
642 | drv->kobj.ktype = &driver_ktype; | 646 | drv->kobj.ktype = &driver_ktype; |
643 | error = kobject_register(&drv->kobj); | 647 | error = kobject_register(&drv->kobj); |
644 | if (error) | 648 | if (error) |
645 | goto out_put_bus; | 649 | goto out_put_bus; |
646 | 650 | ||
647 | if (drv->bus->drivers_autoprobe) { | 651 | if (drv->bus->p->drivers_autoprobe) { |
648 | error = driver_attach(drv); | 652 | error = driver_attach(drv); |
649 | if (error) | 653 | if (error) |
650 | goto out_unregister; | 654 | goto out_unregister; |
651 | } | 655 | } |
652 | klist_add_tail(&drv->knode_bus, &bus->klist_drivers); | 656 | klist_add_tail(&drv->knode_bus, &bus->p->klist_drivers); |
653 | module_add_driver(drv->owner, drv); | 657 | module_add_driver(drv->owner, drv); |
654 | 658 | ||
655 | error = driver_create_file(drv, &driver_attr_uevent); | 659 | error = driver_create_file(drv, &driver_attr_uevent); |
@@ -828,7 +832,7 @@ static ssize_t bus_uevent_store(struct bus_type *bus, | |||
828 | enum kobject_action action; | 832 | enum kobject_action action; |
829 | 833 | ||
830 | if (kobject_action_type(buf, count, &action) == 0) | 834 | if (kobject_action_type(buf, count, &action) == 0) |
831 | kobject_uevent(&bus->subsys.kobj, action); | 835 | kobject_uevent(&bus->p->subsys.kobj, action); |
832 | return count; | 836 | return count; |
833 | } | 837 | } |
834 | static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store); | 838 | static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store); |
@@ -844,17 +848,26 @@ static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store); | |||
844 | int bus_register(struct bus_type * bus) | 848 | int bus_register(struct bus_type * bus) |
845 | { | 849 | { |
846 | int retval; | 850 | int retval; |
851 | struct bus_type_private *priv; | ||
852 | |||
853 | priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL); | ||
854 | if (!priv) | ||
855 | return -ENOMEM; | ||
856 | |||
857 | priv->bus = bus; | ||
858 | bus->p = priv; | ||
847 | 859 | ||
848 | BLOCKING_INIT_NOTIFIER_HEAD(&bus->bus_notifier); | 860 | BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier); |
849 | 861 | ||
850 | retval = kobject_set_name(&bus->subsys.kobj, "%s", bus->name); | 862 | retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name); |
851 | if (retval) | 863 | if (retval) |
852 | goto out; | 864 | goto out; |
853 | 865 | ||
854 | bus->subsys.kobj.kset = bus_kset; | 866 | priv->subsys.kobj.kset = bus_kset; |
855 | bus->subsys.kobj.ktype = &bus_ktype; | 867 | priv->subsys.kobj.ktype = &bus_ktype; |
868 | priv->drivers_autoprobe = 1; | ||
856 | 869 | ||
857 | retval = kset_register(&bus->subsys); | 870 | retval = kset_register(&priv->subsys); |
858 | if (retval) | 871 | if (retval) |
859 | goto out; | 872 | goto out; |
860 | 873 | ||
@@ -862,24 +875,23 @@ int bus_register(struct bus_type * bus) | |||
862 | if (retval) | 875 | if (retval) |
863 | goto bus_uevent_fail; | 876 | goto bus_uevent_fail; |
864 | 877 | ||
865 | bus->devices_kset = kset_create_and_add("devices", NULL, | 878 | priv->devices_kset = kset_create_and_add("devices", NULL, |
866 | &bus->subsys.kobj); | 879 | &priv->subsys.kobj); |
867 | if (!bus->devices_kset) { | 880 | if (!priv->devices_kset) { |
868 | retval = -ENOMEM; | 881 | retval = -ENOMEM; |
869 | goto bus_devices_fail; | 882 | goto bus_devices_fail; |
870 | } | 883 | } |
871 | 884 | ||
872 | bus->drivers_kset = kset_create_and_add("drivers", NULL, | 885 | priv->drivers_kset = kset_create_and_add("drivers", NULL, |
873 | &bus->subsys.kobj); | 886 | &priv->subsys.kobj); |
874 | if (!bus->drivers_kset) { | 887 | if (!priv->drivers_kset) { |
875 | retval = -ENOMEM; | 888 | retval = -ENOMEM; |
876 | goto bus_drivers_fail; | 889 | goto bus_drivers_fail; |
877 | } | 890 | } |
878 | 891 | ||
879 | klist_init(&bus->klist_devices, klist_devices_get, klist_devices_put); | 892 | klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put); |
880 | klist_init(&bus->klist_drivers, NULL, NULL); | 893 | klist_init(&priv->klist_drivers, NULL, NULL); |
881 | 894 | ||
882 | bus->drivers_autoprobe = 1; | ||
883 | retval = add_probe_files(bus); | 895 | retval = add_probe_files(bus); |
884 | if (retval) | 896 | if (retval) |
885 | goto bus_probe_files_fail; | 897 | goto bus_probe_files_fail; |
@@ -894,13 +906,14 @@ int bus_register(struct bus_type * bus) | |||
894 | bus_attrs_fail: | 906 | bus_attrs_fail: |
895 | remove_probe_files(bus); | 907 | remove_probe_files(bus); |
896 | bus_probe_files_fail: | 908 | bus_probe_files_fail: |
897 | kset_unregister(bus->drivers_kset); | 909 | kset_unregister(bus->p->drivers_kset); |
898 | bus_drivers_fail: | 910 | bus_drivers_fail: |
899 | kset_unregister(bus->devices_kset); | 911 | kset_unregister(bus->p->devices_kset); |
900 | bus_devices_fail: | 912 | bus_devices_fail: |
901 | bus_remove_file(bus, &bus_attr_uevent); | 913 | bus_remove_file(bus, &bus_attr_uevent); |
902 | bus_uevent_fail: | 914 | bus_uevent_fail: |
903 | kset_unregister(&bus->subsys); | 915 | kset_unregister(&bus->p->subsys); |
916 | kfree(bus->p); | ||
904 | out: | 917 | out: |
905 | return retval; | 918 | return retval; |
906 | } | 919 | } |
@@ -917,33 +930,34 @@ void bus_unregister(struct bus_type * bus) | |||
917 | pr_debug("bus %s: unregistering\n", bus->name); | 930 | pr_debug("bus %s: unregistering\n", bus->name); |
918 | bus_remove_attrs(bus); | 931 | bus_remove_attrs(bus); |
919 | remove_probe_files(bus); | 932 | remove_probe_files(bus); |
920 | kset_unregister(bus->drivers_kset); | 933 | kset_unregister(bus->p->drivers_kset); |
921 | kset_unregister(bus->devices_kset); | 934 | kset_unregister(bus->p->devices_kset); |
922 | bus_remove_file(bus, &bus_attr_uevent); | 935 | bus_remove_file(bus, &bus_attr_uevent); |
923 | kset_unregister(&bus->subsys); | 936 | kset_unregister(&bus->p->subsys); |
937 | kfree(bus->p); | ||
924 | } | 938 | } |
925 | 939 | ||
926 | int bus_register_notifier(struct bus_type *bus, struct notifier_block *nb) | 940 | int bus_register_notifier(struct bus_type *bus, struct notifier_block *nb) |
927 | { | 941 | { |
928 | return blocking_notifier_chain_register(&bus->bus_notifier, nb); | 942 | return blocking_notifier_chain_register(&bus->p->bus_notifier, nb); |
929 | } | 943 | } |
930 | EXPORT_SYMBOL_GPL(bus_register_notifier); | 944 | EXPORT_SYMBOL_GPL(bus_register_notifier); |
931 | 945 | ||
932 | int bus_unregister_notifier(struct bus_type *bus, struct notifier_block *nb) | 946 | int bus_unregister_notifier(struct bus_type *bus, struct notifier_block *nb) |
933 | { | 947 | { |
934 | return blocking_notifier_chain_unregister(&bus->bus_notifier, nb); | 948 | return blocking_notifier_chain_unregister(&bus->p->bus_notifier, nb); |
935 | } | 949 | } |
936 | EXPORT_SYMBOL_GPL(bus_unregister_notifier); | 950 | EXPORT_SYMBOL_GPL(bus_unregister_notifier); |
937 | 951 | ||
938 | struct kset *bus_get_kset(struct bus_type *bus) | 952 | struct kset *bus_get_kset(struct bus_type *bus) |
939 | { | 953 | { |
940 | return &bus->subsys; | 954 | return &bus->p->subsys; |
941 | } | 955 | } |
942 | EXPORT_SYMBOL_GPL(bus_get_kset); | 956 | EXPORT_SYMBOL_GPL(bus_get_kset); |
943 | 957 | ||
944 | struct klist *bus_get_device_klist(struct bus_type *bus) | 958 | struct klist *bus_get_device_klist(struct bus_type *bus) |
945 | { | 959 | { |
946 | return &bus->klist_devices; | 960 | return &bus->p->klist_devices; |
947 | } | 961 | } |
948 | EXPORT_SYMBOL_GPL(bus_get_device_klist); | 962 | EXPORT_SYMBOL_GPL(bus_get_device_klist); |
949 | 963 | ||