summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/base/bus.c46
-rw-r--r--drivers/base/driver.c32
-rw-r--r--drivers/base/fs/driver.c78
-rw-r--r--include/linux/device.h1
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;