* class.c - basic device class management
*/
+#undef DEBUG
+
#include <linux/device.h>
#include <linux/module.h>
#include <linux/init.h>
{
struct device_class * cls = get_devclass(drv->devclass);
if (cls) {
- down_write(&cls->rwsem);
+ down_write(&cls->subsys.rwsem);
pr_debug("device class %s: adding driver %s:%s\n",
cls->name,drv->bus->name,drv->name);
list_add_tail(&drv->class_list,&cls->drivers);
devclass_drv_link(drv);
- up_write(&cls->rwsem);
+ up_write(&cls->subsys.rwsem);
}
return 0;
}
{
struct device_class * cls = drv->devclass;
if (cls) {
- down_write(&cls->rwsem);
+ down_write(&cls->subsys.rwsem);
pr_debug("device class %s: removing driver %s:%s\n",
cls->name,drv->bus->name,drv->name);
list_del_init(&drv->class_list);
devclass_drv_unlink(drv);
- up_write(&cls->rwsem);
+ up_write(&cls->subsys.rwsem);
put_devclass(cls);
}
}
if (dev->driver) {
cls = get_devclass(dev->driver->devclass);
if (cls) {
- down_write(&cls->rwsem);
+ down_write(&cls->subsys.rwsem);
pr_debug("device class %s: adding device %s\n",
cls->name,dev->name);
if (cls->add_device)
/* notify userspace (call /sbin/hotplug) */
class_hotplug (dev, "add");
- up_write(&cls->rwsem);
+ up_write(&cls->subsys.rwsem);
if (error)
put_devclass(cls);
}
if (dev->driver) {
cls = dev->driver->devclass;
if (cls) {
- down_write(&cls->rwsem);
+ down_write(&cls->subsys.rwsem);
pr_debug("device class %s: removing device %s\n",
cls->name,dev->name);
interface_remove(cls,dev);
if (cls->remove_device)
cls->remove_device(dev);
- up_write(&cls->rwsem);
+ up_write(&cls->subsys.rwsem);
put_devclass(cls);
}
}
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;
+ return cls ? container_of(subsys_get(&cls->subsys),struct device_class,subsys) : NULL;
}
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);
- }
+ subsys_put(&cls->subsys);
}
int devclass_register(struct device_class * cls)
{
INIT_LIST_HEAD(&cls->drivers);
- INIT_LIST_HEAD(&cls->intf_list);
- init_rwsem(&cls->rwsem);
- atomic_set(&cls->refcount,2);
- cls->present = 1;
- pr_debug("device class '%s': registering\n",cls->name);
+ pr_debug("device class '%s': registering\n",cls->name);
strncpy(cls->subsys.kobj.name,cls->name,KOBJ_NAME_LEN);
cls->subsys.parent = &class_subsys;
subsystem_register(&cls->subsys);
cls->drvsubsys.parent = &cls->subsys;
subsystem_register(&cls->drvsubsys);
- spin_lock(&device_lock);
- list_add_tail(&cls->node,&class_list);
- spin_unlock(&device_lock);
- put_devclass(cls);
return 0;
}
void devclass_unregister(struct device_class * cls)
{
- spin_lock(&device_lock);
- cls->present = 0;
- spin_unlock(&device_lock);
pr_debug("device class '%s': unregistering\n",cls->name);
subsystem_unregister(&cls->drvsubsys);
subsystem_unregister(&cls->devsubsys);
subsystem_unregister(&cls->subsys);
- put_devclass(cls);
}
static int __init class_subsys_init(void)
core_initcall(class_subsys_init);
+EXPORT_SYMBOL(devclass_create_file);
+EXPORT_SYMBOL(devclass_remove_file);
EXPORT_SYMBOL(devclass_register);
EXPORT_SYMBOL(devclass_unregister);
EXPORT_SYMBOL(get_devclass);
#include "base.h"
-#define to_intf(node) container_of(node,struct device_interface,node)
+#define to_intf(node) container_of(node,struct device_interface,kobj.entry)
/**
* intf_dev_link - symlink from interface's directory to device's directory
int interface_register(struct device_interface * intf)
{
- struct device_class * cls = intf->devclass;
+ struct device_class * cls = get_devclass(intf->devclass);
+ int error = 0;
if (cls) {
pr_debug("register interface '%s' with class '%s'\n",
intf->name,cls->name);
- kobject_init(&intf->kobj);
strncpy(intf->kobj.name,intf->name,KOBJ_NAME_LEN);
intf->kobj.subsys = &cls->subsys;
kobject_register(&intf->kobj);
-
- spin_lock(&device_lock);
- list_add_tail(&intf->node,&cls->intf_list);
- spin_unlock(&device_lock);
- return 0;
- }
- return -EINVAL;
+ } else
+ error = -EINVAL;
+ return error;
}
void interface_unregister(struct device_interface * intf)
pr_debug("unregistering interface '%s' from class '%s'\n",
intf->name,intf->devclass->name);
kobject_unregister(&intf->kobj);
- spin_lock(&device_lock);
- list_del_init(&intf->node);
- spin_unlock(&device_lock);
}
int interface_add(struct device_class * cls, struct device * dev)
pr_debug("adding '%s' to %s class interfaces\n",dev->name,cls->name);
- list_for_each(node,&cls->intf_list) {
+ list_for_each(node,&cls->subsys.list) {
struct device_interface * intf = to_intf(node);
if (intf->add_device) {
error = intf->add_device(dev);
pr_debug("remove '%s' from %s class interfaces: ",dev->name,cls->name);
- spin_lock(&device_lock);
list_for_each_safe(node,next,&dev->intf_list) {
struct intf_data * intf_data = container_of(node,struct intf_data,node);
list_del_init(&intf_data->node);
- spin_unlock(&device_lock);
intf_dev_unlink(intf_data);
pr_debug("%s ",intf_data->intf->name);
if (intf_data->intf->remove_device)
intf_data->intf->remove_device(intf_data);
-
- spin_lock(&device_lock);
}
- spin_unlock(&device_lock);
pr_debug("\n");
}
int interface_add_data(struct intf_data * data)
{
- spin_lock(&device_lock);
+ down_write(&data->intf->devclass->subsys.rwsem);
list_add_tail(&data->node,&data->dev->intf_list);
- data->intf_num = ++data->intf->devnum;
- spin_unlock(&device_lock);
+ data->intf_num = data->intf->devnum++;
intf_dev_link(data);
+ up_write(&data->intf->devclass->subsys.rwsem);
return 0;
}