Commit 8de57ed6 authored by Patrick Mochel's avatar Patrick Mochel

driver model: convert drivers to use kobject and sysfs.

- add kobject to struct device_driver and register it when drivers are registered
  (as member's of their bus's driver subsystem).
- convert driverfs callbacks to know about struct kobject.
- create links from drivers' directories to devices' directories.
- don't even make driverfs directories for drivers anymore. 
parent 289609f0
...@@ -24,7 +24,47 @@ static LIST_HEAD(bus_driver_list); ...@@ -24,7 +24,47 @@ static LIST_HEAD(bus_driver_list);
#define to_bus(obj) container_of(obj,struct bus_type,subsys.kobj) #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) ...@@ -156,6 +196,7 @@ static void attach(struct device * dev)
pr_debug("bound device '%s' to driver '%s'\n", pr_debug("bound device '%s' to driver '%s'\n",
dev->bus_id,dev->driver->name); dev->bus_id,dev->driver->name);
list_add_tail(&dev->driver_list,&dev->driver->devices); 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) static int bus_match(struct device * dev, struct device_driver * drv)
...@@ -226,6 +267,7 @@ static int driver_attach(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) static void detach(struct device * dev, struct device_driver * drv)
{ {
if (drv) { if (drv) {
sysfs_remove_link(&drv->kobj,dev->kobj.name);
list_del_init(&dev->driver_list); list_del_init(&dev->driver_list);
devclass_remove_device(dev); devclass_remove_device(dev);
if (drv->remove) if (drv->remove)
...@@ -304,7 +346,6 @@ int bus_add_driver(struct device_driver * drv) ...@@ -304,7 +346,6 @@ int bus_add_driver(struct device_driver * drv)
list_add_tail(&drv->bus_list,&bus->drivers); list_add_tail(&drv->bus_list,&bus->drivers);
driver_attach(drv); driver_attach(drv);
up_write(&bus->rwsem); up_write(&bus->rwsem);
driver_make_dir(drv);
} }
return 0; return 0;
} }
...@@ -360,6 +401,7 @@ int bus_register(struct bus_type * bus) ...@@ -360,6 +401,7 @@ int bus_register(struct bus_type * bus)
snprintf(bus->drvsubsys.kobj.name,KOBJ_NAME_LEN,"drivers"); snprintf(bus->drvsubsys.kobj.name,KOBJ_NAME_LEN,"drivers");
bus->drvsubsys.parent = &bus->subsys; bus->drvsubsys.parent = &bus->subsys;
bus->drvsubsys.sysfs_ops = &driver_sysfs_ops;
subsystem_register(&bus->drvsubsys); subsystem_register(&bus->drvsubsys);
spin_lock(&device_lock); spin_lock(&device_lock);
......
...@@ -12,6 +12,29 @@ ...@@ -12,6 +12,29 @@
#define to_dev(node) container_of(node,struct device,driver_list) #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 driver_for_each_dev(struct device_driver * drv, void * data,
int (*callback)(struct device *, void * )) int (*callback)(struct device *, void * ))
{ {
...@@ -65,7 +88,6 @@ void put_driver(struct device_driver * drv) ...@@ -65,7 +88,6 @@ void put_driver(struct device_driver * drv)
return; return;
spin_unlock(&device_lock); spin_unlock(&device_lock);
BUG_ON(drv->present); BUG_ON(drv->present);
bus_remove_driver(drv);
if (drv->release) if (drv->release)
drv->release(drv); drv->release(drv);
put_bus(bus); put_bus(bus);
...@@ -84,6 +106,11 @@ int driver_register(struct device_driver * drv) ...@@ -84,6 +106,11 @@ int driver_register(struct device_driver * drv)
pr_debug("driver %s:%s: registering\n",drv->bus->name,drv->name); 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); get_bus(drv->bus);
atomic_set(&drv->refcount,2); atomic_set(&drv->refcount,2);
rwlock_init(&drv->lock); rwlock_init(&drv->lock);
...@@ -108,3 +135,6 @@ EXPORT_SYMBOL(driver_register); ...@@ -108,3 +135,6 @@ EXPORT_SYMBOL(driver_register);
EXPORT_SYMBOL(driver_unregister); EXPORT_SYMBOL(driver_unregister);
EXPORT_SYMBOL(get_driver); EXPORT_SYMBOL(get_driver);
EXPORT_SYMBOL(put_driver); EXPORT_SYMBOL(put_driver);
EXPORT_SYMBOL(driver_create_file);
EXPORT_SYMBOL(driver_remove_file);
...@@ -4,80 +4,6 @@ ...@@ -4,80 +4,6 @@
#include <linux/err.h> #include <linux/err.h>
#include "fs.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 * 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 ...@@ -86,8 +12,6 @@ void driver_remove_file(struct device_driver * drv, struct driver_attribute * at
int driver_make_dir(struct device_driver * drv) int driver_make_dir(struct device_driver * drv)
{ {
drv->dir.name = drv->name; drv->dir.name = drv->name;
drv->dir.ops = &drv_attr_ops;
return device_create_dir(&drv->dir,&drv->bus->driver_dir); return device_create_dir(&drv->dir,&drv->bus->driver_dir);
} }
...@@ -96,5 +20,3 @@ void driver_remove_dir(struct device_driver * drv) ...@@ -96,5 +20,3 @@ void driver_remove_dir(struct device_driver * drv)
driverfs_remove_dir(&drv->dir); driverfs_remove_dir(&drv->dir);
} }
EXPORT_SYMBOL(driver_create_file);
EXPORT_SYMBOL(driver_remove_file);
...@@ -123,6 +123,7 @@ struct device_driver { ...@@ -123,6 +123,7 @@ struct device_driver {
atomic_t refcount; atomic_t refcount;
u32 present; u32 present;
struct kobject kobj;
struct list_head bus_list; struct list_head bus_list;
struct list_head class_list; struct list_head class_list;
struct list_head devices; struct list_head devices;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment