Commit 1067efac authored by Patrick Mochel's avatar Patrick Mochel

driver model: change class reference counting to be like devices'.

device classes join the club of devices, buses, and drivers. They get a 
->present flag, which is set on registration and cleared on unregistration.
They also get get_devclass() and put_devclass(), which, you guessed it, 
bump the reference count. get_...() of course checks the present flag and
returns NULL if clear. 
parent 2884fae0
...@@ -81,29 +81,55 @@ void devclass_remove_device(struct device * dev) ...@@ -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) int devclass_register(struct device_class * cls)
{ {
INIT_LIST_HEAD(&cls->drivers); INIT_LIST_HEAD(&cls->drivers);
INIT_LIST_HEAD(&cls->intf_list); INIT_LIST_HEAD(&cls->intf_list);
atomic_set(&cls->refcount,2);
pr_debug("registering device class '%s'\n",cls->name); cls->present = 1;
pr_debug("device class '%s': registering\n",cls->name);
spin_lock(&device_lock); spin_lock(&device_lock);
list_add_tail(&cls->node,&class_list); list_add_tail(&cls->node,&class_list);
spin_unlock(&device_lock); spin_unlock(&device_lock);
devclass_make_dir(cls); devclass_make_dir(cls);
put_devclass(cls);
return 0; return 0;
} }
void devclass_unregister(struct device_class * cls) void devclass_unregister(struct device_class * cls)
{ {
pr_debug("unregistering device class '%s'\n",cls->name);
devclass_remove_dir(cls);
spin_lock(&device_lock); spin_lock(&device_lock);
list_del_init(&class_list); cls->present = 0;
spin_unlock(&device_lock); spin_unlock(&device_lock);
pr_debug("device class '%s': unregistering\n",cls->name);
put_devclass(cls);
} }
EXPORT_SYMBOL(devclass_register); EXPORT_SYMBOL(devclass_register);
EXPORT_SYMBOL(devclass_unregister); EXPORT_SYMBOL(devclass_unregister);
EXPORT_SYMBOL(get_devclass);
EXPORT_SYMBOL(put_devclass);
...@@ -163,6 +163,9 @@ extern void driver_remove_file(struct device_driver *, struct driver_attribute * ...@@ -163,6 +163,9 @@ extern void driver_remove_file(struct device_driver *, struct driver_attribute *
*/ */
struct device_class { struct device_class {
char * name; char * name;
atomic_t refcount;
u32 present;
u32 devnum; u32 devnum;
struct list_head node; struct list_head node;
...@@ -180,6 +183,9 @@ struct device_class { ...@@ -180,6 +183,9 @@ struct device_class {
extern int devclass_register(struct device_class *); extern int devclass_register(struct device_class *);
extern void devclass_unregister(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 devclass_attribute {
struct attribute attr; struct attribute attr;
......
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