Commit 0447d4d5 authored by Patrick Mochel's avatar Patrick Mochel

Merge osdl.org:/home/mochel/src/kernel/devel/linux-2.5-virgin

into osdl.org:/home/mochel/src/kernel/devel/linux-2.5-core
parents 9af95a10 ba809e8a
......@@ -47,23 +47,21 @@ int bus_for_each_dev(struct bus_type * bus, void * data,
int error = 0;
get_bus(bus);
spin_lock(&device_lock);
down_write(&bus->rwsem);
list_for_each(node,&bus->devices) {
struct device * dev = get_device_locked(to_dev(node));
struct device * dev = get_device(to_dev(node));
if (dev) {
spin_unlock(&device_lock);
error = callback(dev,data);
if (prev)
put_device(prev);
prev = dev;
spin_lock(&device_lock);
if (error)
break;
}
}
spin_unlock(&device_lock);
if (prev)
put_device(prev);
up_write(&bus->rwsem);
put_bus(bus);
return error;
}
......@@ -77,24 +75,21 @@ int bus_for_each_drv(struct bus_type * bus, void * data,
/* pin bus in memory */
get_bus(bus);
spin_lock(&device_lock);
down_write(&bus->rwsem);
list_for_each(node,&bus->drivers) {
struct device_driver * drv = get_driver(to_drv(node));
if (drv) {
spin_unlock(&device_lock);
error = callback(drv,data);
if (prev)
put_driver(prev);
prev = drv;
spin_lock(&device_lock);
if (error)
break;
}
}
spin_unlock(&device_lock);
if (prev)
put_driver(prev);
up_write(&bus->rwsem);
put_bus(bus);
return error;
}
......@@ -111,11 +106,11 @@ int bus_for_each_drv(struct bus_type * bus, void * data,
int bus_add_device(struct device * dev)
{
if (dev->bus) {
down_write(&dev->bus->rwsem);
pr_debug("registering %s with bus '%s'\n",dev->bus_id,dev->bus->name);
get_bus(dev->bus);
spin_lock(&device_lock);
list_add_tail(&dev->bus_list,&dev->bus->devices);
spin_unlock(&device_lock);
up_write(&dev->bus->rwsem);
device_bus_link(dev);
}
return 0;
......@@ -131,17 +126,43 @@ int bus_add_device(struct device * dev)
void bus_remove_device(struct device * dev)
{
if (dev->bus) {
down_write(&dev->bus->rwsem);
list_del_init(&dev->bus_list);
device_remove_symlink(&dev->bus->device_dir,dev->bus_id);
up_write(&dev->bus->rwsem);
put_bus(dev->bus);
}
}
struct bus_type * get_bus(struct bus_type * bus)
{
struct bus_type * ret = bus;
spin_lock(&device_lock);
if (bus && bus->present && atomic_read(&bus->refcount))
atomic_inc(&bus->refcount);
else
ret = NULL;
spin_unlock(&device_lock);
return ret;
}
void put_bus(struct bus_type * bus)
{
if (!atomic_dec_and_lock(&bus->refcount,&device_lock))
return;
list_del_init(&bus->node);
spin_unlock(&device_lock);
BUG_ON(bus->present);
bus_remove_dir(bus);
}
int bus_register(struct bus_type * bus)
{
rwlock_init(&bus->lock);
init_rwsem(&bus->rwsem);
INIT_LIST_HEAD(&bus->devices);
INIT_LIST_HEAD(&bus->drivers);
atomic_set(&bus->refcount,2);
bus->present = 1;
spin_lock(&device_lock);
list_add_tail(&bus->node,&bus_driver_list);
......@@ -156,13 +177,14 @@ int bus_register(struct bus_type * bus)
return 0;
}
void put_bus(struct bus_type * bus)
void bus_unregister(struct bus_type * bus)
{
if (!atomic_dec_and_lock(&bus->refcount,&device_lock))
return;
list_del_init(&bus->node);
spin_lock(&device_lock);
bus->present = 0;
spin_unlock(&device_lock);
bus_remove_dir(bus);
pr_debug("bus %s: unregistering\n",bus->name);
put_bus(bus);
}
EXPORT_SYMBOL(bus_for_each_dev);
......@@ -170,4 +192,6 @@ EXPORT_SYMBOL(bus_for_each_drv);
EXPORT_SYMBOL(bus_add_device);
EXPORT_SYMBOL(bus_remove_device);
EXPORT_SYMBOL(bus_register);
EXPORT_SYMBOL(bus_unregister);
EXPORT_SYMBOL(get_bus);
EXPORT_SYMBOL(put_bus);
......@@ -81,29 +81,55 @@ void devclass_remove_device(struct device * dev)
}
}
struct device_class * get_devclass(struct device_class * cls)
{
struct device_class * ret = cls;
spin_lock(&device_lock);
if (cls && cls->present && atomic_read(&cls->refcount) > 0)
atomic_inc(&cls->refcount);
else
ret = NULL;
spin_unlock(&device_lock);
return ret;
}
void put_devclass(struct device_class * cls)
{
if (atomic_dec_and_lock(&cls->refcount,&device_lock)) {
list_del_init(&cls->node);
spin_unlock(&device_lock);
devclass_remove_dir(cls);
}
}
int devclass_register(struct device_class * cls)
{
INIT_LIST_HEAD(&cls->drivers);
INIT_LIST_HEAD(&cls->intf_list);
pr_debug("registering device class '%s'\n",cls->name);
atomic_set(&cls->refcount,2);
cls->present = 1;
pr_debug("device class '%s': registering\n",cls->name);
spin_lock(&device_lock);
list_add_tail(&cls->node,&class_list);
spin_unlock(&device_lock);
devclass_make_dir(cls);
put_devclass(cls);
return 0;
}
void devclass_unregister(struct device_class * cls)
{
pr_debug("unregistering device class '%s'\n",cls->name);
devclass_remove_dir(cls);
spin_lock(&device_lock);
list_del_init(&class_list);
cls->present = 0;
spin_unlock(&device_lock);
pr_debug("device class '%s': unregistering\n",cls->name);
put_devclass(cls);
}
EXPORT_SYMBOL(devclass_register);
EXPORT_SYMBOL(devclass_unregister);
EXPORT_SYMBOL(get_devclass);
EXPORT_SYMBOL(put_devclass);
......@@ -259,34 +259,21 @@ struct device * get_device(struct device * dev)
*/
void put_device(struct device * dev)
{
struct device * parent;
if (!atomic_dec_and_lock(&dev->refcount,&device_lock))
return;
parent = dev->parent;
dev->parent = NULL;
list_del_init(&dev->node);
list_del_init(&dev->g_list);
list_del_init(&dev->driver_list);
spin_unlock(&device_lock);
BUG_ON(dev->present);
if (dev->release)
dev->release(dev);
if (parent)
put_device(parent);
device_del(dev);
}
void device_del(struct device * dev)
{
spin_lock(&device_lock);
dev->present = 0;
list_del_init(&dev->node);
list_del_init(&dev->g_list);
list_del_init(&dev->bus_list);
list_del_init(&dev->driver_list);
spin_unlock(&device_lock);
pr_debug("DEV: Unregistering device. ID = '%s', name = '%s'\n",
dev->bus_id,dev->name);
struct device * parent = dev->parent;
/* Notify the platform of the removal, in case they
* need to do anything...
......@@ -302,6 +289,12 @@ void device_del(struct device * dev)
/* remove the driverfs directory */
device_remove_dir(dev);
if (dev->release)
dev->release(dev);
if (parent)
put_device(parent);
}
/**
......@@ -315,22 +308,15 @@ void device_del(struct device * dev)
*/
void device_unregister(struct device * dev)
{
device_del(dev);
put_device(dev);
}
static int __init device_init(void)
{
int error;
spin_lock(&device_lock);
dev->present = 0;
spin_unlock(&device_lock);
error = init_driverfs_fs();
if (error)
panic("DEV: could not initialize driverfs");
return 0;
pr_debug("DEV: Unregistering device. ID = '%s', name = '%s'\n",
dev->bus_id,dev->name);
put_device(dev);
}
core_initcall(device_init);
EXPORT_SYMBOL(device_register);
EXPORT_SYMBOL(device_unregister);
EXPORT_SYMBOL(get_device);
......
......@@ -39,6 +39,43 @@ int driver_for_each_dev(struct device_driver * drv, void * data,
return error;
}
struct device_driver * get_driver(struct device_driver * drv)
{
struct device_driver * ret = drv;
spin_lock(&device_lock);
if (drv && drv->present && atomic_read(&drv->refcount) > 0)
atomic_inc(&drv->refcount);
else
ret = NULL;
spin_unlock(&device_lock);
return ret;
}
void remove_driver(struct device_driver * drv)
{
BUG();
}
/**
* put_driver - decrement driver's refcount and clean up if necessary
* @drv: driver in question
*/
void put_driver(struct device_driver * drv)
{
struct bus_type * bus = drv->bus;
if (!atomic_dec_and_lock(&drv->refcount,&device_lock))
return;
list_del_init(&drv->bus_list);
spin_unlock(&device_lock);
BUG_ON(drv->present);
driver_detach(drv);
driver_remove_dir(drv);
if (drv->release)
drv->release(drv);
put_bus(bus);
}
/**
* driver_register - register driver with bus
* @drv: driver to register
......@@ -50,12 +87,13 @@ int driver_register(struct device_driver * drv)
if (!drv->bus)
return -EINVAL;
pr_debug("Registering driver '%s' with bus '%s'\n",drv->name,drv->bus->name);
pr_debug("driver %s:%s: registering\n",drv->bus->name,drv->name);
get_bus(drv->bus);
atomic_set(&drv->refcount,2);
rwlock_init(&drv->lock);
INIT_LIST_HEAD(&drv->devices);
drv->present = 1;
spin_lock(&device_lock);
list_add(&drv->bus_list,&drv->bus->drivers);
spin_unlock(&device_lock);
......@@ -65,39 +103,17 @@ int driver_register(struct device_driver * drv)
return 0;
}
static void __remove_driver(struct device_driver * drv)
{
pr_debug("Unregistering driver '%s' from bus '%s'\n",drv->name,drv->bus->name);
driver_detach(drv);
driver_remove_dir(drv);
if (drv->release)
drv->release(drv);
put_bus(drv->bus);
}
void remove_driver(struct device_driver * drv)
void driver_unregister(struct device_driver * drv)
{
spin_lock(&device_lock);
atomic_set(&drv->refcount,0);
list_del_init(&drv->bus_list);
spin_unlock(&device_lock);
__remove_driver(drv);
}
/**
* put_driver - decrement driver's refcount and clean up if necessary
* @drv: driver in question
*/
void put_driver(struct device_driver * drv)
{
if (!atomic_dec_and_lock(&drv->refcount,&device_lock))
return;
list_del_init(&drv->bus_list);
drv->present = 0;
spin_unlock(&device_lock);
__remove_driver(drv);
pr_debug("driver %s:%s: unregistering\n",drv->bus->name,drv->name);
put_driver(drv);
}
EXPORT_SYMBOL(driver_for_each_dev);
EXPORT_SYMBOL(driver_register);
EXPORT_SYMBOL(driver_unregister);
EXPORT_SYMBOL(get_driver);
EXPORT_SYMBOL(put_driver);
EXPORT_SYMBOL(remove_driver);
......@@ -509,11 +509,13 @@ static void put_mount(void)
DBG("driverfs: mount_count = %d\n",mount_count);
}
int __init init_driverfs_fs(void)
static int __init driverfs_init(void)
{
return register_filesystem(&driverfs_fs_type);
}
core_initcall(driverfs_init);
static struct dentry * get_dentry(struct dentry * parent, const char * name)
{
struct qstr qstr;
......
......@@ -54,8 +54,9 @@ struct device_class;
struct bus_type {
char * name;
rwlock_t lock;
struct rw_semaphore rwsem;
atomic_t refcount;
u32 present;
struct list_head node;
struct list_head devices;
......@@ -73,14 +74,9 @@ struct bus_type {
extern int bus_register(struct bus_type * bus);
extern void bus_unregister(struct bus_type * bus);
static inline struct bus_type * get_bus(struct bus_type * bus)
{
BUG_ON(!atomic_read(&bus->refcount));
atomic_inc(&bus->refcount);
return bus;
}
extern struct bus_type * get_bus(struct bus_type * bus);
extern void put_bus(struct bus_type * bus);
extern int bus_for_each_dev(struct bus_type * bus, void * data,
......@@ -114,6 +110,7 @@ struct device_driver {
rwlock_t lock;
atomic_t refcount;
u32 present;
struct list_head bus_list;
struct list_head class_list;
......@@ -131,16 +128,10 @@ struct device_driver {
};
extern int driver_register(struct device_driver * drv);
extern void driver_unregister(struct device_driver * drv);
static inline struct device_driver * get_driver(struct device_driver * drv)
{
BUG_ON(!atomic_read(&drv->refcount));
atomic_inc(&drv->refcount);
return drv;
}
extern struct device_driver * get_driver(struct device_driver * drv);
extern void put_driver(struct device_driver * drv);
extern void remove_driver(struct device_driver * drv);
......@@ -172,6 +163,9 @@ extern void driver_remove_file(struct device_driver *, struct driver_attribute *
*/
struct device_class {
char * name;
atomic_t refcount;
u32 present;
u32 devnum;
struct list_head node;
......@@ -189,6 +183,9 @@ struct device_class {
extern int devclass_register(struct device_class *);
extern void devclass_unregister(struct device_class *);
extern struct device_class * get_devclass(struct device_class *);
extern void put_devclass(struct device_class *);
struct devclass_attribute {
struct attribute attr;
......
......@@ -65,6 +65,4 @@ driverfs_create_symlink(struct driver_dir_entry * parent,
extern void
driverfs_remove_file(struct driver_dir_entry *, const char * name);
extern int init_driverfs_fs(void);
#endif /* _DDFS_H_ */
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