11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * bus.c - bus driver management 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Copyright (c) 2002-3 Patrick Mochel 51da177e4SLinus Torvalds * Copyright (c) 2002-3 Open Source Development Labs 61da177e4SLinus Torvalds * 71da177e4SLinus Torvalds * This file is released under the GPLv2 81da177e4SLinus Torvalds * 91da177e4SLinus Torvalds */ 101da177e4SLinus Torvalds 111da177e4SLinus Torvalds #include <linux/config.h> 121da177e4SLinus Torvalds #include <linux/device.h> 131da177e4SLinus Torvalds #include <linux/module.h> 141da177e4SLinus Torvalds #include <linux/errno.h> 151da177e4SLinus Torvalds #include <linux/init.h> 161da177e4SLinus Torvalds #include <linux/string.h> 171da177e4SLinus Torvalds #include "base.h" 181da177e4SLinus Torvalds #include "power/power.h" 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds #define to_dev(node) container_of(node, struct device, bus_list) 211da177e4SLinus Torvalds 221da177e4SLinus Torvalds #define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr) 231da177e4SLinus Torvalds #define to_bus(obj) container_of(obj, struct bus_type, subsys.kset.kobj) 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds /* 261da177e4SLinus Torvalds * sysfs bindings for drivers 271da177e4SLinus Torvalds */ 281da177e4SLinus Torvalds 291da177e4SLinus Torvalds #define to_drv_attr(_attr) container_of(_attr, struct driver_attribute, attr) 301da177e4SLinus Torvalds #define to_driver(obj) container_of(obj, struct device_driver, kobj) 311da177e4SLinus Torvalds 321da177e4SLinus Torvalds 331da177e4SLinus Torvalds static ssize_t 341da177e4SLinus Torvalds drv_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) 351da177e4SLinus Torvalds { 361da177e4SLinus Torvalds struct driver_attribute * drv_attr = to_drv_attr(attr); 371da177e4SLinus Torvalds struct device_driver * drv = to_driver(kobj); 384a0c20bfSDmitry Torokhov ssize_t ret = -EIO; 391da177e4SLinus Torvalds 401da177e4SLinus Torvalds if (drv_attr->show) 411da177e4SLinus Torvalds ret = drv_attr->show(drv, buf); 421da177e4SLinus Torvalds return ret; 431da177e4SLinus Torvalds } 441da177e4SLinus Torvalds 451da177e4SLinus Torvalds static ssize_t 461da177e4SLinus Torvalds drv_attr_store(struct kobject * kobj, struct attribute * attr, 471da177e4SLinus Torvalds const char * buf, size_t count) 481da177e4SLinus Torvalds { 491da177e4SLinus Torvalds struct driver_attribute * drv_attr = to_drv_attr(attr); 501da177e4SLinus Torvalds struct device_driver * drv = to_driver(kobj); 514a0c20bfSDmitry Torokhov ssize_t ret = -EIO; 521da177e4SLinus Torvalds 531da177e4SLinus Torvalds if (drv_attr->store) 541da177e4SLinus Torvalds ret = drv_attr->store(drv, buf, count); 551da177e4SLinus Torvalds return ret; 561da177e4SLinus Torvalds } 571da177e4SLinus Torvalds 581da177e4SLinus Torvalds static struct sysfs_ops driver_sysfs_ops = { 591da177e4SLinus Torvalds .show = drv_attr_show, 601da177e4SLinus Torvalds .store = drv_attr_store, 611da177e4SLinus Torvalds }; 621da177e4SLinus Torvalds 631da177e4SLinus Torvalds 641da177e4SLinus Torvalds static void driver_release(struct kobject * kobj) 651da177e4SLinus Torvalds { 661da177e4SLinus Torvalds struct device_driver * drv = to_driver(kobj); 671da177e4SLinus Torvalds complete(&drv->unloaded); 681da177e4SLinus Torvalds } 691da177e4SLinus Torvalds 701da177e4SLinus Torvalds static struct kobj_type ktype_driver = { 711da177e4SLinus Torvalds .sysfs_ops = &driver_sysfs_ops, 721da177e4SLinus Torvalds .release = driver_release, 731da177e4SLinus Torvalds }; 741da177e4SLinus Torvalds 751da177e4SLinus Torvalds 761da177e4SLinus Torvalds /* 771da177e4SLinus Torvalds * sysfs bindings for buses 781da177e4SLinus Torvalds */ 791da177e4SLinus Torvalds 801da177e4SLinus Torvalds 811da177e4SLinus Torvalds static ssize_t 821da177e4SLinus Torvalds bus_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) 831da177e4SLinus Torvalds { 841da177e4SLinus Torvalds struct bus_attribute * bus_attr = to_bus_attr(attr); 851da177e4SLinus Torvalds struct bus_type * bus = to_bus(kobj); 861da177e4SLinus Torvalds ssize_t ret = 0; 871da177e4SLinus Torvalds 881da177e4SLinus Torvalds if (bus_attr->show) 891da177e4SLinus Torvalds ret = bus_attr->show(bus, buf); 901da177e4SLinus Torvalds return ret; 911da177e4SLinus Torvalds } 921da177e4SLinus Torvalds 931da177e4SLinus Torvalds static ssize_t 941da177e4SLinus Torvalds bus_attr_store(struct kobject * kobj, struct attribute * attr, 951da177e4SLinus Torvalds const char * buf, size_t count) 961da177e4SLinus Torvalds { 971da177e4SLinus Torvalds struct bus_attribute * bus_attr = to_bus_attr(attr); 981da177e4SLinus Torvalds struct bus_type * bus = to_bus(kobj); 991da177e4SLinus Torvalds ssize_t ret = 0; 1001da177e4SLinus Torvalds 1011da177e4SLinus Torvalds if (bus_attr->store) 1021da177e4SLinus Torvalds ret = bus_attr->store(bus, buf, count); 1031da177e4SLinus Torvalds return ret; 1041da177e4SLinus Torvalds } 1051da177e4SLinus Torvalds 1061da177e4SLinus Torvalds static struct sysfs_ops bus_sysfs_ops = { 1071da177e4SLinus Torvalds .show = bus_attr_show, 1081da177e4SLinus Torvalds .store = bus_attr_store, 1091da177e4SLinus Torvalds }; 1101da177e4SLinus Torvalds 1111da177e4SLinus Torvalds int bus_create_file(struct bus_type * bus, struct bus_attribute * attr) 1121da177e4SLinus Torvalds { 1131da177e4SLinus Torvalds int error; 1141da177e4SLinus Torvalds if (get_bus(bus)) { 1151da177e4SLinus Torvalds error = sysfs_create_file(&bus->subsys.kset.kobj, &attr->attr); 1161da177e4SLinus Torvalds put_bus(bus); 1171da177e4SLinus Torvalds } else 1181da177e4SLinus Torvalds error = -EINVAL; 1191da177e4SLinus Torvalds return error; 1201da177e4SLinus Torvalds } 1211da177e4SLinus Torvalds 1221da177e4SLinus Torvalds void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr) 1231da177e4SLinus Torvalds { 1241da177e4SLinus Torvalds if (get_bus(bus)) { 1251da177e4SLinus Torvalds sysfs_remove_file(&bus->subsys.kset.kobj, &attr->attr); 1261da177e4SLinus Torvalds put_bus(bus); 1271da177e4SLinus Torvalds } 1281da177e4SLinus Torvalds } 1291da177e4SLinus Torvalds 1301da177e4SLinus Torvalds static struct kobj_type ktype_bus = { 1311da177e4SLinus Torvalds .sysfs_ops = &bus_sysfs_ops, 1321da177e4SLinus Torvalds 1331da177e4SLinus Torvalds }; 1341da177e4SLinus Torvalds 1351da177e4SLinus Torvalds decl_subsys(bus, &ktype_bus, NULL); 1361da177e4SLinus Torvalds 1371da177e4SLinus Torvalds 1381da177e4SLinus Torvalds static int __bus_for_each_drv(struct bus_type *bus, struct device_driver *start, 1391da177e4SLinus Torvalds void * data, int (*fn)(struct device_driver *, void *)) 1401da177e4SLinus Torvalds { 1411da177e4SLinus Torvalds struct list_head *head; 1421da177e4SLinus Torvalds struct device_driver *drv; 1431da177e4SLinus Torvalds int error = 0; 1441da177e4SLinus Torvalds 1451da177e4SLinus Torvalds if (!(bus = get_bus(bus))) 1461da177e4SLinus Torvalds return -EINVAL; 1471da177e4SLinus Torvalds 1481da177e4SLinus Torvalds head = &bus->drivers.list; 1491da177e4SLinus Torvalds drv = list_prepare_entry(start, head, kobj.entry); 1501da177e4SLinus Torvalds list_for_each_entry_continue(drv, head, kobj.entry) { 1511da177e4SLinus Torvalds get_driver(drv); 1521da177e4SLinus Torvalds error = fn(drv, data); 1531da177e4SLinus Torvalds put_driver(drv); 1541da177e4SLinus Torvalds if (error) 1551da177e4SLinus Torvalds break; 1561da177e4SLinus Torvalds } 1571da177e4SLinus Torvalds put_bus(bus); 1581da177e4SLinus Torvalds return error; 1591da177e4SLinus Torvalds } 1601da177e4SLinus Torvalds 161*465c7a3aSmochel@digitalimplant.org 162*465c7a3aSmochel@digitalimplant.org static struct device * next_device(struct klist_iter * i) 163*465c7a3aSmochel@digitalimplant.org { 164*465c7a3aSmochel@digitalimplant.org struct klist_node * n = klist_next(i); 165*465c7a3aSmochel@digitalimplant.org return n ? container_of(n, struct device, knode_bus) : NULL; 166*465c7a3aSmochel@digitalimplant.org } 167*465c7a3aSmochel@digitalimplant.org 1681da177e4SLinus Torvalds /** 1691da177e4SLinus Torvalds * bus_for_each_dev - device iterator. 1701da177e4SLinus Torvalds * @bus: bus type. 1711da177e4SLinus Torvalds * @start: device to start iterating from. 1721da177e4SLinus Torvalds * @data: data for the callback. 1731da177e4SLinus Torvalds * @fn: function to be called for each device. 1741da177e4SLinus Torvalds * 1751da177e4SLinus Torvalds * Iterate over @bus's list of devices, and call @fn for each, 1761da177e4SLinus Torvalds * passing it @data. If @start is not NULL, we use that device to 1771da177e4SLinus Torvalds * begin iterating from. 1781da177e4SLinus Torvalds * 1791da177e4SLinus Torvalds * We check the return of @fn each time. If it returns anything 1801da177e4SLinus Torvalds * other than 0, we break out and return that value. 1811da177e4SLinus Torvalds * 1821da177e4SLinus Torvalds * NOTE: The device that returns a non-zero value is not retained 1831da177e4SLinus Torvalds * in any way, nor is its refcount incremented. If the caller needs 1841da177e4SLinus Torvalds * to retain this data, it should do, and increment the reference 1851da177e4SLinus Torvalds * count in the supplied callback. 1861da177e4SLinus Torvalds */ 1871da177e4SLinus Torvalds 1881da177e4SLinus Torvalds int bus_for_each_dev(struct bus_type * bus, struct device * start, 1891da177e4SLinus Torvalds void * data, int (*fn)(struct device *, void *)) 1901da177e4SLinus Torvalds { 191*465c7a3aSmochel@digitalimplant.org struct klist_iter i; 192*465c7a3aSmochel@digitalimplant.org struct device * dev; 193*465c7a3aSmochel@digitalimplant.org int error = 0; 1941da177e4SLinus Torvalds 195*465c7a3aSmochel@digitalimplant.org if (!bus) 196*465c7a3aSmochel@digitalimplant.org return -EINVAL; 197*465c7a3aSmochel@digitalimplant.org 198*465c7a3aSmochel@digitalimplant.org klist_iter_init_node(&bus->klist_devices, &i, 199*465c7a3aSmochel@digitalimplant.org (start ? &start->knode_bus : NULL)); 200*465c7a3aSmochel@digitalimplant.org while ((dev = next_device(&i)) && !error) 201*465c7a3aSmochel@digitalimplant.org error = fn(dev, data); 202*465c7a3aSmochel@digitalimplant.org klist_iter_exit(&i); 203*465c7a3aSmochel@digitalimplant.org return error; 2041da177e4SLinus Torvalds } 2051da177e4SLinus Torvalds 2061da177e4SLinus Torvalds /** 2071da177e4SLinus Torvalds * bus_for_each_drv - driver iterator 2081da177e4SLinus Torvalds * @bus: bus we're dealing with. 2091da177e4SLinus Torvalds * @start: driver to start iterating on. 2101da177e4SLinus Torvalds * @data: data to pass to the callback. 2111da177e4SLinus Torvalds * @fn: function to call for each driver. 2121da177e4SLinus Torvalds * 2131da177e4SLinus Torvalds * This is nearly identical to the device iterator above. 2141da177e4SLinus Torvalds * We iterate over each driver that belongs to @bus, and call 2151da177e4SLinus Torvalds * @fn for each. If @fn returns anything but 0, we break out 2161da177e4SLinus Torvalds * and return it. If @start is not NULL, we use it as the head 2171da177e4SLinus Torvalds * of the list. 2181da177e4SLinus Torvalds * 2191da177e4SLinus Torvalds * NOTE: we don't return the driver that returns a non-zero 2201da177e4SLinus Torvalds * value, nor do we leave the reference count incremented for that 2211da177e4SLinus Torvalds * driver. If the caller needs to know that info, it must set it 2221da177e4SLinus Torvalds * in the callback. It must also be sure to increment the refcount 2231da177e4SLinus Torvalds * so it doesn't disappear before returning to the caller. 2241da177e4SLinus Torvalds */ 2251da177e4SLinus Torvalds 2261da177e4SLinus Torvalds int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, 2271da177e4SLinus Torvalds void * data, int (*fn)(struct device_driver *, void *)) 2281da177e4SLinus Torvalds { 2291da177e4SLinus Torvalds int ret; 2301da177e4SLinus Torvalds 2311da177e4SLinus Torvalds down_read(&bus->subsys.rwsem); 2321da177e4SLinus Torvalds ret = __bus_for_each_drv(bus, start, data, fn); 2331da177e4SLinus Torvalds up_read(&bus->subsys.rwsem); 2341da177e4SLinus Torvalds return ret; 2351da177e4SLinus Torvalds } 2361da177e4SLinus Torvalds 2371da177e4SLinus Torvalds static int device_add_attrs(struct bus_type * bus, struct device * dev) 2381da177e4SLinus Torvalds { 2391da177e4SLinus Torvalds int error = 0; 2401da177e4SLinus Torvalds int i; 2411da177e4SLinus Torvalds 2421da177e4SLinus Torvalds if (bus->dev_attrs) { 2431da177e4SLinus Torvalds for (i = 0; attr_name(bus->dev_attrs[i]); i++) { 2441da177e4SLinus Torvalds error = device_create_file(dev,&bus->dev_attrs[i]); 2451da177e4SLinus Torvalds if (error) 2461da177e4SLinus Torvalds goto Err; 2471da177e4SLinus Torvalds } 2481da177e4SLinus Torvalds } 2491da177e4SLinus Torvalds Done: 2501da177e4SLinus Torvalds return error; 2511da177e4SLinus Torvalds Err: 2521da177e4SLinus Torvalds while (--i >= 0) 2531da177e4SLinus Torvalds device_remove_file(dev,&bus->dev_attrs[i]); 2541da177e4SLinus Torvalds goto Done; 2551da177e4SLinus Torvalds } 2561da177e4SLinus Torvalds 2571da177e4SLinus Torvalds 2581da177e4SLinus Torvalds static void device_remove_attrs(struct bus_type * bus, struct device * dev) 2591da177e4SLinus Torvalds { 2601da177e4SLinus Torvalds int i; 2611da177e4SLinus Torvalds 2621da177e4SLinus Torvalds if (bus->dev_attrs) { 2631da177e4SLinus Torvalds for (i = 0; attr_name(bus->dev_attrs[i]); i++) 2641da177e4SLinus Torvalds device_remove_file(dev,&bus->dev_attrs[i]); 2651da177e4SLinus Torvalds } 2661da177e4SLinus Torvalds } 2671da177e4SLinus Torvalds 2681da177e4SLinus Torvalds 2691da177e4SLinus Torvalds /** 2701da177e4SLinus Torvalds * bus_add_device - add device to bus 2711da177e4SLinus Torvalds * @dev: device being added 2721da177e4SLinus Torvalds * 2731da177e4SLinus Torvalds * - Add the device to its bus's list of devices. 2741da177e4SLinus Torvalds * - Try to attach to driver. 2751da177e4SLinus Torvalds * - Create link to device's physical location. 2761da177e4SLinus Torvalds */ 2771da177e4SLinus Torvalds int bus_add_device(struct device * dev) 2781da177e4SLinus Torvalds { 2791da177e4SLinus Torvalds struct bus_type * bus = get_bus(dev->bus); 2801da177e4SLinus Torvalds int error = 0; 2811da177e4SLinus Torvalds 2821da177e4SLinus Torvalds if (bus) { 2831da177e4SLinus Torvalds down_write(&dev->bus->subsys.rwsem); 2841da177e4SLinus Torvalds pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id); 2851da177e4SLinus Torvalds list_add_tail(&dev->bus_list, &dev->bus->devices.list); 2861da177e4SLinus Torvalds device_attach(dev); 2871da177e4SLinus Torvalds up_write(&dev->bus->subsys.rwsem); 288*465c7a3aSmochel@digitalimplant.org klist_add_tail(&bus->klist_devices, &dev->knode_bus); 2891da177e4SLinus Torvalds device_add_attrs(bus, dev); 2901da177e4SLinus Torvalds sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id); 2911da177e4SLinus Torvalds sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "bus"); 2921da177e4SLinus Torvalds } 2931da177e4SLinus Torvalds return error; 2941da177e4SLinus Torvalds } 2951da177e4SLinus Torvalds 2961da177e4SLinus Torvalds /** 2971da177e4SLinus Torvalds * bus_remove_device - remove device from bus 2981da177e4SLinus Torvalds * @dev: device to be removed 2991da177e4SLinus Torvalds * 3001da177e4SLinus Torvalds * - Remove symlink from bus's directory. 3011da177e4SLinus Torvalds * - Delete device from bus's list. 3021da177e4SLinus Torvalds * - Detach from its driver. 3031da177e4SLinus Torvalds * - Drop reference taken in bus_add_device(). 3041da177e4SLinus Torvalds */ 3051da177e4SLinus Torvalds void bus_remove_device(struct device * dev) 3061da177e4SLinus Torvalds { 3071da177e4SLinus Torvalds if (dev->bus) { 3081da177e4SLinus Torvalds sysfs_remove_link(&dev->kobj, "bus"); 3091da177e4SLinus Torvalds sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id); 3101da177e4SLinus Torvalds device_remove_attrs(dev->bus, dev); 311*465c7a3aSmochel@digitalimplant.org klist_remove(&dev->knode_bus); 3121da177e4SLinus Torvalds down_write(&dev->bus->subsys.rwsem); 3131da177e4SLinus Torvalds pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id); 3141da177e4SLinus Torvalds device_release_driver(dev); 3151da177e4SLinus Torvalds list_del_init(&dev->bus_list); 3161da177e4SLinus Torvalds up_write(&dev->bus->subsys.rwsem); 3171da177e4SLinus Torvalds put_bus(dev->bus); 3181da177e4SLinus Torvalds } 3191da177e4SLinus Torvalds } 3201da177e4SLinus Torvalds 3211da177e4SLinus Torvalds static int driver_add_attrs(struct bus_type * bus, struct device_driver * drv) 3221da177e4SLinus Torvalds { 3231da177e4SLinus Torvalds int error = 0; 3241da177e4SLinus Torvalds int i; 3251da177e4SLinus Torvalds 3261da177e4SLinus Torvalds if (bus->drv_attrs) { 3271da177e4SLinus Torvalds for (i = 0; attr_name(bus->drv_attrs[i]); i++) { 3281da177e4SLinus Torvalds error = driver_create_file(drv, &bus->drv_attrs[i]); 3291da177e4SLinus Torvalds if (error) 3301da177e4SLinus Torvalds goto Err; 3311da177e4SLinus Torvalds } 3321da177e4SLinus Torvalds } 3331da177e4SLinus Torvalds Done: 3341da177e4SLinus Torvalds return error; 3351da177e4SLinus Torvalds Err: 3361da177e4SLinus Torvalds while (--i >= 0) 3371da177e4SLinus Torvalds driver_remove_file(drv, &bus->drv_attrs[i]); 3381da177e4SLinus Torvalds goto Done; 3391da177e4SLinus Torvalds } 3401da177e4SLinus Torvalds 3411da177e4SLinus Torvalds 3421da177e4SLinus Torvalds static void driver_remove_attrs(struct bus_type * bus, struct device_driver * drv) 3431da177e4SLinus Torvalds { 3441da177e4SLinus Torvalds int i; 3451da177e4SLinus Torvalds 3461da177e4SLinus Torvalds if (bus->drv_attrs) { 3471da177e4SLinus Torvalds for (i = 0; attr_name(bus->drv_attrs[i]); i++) 3481da177e4SLinus Torvalds driver_remove_file(drv, &bus->drv_attrs[i]); 3491da177e4SLinus Torvalds } 3501da177e4SLinus Torvalds } 3511da177e4SLinus Torvalds 3521da177e4SLinus Torvalds 3531da177e4SLinus Torvalds /** 3541da177e4SLinus Torvalds * bus_add_driver - Add a driver to the bus. 3551da177e4SLinus Torvalds * @drv: driver. 3561da177e4SLinus Torvalds * 3571da177e4SLinus Torvalds */ 3581da177e4SLinus Torvalds int bus_add_driver(struct device_driver * drv) 3591da177e4SLinus Torvalds { 3601da177e4SLinus Torvalds struct bus_type * bus = get_bus(drv->bus); 3611da177e4SLinus Torvalds int error = 0; 3621da177e4SLinus Torvalds 3631da177e4SLinus Torvalds if (bus) { 3641da177e4SLinus Torvalds pr_debug("bus %s: add driver %s\n", bus->name, drv->name); 3651da177e4SLinus Torvalds error = kobject_set_name(&drv->kobj, "%s", drv->name); 3661da177e4SLinus Torvalds if (error) { 3671da177e4SLinus Torvalds put_bus(bus); 3681da177e4SLinus Torvalds return error; 3691da177e4SLinus Torvalds } 3701da177e4SLinus Torvalds drv->kobj.kset = &bus->drivers; 3711da177e4SLinus Torvalds if ((error = kobject_register(&drv->kobj))) { 3721da177e4SLinus Torvalds put_bus(bus); 3731da177e4SLinus Torvalds return error; 3741da177e4SLinus Torvalds } 3751da177e4SLinus Torvalds 3761da177e4SLinus Torvalds down_write(&bus->subsys.rwsem); 3771da177e4SLinus Torvalds driver_attach(drv); 3781da177e4SLinus Torvalds up_write(&bus->subsys.rwsem); 3791da177e4SLinus Torvalds module_add_driver(drv->owner, drv); 3801da177e4SLinus Torvalds 3811da177e4SLinus Torvalds driver_add_attrs(bus, drv); 3821da177e4SLinus Torvalds } 3831da177e4SLinus Torvalds return error; 3841da177e4SLinus Torvalds } 3851da177e4SLinus Torvalds 3861da177e4SLinus Torvalds 3871da177e4SLinus Torvalds /** 3881da177e4SLinus Torvalds * bus_remove_driver - delete driver from bus's knowledge. 3891da177e4SLinus Torvalds * @drv: driver. 3901da177e4SLinus Torvalds * 3911da177e4SLinus Torvalds * Detach the driver from the devices it controls, and remove 3921da177e4SLinus Torvalds * it from its bus's list of drivers. Finally, we drop the reference 3931da177e4SLinus Torvalds * to the bus we took in bus_add_driver(). 3941da177e4SLinus Torvalds */ 3951da177e4SLinus Torvalds 3961da177e4SLinus Torvalds void bus_remove_driver(struct device_driver * drv) 3971da177e4SLinus Torvalds { 3981da177e4SLinus Torvalds if (drv->bus) { 3991da177e4SLinus Torvalds driver_remove_attrs(drv->bus, drv); 4001da177e4SLinus Torvalds down_write(&drv->bus->subsys.rwsem); 4011da177e4SLinus Torvalds pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name); 4021da177e4SLinus Torvalds driver_detach(drv); 4031da177e4SLinus Torvalds up_write(&drv->bus->subsys.rwsem); 4041da177e4SLinus Torvalds module_remove_driver(drv); 4051da177e4SLinus Torvalds kobject_unregister(&drv->kobj); 4061da177e4SLinus Torvalds put_bus(drv->bus); 4071da177e4SLinus Torvalds } 4081da177e4SLinus Torvalds } 4091da177e4SLinus Torvalds 4101da177e4SLinus Torvalds 4111da177e4SLinus Torvalds /* Helper for bus_rescan_devices's iter */ 4121da177e4SLinus Torvalds static int bus_rescan_devices_helper(struct device *dev, void *data) 4131da177e4SLinus Torvalds { 4141da177e4SLinus Torvalds int *count = data; 4151da177e4SLinus Torvalds 4161da177e4SLinus Torvalds if (!dev->driver && device_attach(dev)) 4171da177e4SLinus Torvalds (*count)++; 4181da177e4SLinus Torvalds 4191da177e4SLinus Torvalds return 0; 4201da177e4SLinus Torvalds } 4211da177e4SLinus Torvalds 4221da177e4SLinus Torvalds 4231da177e4SLinus Torvalds /** 4241da177e4SLinus Torvalds * bus_rescan_devices - rescan devices on the bus for possible drivers 4251da177e4SLinus Torvalds * @bus: the bus to scan. 4261da177e4SLinus Torvalds * 4271da177e4SLinus Torvalds * This function will look for devices on the bus with no driver 4281da177e4SLinus Torvalds * attached and rescan it against existing drivers to see if it 4291da177e4SLinus Torvalds * matches any. Calls device_attach(). Returns the number of devices 4301da177e4SLinus Torvalds * that were sucessfully bound to a driver. 4311da177e4SLinus Torvalds */ 4321da177e4SLinus Torvalds int bus_rescan_devices(struct bus_type * bus) 4331da177e4SLinus Torvalds { 4341da177e4SLinus Torvalds int count = 0; 4351da177e4SLinus Torvalds 436*465c7a3aSmochel@digitalimplant.org bus_for_each_dev(bus, NULL, &count, bus_rescan_devices_helper); 4371da177e4SLinus Torvalds 4381da177e4SLinus Torvalds return count; 4391da177e4SLinus Torvalds } 4401da177e4SLinus Torvalds 4411da177e4SLinus Torvalds 4421da177e4SLinus Torvalds struct bus_type * get_bus(struct bus_type * bus) 4431da177e4SLinus Torvalds { 4441da177e4SLinus Torvalds return bus ? container_of(subsys_get(&bus->subsys), struct bus_type, subsys) : NULL; 4451da177e4SLinus Torvalds } 4461da177e4SLinus Torvalds 4471da177e4SLinus Torvalds void put_bus(struct bus_type * bus) 4481da177e4SLinus Torvalds { 4491da177e4SLinus Torvalds subsys_put(&bus->subsys); 4501da177e4SLinus Torvalds } 4511da177e4SLinus Torvalds 4521da177e4SLinus Torvalds 4531da177e4SLinus Torvalds /** 4541da177e4SLinus Torvalds * find_bus - locate bus by name. 4551da177e4SLinus Torvalds * @name: name of bus. 4561da177e4SLinus Torvalds * 4571da177e4SLinus Torvalds * Call kset_find_obj() to iterate over list of buses to 4581da177e4SLinus Torvalds * find a bus by name. Return bus if found. 4591da177e4SLinus Torvalds * 4601da177e4SLinus Torvalds * Note that kset_find_obj increments bus' reference count. 4611da177e4SLinus Torvalds */ 4621da177e4SLinus Torvalds 4631da177e4SLinus Torvalds struct bus_type * find_bus(char * name) 4641da177e4SLinus Torvalds { 4651da177e4SLinus Torvalds struct kobject * k = kset_find_obj(&bus_subsys.kset, name); 4661da177e4SLinus Torvalds return k ? to_bus(k) : NULL; 4671da177e4SLinus Torvalds } 4681da177e4SLinus Torvalds 4691da177e4SLinus Torvalds 4701da177e4SLinus Torvalds /** 4711da177e4SLinus Torvalds * bus_add_attrs - Add default attributes for this bus. 4721da177e4SLinus Torvalds * @bus: Bus that has just been registered. 4731da177e4SLinus Torvalds */ 4741da177e4SLinus Torvalds 4751da177e4SLinus Torvalds static int bus_add_attrs(struct bus_type * bus) 4761da177e4SLinus Torvalds { 4771da177e4SLinus Torvalds int error = 0; 4781da177e4SLinus Torvalds int i; 4791da177e4SLinus Torvalds 4801da177e4SLinus Torvalds if (bus->bus_attrs) { 4811da177e4SLinus Torvalds for (i = 0; attr_name(bus->bus_attrs[i]); i++) { 4821da177e4SLinus Torvalds if ((error = bus_create_file(bus,&bus->bus_attrs[i]))) 4831da177e4SLinus Torvalds goto Err; 4841da177e4SLinus Torvalds } 4851da177e4SLinus Torvalds } 4861da177e4SLinus Torvalds Done: 4871da177e4SLinus Torvalds return error; 4881da177e4SLinus Torvalds Err: 4891da177e4SLinus Torvalds while (--i >= 0) 4901da177e4SLinus Torvalds bus_remove_file(bus,&bus->bus_attrs[i]); 4911da177e4SLinus Torvalds goto Done; 4921da177e4SLinus Torvalds } 4931da177e4SLinus Torvalds 4941da177e4SLinus Torvalds static void bus_remove_attrs(struct bus_type * bus) 4951da177e4SLinus Torvalds { 4961da177e4SLinus Torvalds int i; 4971da177e4SLinus Torvalds 4981da177e4SLinus Torvalds if (bus->bus_attrs) { 4991da177e4SLinus Torvalds for (i = 0; attr_name(bus->bus_attrs[i]); i++) 5001da177e4SLinus Torvalds bus_remove_file(bus,&bus->bus_attrs[i]); 5011da177e4SLinus Torvalds } 5021da177e4SLinus Torvalds } 5031da177e4SLinus Torvalds 5041da177e4SLinus Torvalds /** 5051da177e4SLinus Torvalds * bus_register - register a bus with the system. 5061da177e4SLinus Torvalds * @bus: bus. 5071da177e4SLinus Torvalds * 5081da177e4SLinus Torvalds * Once we have that, we registered the bus with the kobject 5091da177e4SLinus Torvalds * infrastructure, then register the children subsystems it has: 5101da177e4SLinus Torvalds * the devices and drivers that belong to the bus. 5111da177e4SLinus Torvalds */ 5121da177e4SLinus Torvalds int bus_register(struct bus_type * bus) 5131da177e4SLinus Torvalds { 5141da177e4SLinus Torvalds int retval; 5151da177e4SLinus Torvalds 5161da177e4SLinus Torvalds retval = kobject_set_name(&bus->subsys.kset.kobj, "%s", bus->name); 5171da177e4SLinus Torvalds if (retval) 5181da177e4SLinus Torvalds goto out; 5191da177e4SLinus Torvalds 5201da177e4SLinus Torvalds subsys_set_kset(bus, bus_subsys); 5211da177e4SLinus Torvalds retval = subsystem_register(&bus->subsys); 5221da177e4SLinus Torvalds if (retval) 5231da177e4SLinus Torvalds goto out; 5241da177e4SLinus Torvalds 5251da177e4SLinus Torvalds kobject_set_name(&bus->devices.kobj, "devices"); 5261da177e4SLinus Torvalds bus->devices.subsys = &bus->subsys; 5271da177e4SLinus Torvalds retval = kset_register(&bus->devices); 5281da177e4SLinus Torvalds if (retval) 5291da177e4SLinus Torvalds goto bus_devices_fail; 5301da177e4SLinus Torvalds 5311da177e4SLinus Torvalds kobject_set_name(&bus->drivers.kobj, "drivers"); 5321da177e4SLinus Torvalds bus->drivers.subsys = &bus->subsys; 5331da177e4SLinus Torvalds bus->drivers.ktype = &ktype_driver; 5341da177e4SLinus Torvalds retval = kset_register(&bus->drivers); 5351da177e4SLinus Torvalds if (retval) 5361da177e4SLinus Torvalds goto bus_drivers_fail; 537*465c7a3aSmochel@digitalimplant.org 538*465c7a3aSmochel@digitalimplant.org klist_init(&bus->klist_devices); 5391da177e4SLinus Torvalds bus_add_attrs(bus); 5401da177e4SLinus Torvalds 5411da177e4SLinus Torvalds pr_debug("bus type '%s' registered\n", bus->name); 5421da177e4SLinus Torvalds return 0; 5431da177e4SLinus Torvalds 5441da177e4SLinus Torvalds bus_drivers_fail: 5451da177e4SLinus Torvalds kset_unregister(&bus->devices); 5461da177e4SLinus Torvalds bus_devices_fail: 5471da177e4SLinus Torvalds subsystem_unregister(&bus->subsys); 5481da177e4SLinus Torvalds out: 5491da177e4SLinus Torvalds return retval; 5501da177e4SLinus Torvalds } 5511da177e4SLinus Torvalds 5521da177e4SLinus Torvalds 5531da177e4SLinus Torvalds /** 5541da177e4SLinus Torvalds * bus_unregister - remove a bus from the system 5551da177e4SLinus Torvalds * @bus: bus. 5561da177e4SLinus Torvalds * 5571da177e4SLinus Torvalds * Unregister the child subsystems and the bus itself. 5581da177e4SLinus Torvalds * Finally, we call put_bus() to release the refcount 5591da177e4SLinus Torvalds */ 5601da177e4SLinus Torvalds void bus_unregister(struct bus_type * bus) 5611da177e4SLinus Torvalds { 5621da177e4SLinus Torvalds pr_debug("bus %s: unregistering\n", bus->name); 5631da177e4SLinus Torvalds bus_remove_attrs(bus); 5641da177e4SLinus Torvalds kset_unregister(&bus->drivers); 5651da177e4SLinus Torvalds kset_unregister(&bus->devices); 5661da177e4SLinus Torvalds subsystem_unregister(&bus->subsys); 5671da177e4SLinus Torvalds } 5681da177e4SLinus Torvalds 5691da177e4SLinus Torvalds int __init buses_init(void) 5701da177e4SLinus Torvalds { 5711da177e4SLinus Torvalds return subsystem_register(&bus_subsys); 5721da177e4SLinus Torvalds } 5731da177e4SLinus Torvalds 5741da177e4SLinus Torvalds 5751da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(bus_for_each_dev); 5761da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(bus_for_each_drv); 5771da177e4SLinus Torvalds 5781da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(bus_add_device); 5791da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(bus_remove_device); 5801da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(bus_register); 5811da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(bus_unregister); 5821da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(bus_rescan_devices); 5831da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(get_bus); 5841da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(put_bus); 5851da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(find_bus); 5861da177e4SLinus Torvalds 5871da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(bus_create_file); 5881da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(bus_remove_file); 589