diff options
Diffstat (limited to 'drivers/base/bus.c')
-rw-r--r-- | drivers/base/bus.c | 60 |
1 files changed, 45 insertions, 15 deletions
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index d414331b480e..4c289ab91357 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -17,6 +17,7 @@ #include <linux/init.h> #include <linux/string.h> #include <linux/mutex.h> +#include <linux/sysfs.h> #include "base.h" #include "power/power.h" @@ -165,8 +166,8 @@ static const struct kset_uevent_ops bus_uevent_ops = { static struct kset *bus_kset; /* Manually detach a device from its associated driver. */ -static ssize_t driver_unbind(struct device_driver *drv, - const char *buf, size_t count) +static ssize_t unbind_store(struct device_driver *drv, const char *buf, + size_t count) { struct bus_type *bus = bus_get(drv->bus); struct device *dev; @@ -185,15 +186,15 @@ static ssize_t driver_unbind(struct device_driver *drv, bus_put(bus); return err; } -static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind); +static DRIVER_ATTR_WO(unbind); /* * Manually attach a device to a driver. * Note: the driver must want to bind to the device, * it is not possible to override the driver's id table. */ -static ssize_t driver_bind(struct device_driver *drv, - const char *buf, size_t count) +static ssize_t bind_store(struct device_driver *drv, const char *buf, + size_t count) { struct bus_type *bus = bus_get(drv->bus); struct device *dev; @@ -221,7 +222,7 @@ static ssize_t driver_bind(struct device_driver *drv, bus_put(bus); return err; } -static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind); +static DRIVER_ATTR_WO(bind); static ssize_t show_drivers_autoprobe(struct bus_type *bus, char *buf) { @@ -460,7 +461,7 @@ static int device_add_attrs(struct bus_type *bus, struct device *dev) if (!bus->dev_attrs) return 0; - for (i = 0; attr_name(bus->dev_attrs[i]); i++) { + for (i = 0; bus->dev_attrs[i].attr.name; i++) { error = device_create_file(dev, &bus->dev_attrs[i]); if (error) { while (--i >= 0) @@ -476,7 +477,7 @@ static void device_remove_attrs(struct bus_type *bus, struct device *dev) int i; if (bus->dev_attrs) { - for (i = 0; attr_name(bus->dev_attrs[i]); i++) + for (i = 0; bus->dev_attrs[i].attr.name; i++) device_remove_file(dev, &bus->dev_attrs[i]); } } @@ -499,6 +500,9 @@ int bus_add_device(struct device *dev) error = device_add_attrs(bus, dev); if (error) goto out_put; + error = device_add_groups(dev, bus->dev_groups); + if (error) + goto out_groups; error = sysfs_create_link(&bus->p->devices_kset->kobj, &dev->kobj, dev_name(dev)); if (error) @@ -513,6 +517,8 @@ int bus_add_device(struct device *dev) out_subsys: sysfs_remove_link(&bus->p->devices_kset->kobj, dev_name(dev)); +out_groups: + device_remove_groups(dev, bus->dev_groups); out_id: device_remove_attrs(bus, dev); out_put: @@ -575,6 +581,7 @@ void bus_remove_device(struct device *dev) sysfs_remove_link(&dev->bus->p->devices_kset->kobj, dev_name(dev)); device_remove_attrs(dev->bus, dev); + device_remove_groups(dev, dev->bus->dev_groups); if (klist_node_attached(&dev->p->knode_bus)) klist_del(&dev->p->knode_bus); @@ -590,7 +597,7 @@ static int driver_add_attrs(struct bus_type *bus, struct device_driver *drv) int i; if (bus->drv_attrs) { - for (i = 0; attr_name(bus->drv_attrs[i]); i++) { + for (i = 0; bus->drv_attrs[i].attr.name; i++) { error = driver_create_file(drv, &bus->drv_attrs[i]); if (error) goto err; @@ -610,7 +617,7 @@ static void driver_remove_attrs(struct bus_type *bus, int i; if (bus->drv_attrs) { - for (i = 0; attr_name(bus->drv_attrs[i]); i++) + for (i = 0; bus->drv_attrs[i].attr.name; i++) driver_remove_file(drv, &bus->drv_attrs[i]); } } @@ -659,8 +666,8 @@ static void remove_probe_files(struct bus_type *bus) bus_remove_file(bus, &bus_attr_drivers_probe); } -static ssize_t driver_uevent_store(struct device_driver *drv, - const char *buf, size_t count) +static ssize_t uevent_store(struct device_driver *drv, const char *buf, + size_t count) { enum kobject_action action; @@ -668,7 +675,7 @@ static ssize_t driver_uevent_store(struct device_driver *drv, kobject_uevent(&drv->p->kobj, action); return count; } -static DRIVER_ATTR(uevent, S_IWUSR, NULL, driver_uevent_store); +static DRIVER_ATTR_WO(uevent); /** * bus_add_driver - Add a driver to the bus. @@ -719,6 +726,10 @@ int bus_add_driver(struct device_driver *drv) printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n", __func__, drv->name); } + error = driver_add_groups(drv, bus->drv_groups); + if (error) + printk(KERN_ERR "%s: driver_create_groups(%s) failed\n", + __func__, drv->name); if (!drv->suppress_bind_attrs) { error = add_bind_files(drv); @@ -756,6 +767,7 @@ void bus_remove_driver(struct device_driver *drv) if (!drv->suppress_bind_attrs) remove_bind_files(drv); driver_remove_attrs(drv->bus, drv); + driver_remove_groups(drv, drv->bus->drv_groups); driver_remove_file(drv, &driver_attr_uevent); klist_remove(&drv->p->knode_bus); pr_debug("bus: '%s': remove driver %s\n", drv->bus->name, drv->name); @@ -846,7 +858,7 @@ static int bus_add_attrs(struct bus_type *bus) int i; if (bus->bus_attrs) { - for (i = 0; attr_name(bus->bus_attrs[i]); i++) { + for (i = 0; bus->bus_attrs[i].attr.name; i++) { error = bus_create_file(bus, &bus->bus_attrs[i]); if (error) goto err; @@ -865,11 +877,23 @@ static void bus_remove_attrs(struct bus_type *bus) int i; if (bus->bus_attrs) { - for (i = 0; attr_name(bus->bus_attrs[i]); i++) + for (i = 0; bus->bus_attrs[i].attr.name; i++) bus_remove_file(bus, &bus->bus_attrs[i]); } } +static int bus_add_groups(struct bus_type *bus, + const struct attribute_group **groups) +{ + return sysfs_create_groups(&bus->p->subsys.kobj, groups); +} + +static void bus_remove_groups(struct bus_type *bus, + const struct attribute_group **groups) +{ + sysfs_remove_groups(&bus->p->subsys.kobj, groups); +} + static void klist_devices_get(struct klist_node *n) { struct device_private *dev_prv = to_device_private_bus(n); @@ -962,10 +986,15 @@ int bus_register(struct bus_type *bus) retval = bus_add_attrs(bus); if (retval) goto bus_attrs_fail; + retval = bus_add_groups(bus, bus->bus_groups); + if (retval) + goto bus_groups_fail; pr_debug("bus: '%s': registered\n", bus->name); return 0; +bus_groups_fail: + bus_remove_attrs(bus); bus_attrs_fail: remove_probe_files(bus); bus_probe_files_fail: @@ -996,6 +1025,7 @@ void bus_unregister(struct bus_type *bus) if (bus->dev_root) device_unregister(bus->dev_root); bus_remove_attrs(bus); + bus_remove_groups(bus, bus->bus_groups); remove_probe_files(bus); kset_unregister(bus->p->drivers_kset); kset_unregister(bus->p->devices_kset); |