diff options
| -rw-r--r-- | drivers/base/bus.c | 46 | ||||
| -rw-r--r-- | drivers/base/driver.c | 32 | ||||
| -rw-r--r-- | drivers/base/fs/driver.c | 78 | ||||
| -rw-r--r-- | include/linux/device.h | 1 |
4 files changed, 76 insertions, 81 deletions
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 57fd83004240..8428b8f1acd3 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -24,7 +24,47 @@ static LIST_HEAD(bus_driver_list); #define to_bus(obj) container_of(obj,struct bus_type,subsys.kobj) /* - * sysfs bindings for buses + * sysfs bindings for drivers + */ + +#define to_drv_attr(_attr) container_of(_attr,struct driver_attribute,attr) +#define to_driver(obj) container_of(obj, struct device_driver, kobj) + + +static ssize_t +drv_attr_show(struct kobject * kobj, struct attribute * attr, + char * buf, size_t count, loff_t off) +{ + struct driver_attribute * drv_attr = to_drv_attr(attr); + struct device_driver * drv = to_driver(kobj); + ssize_t ret = 0; + + if (drv_attr->show) + ret = drv_attr->show(drv,buf,count,off); + return ret; +} + +static ssize_t +drv_attr_store(struct kobject * kobj, struct attribute * attr, + const char * buf, size_t count, loff_t off) +{ + struct driver_attribute * drv_attr = to_drv_attr(attr); + struct device_driver * drv = to_driver(kobj); + ssize_t ret = 0; + + if (drv_attr->store) + ret = drv_attr->store(drv,buf,count,off); + return ret; +} + +static struct sysfs_ops driver_sysfs_ops = { + .show = drv_attr_show, + .store = drv_attr_store, +}; + + +/* + * sysfs bindings for drivers */ @@ -156,6 +196,7 @@ static void attach(struct device * dev) pr_debug("bound device '%s' to driver '%s'\n", dev->bus_id,dev->driver->name); list_add_tail(&dev->driver_list,&dev->driver->devices); + sysfs_create_link(&dev->driver->kobj,&dev->kobj,dev->kobj.name); } static int bus_match(struct device * dev, struct device_driver * drv) @@ -226,6 +267,7 @@ static int driver_attach(struct device_driver * drv) static void detach(struct device * dev, struct device_driver * drv) { if (drv) { + sysfs_remove_link(&drv->kobj,dev->kobj.name); list_del_init(&dev->driver_list); devclass_remove_device(dev); if (drv->remove) @@ -304,7 +346,6 @@ int bus_add_driver(struct device_driver * drv) list_add_tail(&drv->bus_list,&bus->drivers); driver_attach(drv); up_write(&bus->rwsem); - driver_make_dir(drv); } return 0; } @@ -360,6 +401,7 @@ int bus_register(struct bus_type * bus) snprintf(bus->drvsubsys.kobj.name,KOBJ_NAME_LEN,"drivers"); bus->drvsubsys.parent = &bus->subsys; + bus->drvsubsys.sysfs_ops = &driver_sysfs_ops; subsystem_register(&bus->drvsubsys); spin_lock(&device_lock); diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 4bf4a005b918..f940cc4c5165 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -12,6 +12,29 @@ #define to_dev(node) container_of(node,struct device,driver_list) +/* + * helpers for creating driver attributes in sysfs + */ + +int driver_create_file(struct device_driver * drv, struct driver_attribute * attr) +{ + int error; + if (get_driver(drv)) { + error = sysfs_create_file(&drv->kobj,&attr->attr); + put_driver(drv); + } else + error = -EINVAL; + return error; +} + +void driver_remove_file(struct device_driver * drv, struct driver_attribute * attr) +{ + if (get_driver(drv)) { + sysfs_remove_file(&drv->kobj,&attr->attr); + put_driver(drv); + } +} + int driver_for_each_dev(struct device_driver * drv, void * data, int (*callback)(struct device *, void * )) { @@ -65,7 +88,6 @@ void put_driver(struct device_driver * drv) return; spin_unlock(&device_lock); BUG_ON(drv->present); - bus_remove_driver(drv); if (drv->release) drv->release(drv); put_bus(bus); @@ -84,6 +106,11 @@ int driver_register(struct device_driver * drv) pr_debug("driver %s:%s: registering\n",drv->bus->name,drv->name); + kobject_init(&drv->kobj); + strncpy(drv->kobj.name,drv->name,KOBJ_NAME_LEN); + drv->kobj.subsys = &drv->bus->drvsubsys; + kobject_register(&drv->kobj); + get_bus(drv->bus); atomic_set(&drv->refcount,2); rwlock_init(&drv->lock); @@ -108,3 +135,6 @@ EXPORT_SYMBOL(driver_register); EXPORT_SYMBOL(driver_unregister); EXPORT_SYMBOL(get_driver); EXPORT_SYMBOL(put_driver); + +EXPORT_SYMBOL(driver_create_file); +EXPORT_SYMBOL(driver_remove_file); diff --git a/drivers/base/fs/driver.c b/drivers/base/fs/driver.c index c70834d738fc..c259470c7bb6 100644 --- a/drivers/base/fs/driver.c +++ b/drivers/base/fs/driver.c @@ -4,80 +4,6 @@ #include <linux/err.h> #include "fs.h" -#define to_drv_attr(_attr) container_of(_attr,struct driver_attribute,attr) - -#define to_drv(d) container_of(d, struct device_driver, dir) - - -/* driverfs ops for device attribute files */ - -static int -drv_attr_open(struct driver_dir_entry * dir) -{ - struct device_driver * drv = to_drv(dir); - get_driver(drv); - return 0; -} - -static int -drv_attr_close(struct driver_dir_entry * dir) -{ - struct device_driver * drv = to_drv(dir); - put_driver(drv); - return 0; -} - -static ssize_t -drv_attr_show(struct driver_dir_entry * dir, struct attribute * attr, - char * buf, size_t count, loff_t off) -{ - struct driver_attribute * drv_attr = to_drv_attr(attr); - struct device_driver * drv = to_drv(dir); - ssize_t ret = 0; - - if (drv_attr->show) - ret = drv_attr->show(drv,buf,count,off); - return ret; -} - -static ssize_t -drv_attr_store(struct driver_dir_entry * dir, struct attribute * attr, - const char * buf, size_t count, loff_t off) -{ - struct driver_attribute * drv_attr = to_drv_attr(attr); - struct device_driver * drv = to_drv(dir); - ssize_t ret = 0; - - if (drv_attr->store) - ret = drv_attr->store(drv,buf,count,off); - return ret; -} - -static struct driverfs_ops drv_attr_ops = { - .open = drv_attr_open, - .close = drv_attr_close, - .show = drv_attr_show, - .store = drv_attr_store, -}; - -int driver_create_file(struct device_driver * drv, struct driver_attribute * attr) -{ - int error; - if (get_driver(drv)) { - error = driverfs_create_file(&attr->attr,&drv->dir); - put_driver(drv); - } else - error = -EINVAL; - return error; -} - -void driver_remove_file(struct device_driver * drv, struct driver_attribute * attr) -{ - if (get_driver(drv)) { - driverfs_remove_file(&drv->dir,attr->attr.name); - put_driver(drv); - } -} /** * driver_make_dir - create a driverfs directory for a driver @@ -86,8 +12,6 @@ void driver_remove_file(struct device_driver * drv, struct driver_attribute * at int driver_make_dir(struct device_driver * drv) { drv->dir.name = drv->name; - drv->dir.ops = &drv_attr_ops; - return device_create_dir(&drv->dir,&drv->bus->driver_dir); } @@ -96,5 +20,3 @@ void driver_remove_dir(struct device_driver * drv) driverfs_remove_dir(&drv->dir); } -EXPORT_SYMBOL(driver_create_file); -EXPORT_SYMBOL(driver_remove_file); diff --git a/include/linux/device.h b/include/linux/device.h index 66d4f313a809..5ce759266658 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -123,6 +123,7 @@ struct device_driver { atomic_t refcount; u32 present; + struct kobject kobj; struct list_head bus_list; struct list_head class_list; struct list_head devices; |
