Commit 117e6adf authored by Patrick Mochel's avatar Patrick Mochel

Merge bk://ldm@bkbits.net/linux-2.5-kobject

into osdl.org:/home/mochel/src/kernel/devel/linux-2.5-kobject
parents b1b782f7 8de57ed6
......@@ -12,6 +12,7 @@
#include <linux/device.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/init.h>
#include "base.h"
static LIST_HEAD(bus_driver_list);
......@@ -19,6 +20,109 @@ static LIST_HEAD(bus_driver_list);
#define to_dev(node) container_of(node,struct device,bus_list)
#define to_drv(node) container_of(node,struct device_driver,bus_list)
#define to_bus_attr(_attr) container_of(_attr,struct bus_attribute,attr)
#define to_bus(obj) container_of(obj,struct bus_type,subsys.kobj)
/*
* 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
*/
static ssize_t
bus_attr_show(struct kobject * kobj, struct attribute * attr,
char * buf, size_t count, loff_t off)
{
struct bus_attribute * bus_attr = to_bus_attr(attr);
struct bus_type * bus = to_bus(kobj);
ssize_t ret = 0;
if (bus_attr->show)
ret = bus_attr->show(bus,buf,count,off);
return ret;
}
static ssize_t
bus_attr_store(struct kobject * kobj, struct attribute * attr,
const char * buf, size_t count, loff_t off)
{
struct bus_attribute * bus_attr = to_bus_attr(attr);
struct bus_type * bus = to_bus(kobj);
ssize_t ret = 0;
if (bus_attr->store)
ret = bus_attr->store(bus,buf,count,off);
return ret;
}
static struct sysfs_ops bus_sysfs_ops = {
.show = bus_attr_show,
.store = bus_attr_store,
};
int bus_create_file(struct bus_type * bus, struct bus_attribute * attr)
{
int error;
if (get_bus(bus)) {
error = sysfs_create_file(&bus->subsys.kobj,&attr->attr);
put_bus(bus);
} else
error = -EINVAL;
return error;
}
void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr)
{
if (get_bus(bus)) {
sysfs_remove_file(&bus->subsys.kobj,&attr->attr);
put_bus(bus);
}
}
struct subsystem bus_subsys = {
.kobj = { .name = "bus" },
.sysfs_ops = &bus_sysfs_ops,
};
/**
* bus_for_each_dev - walk list of devices and do something to each
* @bus: bus in question
......@@ -92,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)
......@@ -162,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)
......@@ -206,7 +312,7 @@ int bus_add_device(struct device * dev)
list_add_tail(&dev->bus_list,&dev->bus->devices);
device_attach(dev);
up_write(&dev->bus->rwsem);
device_bus_link(dev);
sysfs_create_link(&bus->devsubsys.kobj,&dev->kobj,dev->bus_id);
}
return 0;
}
......@@ -221,9 +327,9 @@ int bus_add_device(struct device * dev)
void bus_remove_device(struct device * dev)
{
if (dev->bus) {
sysfs_remove_link(&dev->bus->devsubsys.kobj,dev->bus_id);
down_write(&dev->bus->rwsem);
pr_debug("bus %s: remove device %s\n",dev->bus->name,dev->bus_id);
device_remove_symlink(&dev->bus->device_dir,dev->bus_id);
device_detach(dev);
list_del_init(&dev->bus_list);
up_write(&dev->bus->rwsem);
......@@ -240,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;
}
......@@ -286,6 +391,19 @@ int bus_register(struct bus_type * bus)
atomic_set(&bus->refcount,2);
bus->present = 1;
strncpy(bus->subsys.kobj.name,bus->name,KOBJ_NAME_LEN);
bus->subsys.parent = &bus_subsys;
subsystem_register(&bus->subsys);
snprintf(bus->devsubsys.kobj.name,KOBJ_NAME_LEN,"devices");
bus->devsubsys.parent = &bus->subsys;
subsystem_register(&bus->devsubsys);
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);
list_add_tail(&bus->node,&bus_driver_list);
spin_unlock(&device_lock);
......@@ -309,6 +427,13 @@ void bus_unregister(struct bus_type * bus)
put_bus(bus);
}
static int __init bus_subsys_init(void)
{
return subsystem_register(&bus_subsys);
}
core_initcall(bus_subsys_init);
EXPORT_SYMBOL(bus_for_each_dev);
EXPORT_SYMBOL(bus_for_each_drv);
EXPORT_SYMBOL(bus_add_device);
......@@ -317,3 +442,6 @@ EXPORT_SYMBOL(bus_register);
EXPORT_SYMBOL(bus_unregister);
EXPORT_SYMBOL(get_bus);
EXPORT_SYMBOL(put_bus);
EXPORT_SYMBOL(bus_create_file);
EXPORT_SYMBOL(bus_remove_file);
......@@ -23,7 +23,76 @@ DECLARE_MUTEX(device_sem);
spinlock_t device_lock = SPIN_LOCK_UNLOCKED;
#define to_dev(node) container_of(node,struct device,driver_list)
struct subsystem device_subsys;
#define to_dev(obj) container_of(obj,struct device,kobj)
/*
* sysfs bindings for devices.
*/
#define to_dev_attr(_attr) container_of(_attr,struct device_attribute,attr)
extern struct attribute * dev_default_attrs[];
static ssize_t
dev_attr_show(struct kobject * kobj, struct attribute * attr,
char * buf, size_t count, loff_t off)
{
struct device_attribute * dev_attr = to_dev_attr(attr);
struct device * dev = to_dev(kobj);
ssize_t ret = 0;
if (dev_attr->show)
ret = dev_attr->show(dev,buf,count,off);
return ret;
}
static ssize_t
dev_attr_store(struct kobject * kobj, struct attribute * attr,
const char * buf, size_t count, loff_t off)
{
struct device_attribute * dev_attr = to_dev_attr(attr);
struct device * dev = to_dev(kobj);
ssize_t ret = 0;
if (dev_attr->store)
ret = dev_attr->store(dev,buf,count,off);
return ret;
}
static struct sysfs_ops dev_sysfs_ops = {
.show = dev_attr_show,
.store = dev_attr_store,
};
struct subsystem device_subsys = {
.kobj = {
.name = "devices",
},
.sysfs_ops = &dev_sysfs_ops,
.default_attrs = dev_default_attrs,
};
int device_create_file(struct device * dev, struct device_attribute * attr)
{
int error = 0;
if (get_device(dev)) {
error = sysfs_create_file(&dev->kobj,&attr->attr);
put_device(dev);
}
return error;
}
void device_remove_file(struct device * dev, struct device_attribute * attr)
{
if (get_device(dev)) {
sysfs_remove_file(&dev->kobj,&attr->attr);
put_device(dev);
}
}
int device_add(struct device *dev)
{
......@@ -44,6 +113,12 @@ int device_add(struct device *dev)
pr_debug("DEV: registering device: ID = '%s', name = %s\n",
dev->bus_id, dev->name);
strncpy(dev->kobj.name,dev->bus_id,KOBJ_NAME_LEN);
if (dev->parent)
dev->kobj.parent = &dev->parent->kobj;
dev->kobj.subsys = &device_subsys;
kobject_register(&dev->kobj);
if ((error = device_make_dir(dev)))
goto register_done;
......@@ -69,6 +144,7 @@ int device_add(struct device *dev)
void device_initialize(struct device *dev)
{
kobject_init(&dev->kobj);
INIT_LIST_HEAD(&dev->node);
INIT_LIST_HEAD(&dev->children);
INIT_LIST_HEAD(&dev->g_list);
......@@ -184,9 +260,17 @@ void device_unregister(struct device * dev)
pr_debug("DEV: Unregistering device. ID = '%s', name = '%s'\n",
dev->bus_id,dev->name);
kobject_unregister(&dev->kobj);
put_device(dev);
}
static int __init device_subsys_init(void)
{
return subsystem_register(&device_subsys);
}
core_initcall(device_subsys_init);
EXPORT_SYMBOL(device_register);
EXPORT_SYMBOL(device_unregister);
EXPORT_SYMBOL(get_device);
......
......@@ -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);
......@@ -6,86 +6,10 @@
static struct driver_dir_entry bus_dir;
#define to_bus_attr(_attr) container_of(_attr,struct bus_attribute,attr)
#define to_bus(dir) container_of(dir,struct bus_type,dir)
/* driverfs ops for device attribute files */
static int
bus_attr_open(struct driver_dir_entry * dir)
{
struct bus_type * bus = to_bus(dir);
get_bus(bus);
return 0;
}
static int
bus_attr_close(struct driver_dir_entry * dir)
{
struct bus_type * bus = to_bus(dir);
put_bus(bus);
return 0;
}
static ssize_t
bus_attr_show(struct driver_dir_entry * dir, struct attribute * attr,
char * buf, size_t count, loff_t off)
{
struct bus_attribute * bus_attr = to_bus_attr(attr);
struct bus_type * bus = to_bus(dir);
ssize_t ret = 0;
if (bus_attr->show)
ret = bus_attr->show(bus,buf,count,off);
return ret;
}
static ssize_t
bus_attr_store(struct driver_dir_entry * dir, struct attribute * attr,
const char * buf, size_t count, loff_t off)
{
struct bus_attribute * bus_attr = to_bus_attr(attr);
struct bus_type * bus = to_bus(dir);
ssize_t ret = 0;
if (bus_attr->store)
ret = bus_attr->store(bus,buf,count,off);
return ret;
}
static struct driverfs_ops bus_attr_ops = {
.open = bus_attr_open,
.close = bus_attr_close,
.show = bus_attr_show,
.store = bus_attr_store,
};
int bus_create_file(struct bus_type * bus, struct bus_attribute * attr)
{
int error;
if (get_bus(bus)) {
error = driverfs_create_file(&attr->attr,&bus->dir);
put_bus(bus);
} else
error = -EINVAL;
return error;
}
void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr)
{
if (get_bus(bus)) {
driverfs_remove_file(&bus->dir,attr->attr.name);
put_bus(bus);
}
}
int bus_make_dir(struct bus_type * bus)
{
int error;
bus->dir.name = bus->name;
bus->dir.ops = &bus_attr_ops;
error = device_create_dir(&bus->dir,&bus_dir);
if (!error) {
......@@ -119,5 +43,3 @@ static int __init bus_init(void)
core_initcall(bus_init);
EXPORT_SYMBOL(bus_create_file);
EXPORT_SYMBOL(bus_remove_file);
......@@ -21,97 +21,6 @@ static struct driver_dir_entry device_root_dir = {
.mode = (S_IRWXU | S_IRUGO | S_IXUGO),
};
extern struct device_attribute * device_default_files[];
#define to_dev_attr(_attr) container_of(_attr,struct device_attribute,attr)
#define to_device(d) container_of(d, struct device, dir)
/* driverfs ops for device attribute files */
static int
dev_attr_open(struct driver_dir_entry * dir)
{
struct device * dev = to_device(dir);
get_device(dev);
return 0;
}
static int
dev_attr_close(struct driver_dir_entry * dir)
{
struct device * dev = to_device(dir);
put_device(dev);
return 0;
}
static ssize_t
dev_attr_show(struct driver_dir_entry * dir, struct attribute * attr,
char * buf, size_t count, loff_t off)
{
struct device_attribute * dev_attr = to_dev_attr(attr);
struct device * dev = to_device(dir);
ssize_t ret = 0;
if (dev_attr->show)
ret = dev_attr->show(dev,buf,count,off);
return ret;
}
static ssize_t
dev_attr_store(struct driver_dir_entry * dir, struct attribute * attr,
const char * buf, size_t count, loff_t off)
{
struct device_attribute * dev_attr = to_dev_attr(attr);
struct device * dev = to_device(dir);
ssize_t ret = 0;
if (dev_attr->store)
ret = dev_attr->store(dev,buf,count,off);
return ret;
}
static struct driverfs_ops dev_attr_ops = {
.open = dev_attr_open,
.close = dev_attr_close,
.show = dev_attr_show,
.store = dev_attr_store,
};
/**
* device_create_file - create a driverfs file for a device
* @dev: device requesting file
* @entry: entry describing file
*
* Allocate space for file entry, copy descriptor, and create.
*/
int device_create_file(struct device * dev, struct device_attribute * entry)
{
int error = -EINVAL;
if (get_device(dev)) {
error = driverfs_create_file(&entry->attr,&dev->dir);
put_device(dev);
}
return error;
}
/**
* device_remove_file - remove a device's file by name
* @dev: device requesting removal
* @name: name of the file
*
*/
void device_remove_file(struct device * dev, struct device_attribute * attr)
{
if (dev) {
get_device(dev);
driverfs_remove_file(&dev->dir,attr->attr.name);
put_device(dev);
}
}
/**
* device_remove_dir - remove a device's directory
* @dev: device in question
......@@ -213,24 +122,12 @@ int device_create_dir(struct driver_dir_entry * dir, struct driver_dir_entry * p
int device_make_dir(struct device * dev)
{
struct driver_dir_entry * parent;
struct device_attribute * entry;
int error;
int i;
parent = dev->parent ? &dev->parent->dir : &device_root_dir;
dev->dir.name = dev->bus_id;
dev->dir.ops = &dev_attr_ops;
if ((error = device_create_dir(&dev->dir,parent)))
return error;
for (i = 0; (entry = *(device_default_files + i)); i++) {
if ((error = device_create_file(dev,entry))) {
device_remove_dir(dev);
break;
}
}
return error;
return device_create_dir(&dev->dir,parent);
}
static int device_driverfs_init(void)
......
......@@ -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);
......@@ -88,8 +88,8 @@ device_write_power(struct device * dev, const char * buf, size_t count, loff_t o
static DEVICE_ATTR(power,S_IWUSR | S_IRUGO,
device_read_power,device_write_power);
struct device_attribute * device_default_files[] = {
&dev_attr_name,
&dev_attr_power,
struct attribute * dev_default_attrs[] = {
&dev_attr_name.attr,
&dev_attr_power.attr,
NULL,
};
......@@ -29,6 +29,7 @@
#include <linux/list.h>
#include <linux/sched.h>
#include <linux/driverfs_fs.h>
#include <linux/kobject.h>
#define DEVICE_NAME_SIZE 80
#define DEVICE_ID_SIZE 32
......@@ -65,6 +66,9 @@ struct bus_type {
atomic_t refcount;
u32 present;
struct subsystem subsys;
struct subsystem drvsubsys;
struct subsystem devsubsys;
struct list_head node;
struct list_head devices;
struct list_head drivers;
......@@ -119,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;
......@@ -275,6 +280,7 @@ struct device {
struct list_head intf_list;
struct device * parent;
struct kobject kobj;
char name[DEVICE_NAME_SIZE]; /* descriptive ascii string */
char bus_id[BUS_ID_SIZE]; /* position on parent bus */
......
......@@ -26,6 +26,8 @@
#ifndef _DRIVER_FS_H_
#define _DRIVER_FS_H_
#include <linux/sysfs.h>
struct driver_dir_entry;
struct attribute;
......@@ -43,11 +45,6 @@ struct driver_dir_entry {
struct driverfs_ops * ops;
};
struct attribute {
char * name;
mode_t mode;
};
extern int
driverfs_create_dir(struct driver_dir_entry *, struct driver_dir_entry *);
......
......@@ -12,8 +12,10 @@
#include <linux/rwsem.h>
#include <asm/atomic.h>
#define KOBJ_NAME_LEN 16
struct kobject {
char name[16];
char name[KOBJ_NAME_LEN];
atomic_t refcount;
struct list_head entry;
struct kobject * parent;
......
......@@ -9,20 +9,18 @@
#ifndef _SYSFS_H_
#define _SYSFS_H_
struct driver_dir_entry;
struct attribute;
struct kobject;
struct sysfs_ops {
ssize_t (*show)(struct kobject *, struct attribute *,char *, size_t, loff_t);
ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t, loff_t);
};
struct attribute {
char * name;
mode_t mode;
};
struct sysfs_ops {
ssize_t (*show)(struct kobject *, struct attribute *,char *, size_t, loff_t);
ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t, loff_t);
};
extern int
sysfs_create_dir(struct kobject *);
......
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