diff options
Diffstat (limited to 'drivers/base/bus.c')
-rw-r--r-- | drivers/base/bus.c | 293 |
1 files changed, 274 insertions, 19 deletions
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 000e7b2006f8..99dc5921e1dd 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c | |||
@@ -16,9 +16,14 @@ | |||
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/string.h> | 18 | #include <linux/string.h> |
19 | #include <linux/mutex.h> | ||
19 | #include "base.h" | 20 | #include "base.h" |
20 | #include "power/power.h" | 21 | #include "power/power.h" |
21 | 22 | ||
23 | /* /sys/devices/system */ | ||
24 | /* FIXME: make static after drivers/base/sys.c is deleted */ | ||
25 | struct kset *system_kset; | ||
26 | |||
22 | #define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr) | 27 | #define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr) |
23 | 28 | ||
24 | /* | 29 | /* |
@@ -360,6 +365,47 @@ struct device *bus_find_device_by_name(struct bus_type *bus, | |||
360 | } | 365 | } |
361 | EXPORT_SYMBOL_GPL(bus_find_device_by_name); | 366 | EXPORT_SYMBOL_GPL(bus_find_device_by_name); |
362 | 367 | ||
368 | /** | ||
369 | * subsys_find_device_by_id - find a device with a specific enumeration number | ||
370 | * @subsys: subsystem | ||
371 | * @id: index 'id' in struct device | ||
372 | * @hint: device to check first | ||
373 | * | ||
374 | * Check the hint's next object and if it is a match return it directly, | ||
375 | * otherwise, fall back to a full list search. Either way a reference for | ||
376 | * the returned object is taken. | ||
377 | */ | ||
378 | struct device *subsys_find_device_by_id(struct bus_type *subsys, unsigned int id, | ||
379 | struct device *hint) | ||
380 | { | ||
381 | struct klist_iter i; | ||
382 | struct device *dev; | ||
383 | |||
384 | if (!subsys) | ||
385 | return NULL; | ||
386 | |||
387 | if (hint) { | ||
388 | klist_iter_init_node(&subsys->p->klist_devices, &i, &hint->p->knode_bus); | ||
389 | dev = next_device(&i); | ||
390 | if (dev && dev->id == id && get_device(dev)) { | ||
391 | klist_iter_exit(&i); | ||
392 | return dev; | ||
393 | } | ||
394 | klist_iter_exit(&i); | ||
395 | } | ||
396 | |||
397 | klist_iter_init_node(&subsys->p->klist_devices, &i, NULL); | ||
398 | while ((dev = next_device(&i))) { | ||
399 | if (dev->id == id && get_device(dev)) { | ||
400 | klist_iter_exit(&i); | ||
401 | return dev; | ||
402 | } | ||
403 | } | ||
404 | klist_iter_exit(&i); | ||
405 | return NULL; | ||
406 | } | ||
407 | EXPORT_SYMBOL_GPL(subsys_find_device_by_id); | ||
408 | |||
363 | static struct device_driver *next_driver(struct klist_iter *i) | 409 | static struct device_driver *next_driver(struct klist_iter *i) |
364 | { | 410 | { |
365 | struct klist_node *n = klist_next(i); | 411 | struct klist_node *n = klist_next(i); |
@@ -487,38 +533,59 @@ out_put: | |||
487 | void bus_probe_device(struct device *dev) | 533 | void bus_probe_device(struct device *dev) |
488 | { | 534 | { |
489 | struct bus_type *bus = dev->bus; | 535 | struct bus_type *bus = dev->bus; |
536 | struct subsys_interface *sif; | ||
490 | int ret; | 537 | int ret; |
491 | 538 | ||
492 | if (bus && bus->p->drivers_autoprobe) { | 539 | if (!bus) |
540 | return; | ||
541 | |||
542 | if (bus->p->drivers_autoprobe) { | ||
493 | ret = device_attach(dev); | 543 | ret = device_attach(dev); |
494 | WARN_ON(ret < 0); | 544 | WARN_ON(ret < 0); |
495 | } | 545 | } |
546 | |||
547 | mutex_lock(&bus->p->mutex); | ||
548 | list_for_each_entry(sif, &bus->p->interfaces, node) | ||
549 | if (sif->add_dev) | ||
550 | sif->add_dev(dev, sif); | ||
551 | mutex_unlock(&bus->p->mutex); | ||
496 | } | 552 | } |
497 | 553 | ||
498 | /** | 554 | /** |
499 | * bus_remove_device - remove device from bus | 555 | * bus_remove_device - remove device from bus |
500 | * @dev: device to be removed | 556 | * @dev: device to be removed |
501 | * | 557 | * |
502 | * - Remove symlink from bus's directory. | 558 | * - Remove device from all interfaces. |
559 | * - Remove symlink from bus' directory. | ||
503 | * - Delete device from bus's list. | 560 | * - Delete device from bus's list. |
504 | * - Detach from its driver. | 561 | * - Detach from its driver. |
505 | * - Drop reference taken in bus_add_device(). | 562 | * - Drop reference taken in bus_add_device(). |
506 | */ | 563 | */ |
507 | void bus_remove_device(struct device *dev) | 564 | void bus_remove_device(struct device *dev) |
508 | { | 565 | { |
509 | if (dev->bus) { | 566 | struct bus_type *bus = dev->bus; |
510 | sysfs_remove_link(&dev->kobj, "subsystem"); | 567 | struct subsys_interface *sif; |
511 | sysfs_remove_link(&dev->bus->p->devices_kset->kobj, | 568 | |
512 | dev_name(dev)); | 569 | if (!bus) |
513 | device_remove_attrs(dev->bus, dev); | 570 | return; |
514 | if (klist_node_attached(&dev->p->knode_bus)) | 571 | |
515 | klist_del(&dev->p->knode_bus); | 572 | mutex_lock(&bus->p->mutex); |
516 | 573 | list_for_each_entry(sif, &bus->p->interfaces, node) | |
517 | pr_debug("bus: '%s': remove device %s\n", | 574 | if (sif->remove_dev) |
518 | dev->bus->name, dev_name(dev)); | 575 | sif->remove_dev(dev, sif); |
519 | device_release_driver(dev); | 576 | mutex_unlock(&bus->p->mutex); |
520 | bus_put(dev->bus); | 577 | |
521 | } | 578 | sysfs_remove_link(&dev->kobj, "subsystem"); |
579 | sysfs_remove_link(&dev->bus->p->devices_kset->kobj, | ||
580 | dev_name(dev)); | ||
581 | device_remove_attrs(dev->bus, dev); | ||
582 | if (klist_node_attached(&dev->p->knode_bus)) | ||
583 | klist_del(&dev->p->knode_bus); | ||
584 | |||
585 | pr_debug("bus: '%s': remove device %s\n", | ||
586 | dev->bus->name, dev_name(dev)); | ||
587 | device_release_driver(dev); | ||
588 | bus_put(dev->bus); | ||
522 | } | 589 | } |
523 | 590 | ||
524 | static int driver_add_attrs(struct bus_type *bus, struct device_driver *drv) | 591 | static int driver_add_attrs(struct bus_type *bus, struct device_driver *drv) |
@@ -847,14 +914,14 @@ static ssize_t bus_uevent_store(struct bus_type *bus, | |||
847 | static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store); | 914 | static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store); |
848 | 915 | ||
849 | /** | 916 | /** |
850 | * bus_register - register a bus with the system. | 917 | * __bus_register - register a driver-core subsystem |
851 | * @bus: bus. | 918 | * @bus: bus. |
852 | * | 919 | * |
853 | * Once we have that, we registered the bus with the kobject | 920 | * Once we have that, we registered the bus with the kobject |
854 | * infrastructure, then register the children subsystems it has: | 921 | * infrastructure, then register the children subsystems it has: |
855 | * the devices and drivers that belong to the bus. | 922 | * the devices and drivers that belong to the subsystem. |
856 | */ | 923 | */ |
857 | int bus_register(struct bus_type *bus) | 924 | int __bus_register(struct bus_type *bus, struct lock_class_key *key) |
858 | { | 925 | { |
859 | int retval; | 926 | int retval; |
860 | struct subsys_private *priv; | 927 | struct subsys_private *priv; |
@@ -898,6 +965,8 @@ int bus_register(struct bus_type *bus) | |||
898 | goto bus_drivers_fail; | 965 | goto bus_drivers_fail; |
899 | } | 966 | } |
900 | 967 | ||
968 | INIT_LIST_HEAD(&priv->interfaces); | ||
969 | __mutex_init(&priv->mutex, "subsys mutex", key); | ||
901 | klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put); | 970 | klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put); |
902 | klist_init(&priv->klist_drivers, NULL, NULL); | 971 | klist_init(&priv->klist_drivers, NULL, NULL); |
903 | 972 | ||
@@ -927,7 +996,7 @@ out: | |||
927 | bus->p = NULL; | 996 | bus->p = NULL; |
928 | return retval; | 997 | return retval; |
929 | } | 998 | } |
930 | EXPORT_SYMBOL_GPL(bus_register); | 999 | EXPORT_SYMBOL_GPL(__bus_register); |
931 | 1000 | ||
932 | /** | 1001 | /** |
933 | * bus_unregister - remove a bus from the system | 1002 | * bus_unregister - remove a bus from the system |
@@ -939,6 +1008,8 @@ EXPORT_SYMBOL_GPL(bus_register); | |||
939 | void bus_unregister(struct bus_type *bus) | 1008 | void bus_unregister(struct bus_type *bus) |
940 | { | 1009 | { |
941 | pr_debug("bus: '%s': unregistering\n", bus->name); | 1010 | pr_debug("bus: '%s': unregistering\n", bus->name); |
1011 | if (bus->dev_root) | ||
1012 | device_unregister(bus->dev_root); | ||
942 | bus_remove_attrs(bus); | 1013 | bus_remove_attrs(bus); |
943 | remove_probe_files(bus); | 1014 | remove_probe_files(bus); |
944 | kset_unregister(bus->p->drivers_kset); | 1015 | kset_unregister(bus->p->drivers_kset); |
@@ -1028,10 +1099,194 @@ void bus_sort_breadthfirst(struct bus_type *bus, | |||
1028 | } | 1099 | } |
1029 | EXPORT_SYMBOL_GPL(bus_sort_breadthfirst); | 1100 | EXPORT_SYMBOL_GPL(bus_sort_breadthfirst); |
1030 | 1101 | ||
1102 | /** | ||
1103 | * subsys_dev_iter_init - initialize subsys device iterator | ||
1104 | * @iter: subsys iterator to initialize | ||
1105 | * @subsys: the subsys we wanna iterate over | ||
1106 | * @start: the device to start iterating from, if any | ||
1107 | * @type: device_type of the devices to iterate over, NULL for all | ||
1108 | * | ||
1109 | * Initialize subsys iterator @iter such that it iterates over devices | ||
1110 | * of @subsys. If @start is set, the list iteration will start there, | ||
1111 | * otherwise if it is NULL, the iteration starts at the beginning of | ||
1112 | * the list. | ||
1113 | */ | ||
1114 | void subsys_dev_iter_init(struct subsys_dev_iter *iter, struct bus_type *subsys, | ||
1115 | struct device *start, const struct device_type *type) | ||
1116 | { | ||
1117 | struct klist_node *start_knode = NULL; | ||
1118 | |||
1119 | if (start) | ||
1120 | start_knode = &start->p->knode_bus; | ||
1121 | klist_iter_init_node(&subsys->p->klist_devices, &iter->ki, start_knode); | ||
1122 | iter->type = type; | ||
1123 | } | ||
1124 | EXPORT_SYMBOL_GPL(subsys_dev_iter_init); | ||
1125 | |||
1126 | /** | ||
1127 | * subsys_dev_iter_next - iterate to the next device | ||
1128 | * @iter: subsys iterator to proceed | ||
1129 | * | ||
1130 | * Proceed @iter to the next device and return it. Returns NULL if | ||
1131 | * iteration is complete. | ||
1132 | * | ||
1133 | * The returned device is referenced and won't be released till | ||
1134 | * iterator is proceed to the next device or exited. The caller is | ||
1135 | * free to do whatever it wants to do with the device including | ||
1136 | * calling back into subsys code. | ||
1137 | */ | ||
1138 | struct device *subsys_dev_iter_next(struct subsys_dev_iter *iter) | ||
1139 | { | ||
1140 | struct klist_node *knode; | ||
1141 | struct device *dev; | ||
1142 | |||
1143 | for (;;) { | ||
1144 | knode = klist_next(&iter->ki); | ||
1145 | if (!knode) | ||
1146 | return NULL; | ||
1147 | dev = container_of(knode, struct device_private, knode_bus)->device; | ||
1148 | if (!iter->type || iter->type == dev->type) | ||
1149 | return dev; | ||
1150 | } | ||
1151 | } | ||
1152 | EXPORT_SYMBOL_GPL(subsys_dev_iter_next); | ||
1153 | |||
1154 | /** | ||
1155 | * subsys_dev_iter_exit - finish iteration | ||
1156 | * @iter: subsys iterator to finish | ||
1157 | * | ||
1158 | * Finish an iteration. Always call this function after iteration is | ||
1159 | * complete whether the iteration ran till the end or not. | ||
1160 | */ | ||
1161 | void subsys_dev_iter_exit(struct subsys_dev_iter *iter) | ||
1162 | { | ||
1163 | klist_iter_exit(&iter->ki); | ||
1164 | } | ||
1165 | EXPORT_SYMBOL_GPL(subsys_dev_iter_exit); | ||
1166 | |||
1167 | int subsys_interface_register(struct subsys_interface *sif) | ||
1168 | { | ||
1169 | struct bus_type *subsys; | ||
1170 | struct subsys_dev_iter iter; | ||
1171 | struct device *dev; | ||
1172 | |||
1173 | if (!sif || !sif->subsys) | ||
1174 | return -ENODEV; | ||
1175 | |||
1176 | subsys = bus_get(sif->subsys); | ||
1177 | if (!subsys) | ||
1178 | return -EINVAL; | ||
1179 | |||
1180 | mutex_lock(&subsys->p->mutex); | ||
1181 | list_add_tail(&sif->node, &subsys->p->interfaces); | ||
1182 | if (sif->add_dev) { | ||
1183 | subsys_dev_iter_init(&iter, subsys, NULL, NULL); | ||
1184 | while ((dev = subsys_dev_iter_next(&iter))) | ||
1185 | sif->add_dev(dev, sif); | ||
1186 | subsys_dev_iter_exit(&iter); | ||
1187 | } | ||
1188 | mutex_unlock(&subsys->p->mutex); | ||
1189 | |||
1190 | return 0; | ||
1191 | } | ||
1192 | EXPORT_SYMBOL_GPL(subsys_interface_register); | ||
1193 | |||
1194 | void subsys_interface_unregister(struct subsys_interface *sif) | ||
1195 | { | ||
1196 | struct bus_type *subsys = sif->subsys; | ||
1197 | struct subsys_dev_iter iter; | ||
1198 | struct device *dev; | ||
1199 | |||
1200 | if (!sif) | ||
1201 | return; | ||
1202 | |||
1203 | mutex_lock(&subsys->p->mutex); | ||
1204 | list_del_init(&sif->node); | ||
1205 | if (sif->remove_dev) { | ||
1206 | subsys_dev_iter_init(&iter, subsys, NULL, NULL); | ||
1207 | while ((dev = subsys_dev_iter_next(&iter))) | ||
1208 | sif->remove_dev(dev, sif); | ||
1209 | subsys_dev_iter_exit(&iter); | ||
1210 | } | ||
1211 | mutex_unlock(&subsys->p->mutex); | ||
1212 | |||
1213 | bus_put(subsys); | ||
1214 | } | ||
1215 | EXPORT_SYMBOL_GPL(subsys_interface_unregister); | ||
1216 | |||
1217 | static void system_root_device_release(struct device *dev) | ||
1218 | { | ||
1219 | kfree(dev); | ||
1220 | } | ||
1221 | /** | ||
1222 | * subsys_system_register - register a subsystem at /sys/devices/system/ | ||
1223 | * @subsys - system subsystem | ||
1224 | * @groups - default attributes for the root device | ||
1225 | * | ||
1226 | * All 'system' subsystems have a /sys/devices/system/<name> root device | ||
1227 | * with the name of the subsystem. The root device can carry subsystem- | ||
1228 | * wide attributes. All registered devices are below this single root | ||
1229 | * device and are named after the subsystem with a simple enumeration | ||
1230 | * number appended. The registered devices are not explicitely named; | ||
1231 | * only 'id' in the device needs to be set. | ||
1232 | * | ||
1233 | * Do not use this interface for anything new, it exists for compatibility | ||
1234 | * with bad ideas only. New subsystems should use plain subsystems; and | ||
1235 | * add the subsystem-wide attributes should be added to the subsystem | ||
1236 | * directory itself and not some create fake root-device placed in | ||
1237 | * /sys/devices/system/<name>. | ||
1238 | */ | ||
1239 | int subsys_system_register(struct bus_type *subsys, | ||
1240 | const struct attribute_group **groups) | ||
1241 | { | ||
1242 | struct device *dev; | ||
1243 | int err; | ||
1244 | |||
1245 | err = bus_register(subsys); | ||
1246 | if (err < 0) | ||
1247 | return err; | ||
1248 | |||
1249 | dev = kzalloc(sizeof(struct device), GFP_KERNEL); | ||
1250 | if (!dev) { | ||
1251 | err = -ENOMEM; | ||
1252 | goto err_dev; | ||
1253 | } | ||
1254 | |||
1255 | err = dev_set_name(dev, "%s", subsys->name); | ||
1256 | if (err < 0) | ||
1257 | goto err_name; | ||
1258 | |||
1259 | dev->kobj.parent = &system_kset->kobj; | ||
1260 | dev->groups = groups; | ||
1261 | dev->release = system_root_device_release; | ||
1262 | |||
1263 | err = device_register(dev); | ||
1264 | if (err < 0) | ||
1265 | goto err_dev_reg; | ||
1266 | |||
1267 | subsys->dev_root = dev; | ||
1268 | return 0; | ||
1269 | |||
1270 | err_dev_reg: | ||
1271 | put_device(dev); | ||
1272 | dev = NULL; | ||
1273 | err_name: | ||
1274 | kfree(dev); | ||
1275 | err_dev: | ||
1276 | bus_unregister(subsys); | ||
1277 | return err; | ||
1278 | } | ||
1279 | EXPORT_SYMBOL_GPL(subsys_system_register); | ||
1280 | |||
1031 | int __init buses_init(void) | 1281 | int __init buses_init(void) |
1032 | { | 1282 | { |
1033 | bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL); | 1283 | bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL); |
1034 | if (!bus_kset) | 1284 | if (!bus_kset) |
1035 | return -ENOMEM; | 1285 | return -ENOMEM; |
1286 | |||
1287 | system_kset = kset_create_and_add("system", NULL, &devices_kset->kobj); | ||
1288 | if (!system_kset) | ||
1289 | return -ENOMEM; | ||
1290 | |||
1036 | return 0; | 1291 | return 0; |
1037 | } | 1292 | } |