X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fbase%2Fclass.c;h=2693bb5455f4fe08666a48a3d2ba0a65bbd5999e;hb=9bf4aaab3e101692164d49b7ca357651eb691cb6;hp=ed13d9de0d1d3795407f11edddd79fbebb4e3439;hpb=db216c3d5e4c040e557a50f8f5d35d5c415e8c1c;p=linux-2.6.git diff --git a/drivers/base/class.c b/drivers/base/class.c index ed13d9de0..2693bb545 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -5,7 +5,7 @@ * Copyright (c) 2002-3 Open Source Development Labs * Copyright (c) 2003-2004 Greg Kroah-Hartman * Copyright (c) 2003-2004 IBM Corp. - * + * * This file is released under the GPLv2 * */ @@ -17,8 +17,8 @@ #include #include "base.h" -#define to_class_attr(_attr) container_of(_attr,struct class_attribute,attr) -#define to_class(obj) container_of(obj,struct class,subsys.kset.kobj) +#define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr) +#define to_class(obj) container_of(obj, struct class, subsys.kset.kobj) static ssize_t class_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) @@ -28,12 +28,12 @@ class_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) ssize_t ret = 0; if (class_attr->show) - ret = class_attr->show(dc,buf); + ret = class_attr->show(dc, buf); return ret; } static ssize_t -class_attr_store(struct kobject * kobj, struct attribute * attr, +class_attr_store(struct kobject * kobj, struct attribute * attr, const char * buf, size_t count) { struct class_attribute * class_attr = to_class_attr(attr); @@ -41,7 +41,7 @@ class_attr_store(struct kobject * kobj, struct attribute * attr, ssize_t ret = 0; if (class_attr->store) - ret = class_attr->store(dc,buf,count); + ret = class_attr->store(dc, buf, count); return ret; } @@ -69,14 +69,14 @@ static struct kobj_type ktype_class = { }; /* Hotplug events for classes go to the class_obj subsys */ -static decl_subsys(class,&ktype_class,NULL); +static decl_subsys(class, &ktype_class, NULL); int class_create_file(struct class * cls, const struct class_attribute * attr) { int error; if (cls) { - error = sysfs_create_file(&cls->subsys.kset.kobj,&attr->attr); + error = sysfs_create_file(&cls->subsys.kset.kobj, &attr->attr); } else error = -EINVAL; return error; @@ -85,13 +85,13 @@ int class_create_file(struct class * cls, const struct class_attribute * attr) void class_remove_file(struct class * cls, const struct class_attribute * attr) { if (cls) - sysfs_remove_file(&cls->subsys.kset.kobj,&attr->attr); + sysfs_remove_file(&cls->subsys.kset.kobj, &attr->attr); } struct class * class_get(struct class * cls) { if (cls) - return container_of(subsys_get(&cls->subsys),struct class,subsys); + return container_of(subsys_get(&cls->subsys), struct class, subsys); return NULL; } @@ -100,33 +100,67 @@ void class_put(struct class * cls) subsys_put(&cls->subsys); } + +static int add_class_attrs(struct class * cls) +{ + int i; + int error = 0; + + if (cls->class_attrs) { + for (i = 0; attr_name(cls->class_attrs[i]); i++) { + error = class_create_file(cls,&cls->class_attrs[i]); + if (error) + goto Err; + } + } + Done: + return error; + Err: + while (--i >= 0) + class_remove_file(cls,&cls->class_attrs[i]); + goto Done; +} + +static void remove_class_attrs(struct class * cls) +{ + int i; + + if (cls->class_attrs) { + for (i = 0; attr_name(cls->class_attrs[i]); i++) + class_remove_file(cls,&cls->class_attrs[i]); + } +} + int class_register(struct class * cls) { int error; - pr_debug("device class '%s': registering\n",cls->name); + pr_debug("device class '%s': registering\n", cls->name); INIT_LIST_HEAD(&cls->children); INIT_LIST_HEAD(&cls->interfaces); - error = kobject_set_name(&cls->subsys.kset.kobj,cls->name); + error = kobject_set_name(&cls->subsys.kset.kobj, cls->name); if (error) return error; - subsys_set_kset(cls,class_subsys); + subsys_set_kset(cls, class_subsys); error = subsystem_register(&cls->subsys); - if (error) - return error; - - return 0; + if (!error) { + error = add_class_attrs(class_get(cls)); + class_put(cls); + } + return error; } void class_unregister(struct class * cls) { - pr_debug("device class '%s': unregistering\n",cls->name); + pr_debug("device class '%s': unregistering\n", cls->name); + remove_class_attrs(cls); subsystem_unregister(&cls->subsys); } + /* Class Device Stuff */ int class_device_create_file(struct class_device * class_dev, @@ -181,12 +215,12 @@ class_device_attr_show(struct kobject * kobj, struct attribute * attr, ssize_t ret = 0; if (class_dev_attr->show) - ret = class_dev_attr->show(cd,buf); + ret = class_dev_attr->show(cd, buf); return ret; } static ssize_t -class_device_attr_store(struct kobject * kobj, struct attribute * attr, +class_device_attr_store(struct kobject * kobj, struct attribute * attr, const char * buf, size_t count) { struct class_device_attribute * class_dev_attr = to_class_dev_attr(attr); @@ -194,7 +228,7 @@ class_device_attr_store(struct kobject * kobj, struct attribute * attr, ssize_t ret = 0; if (class_dev_attr->store) - ret = class_dev_attr->store(cd,buf,count); + ret = class_dev_attr->store(cd, buf, count); return ret; } @@ -208,7 +242,7 @@ static void class_dev_release(struct kobject * kobj) struct class_device *cd = to_class_dev(kobj); struct class * cls = cd->class; - pr_debug("device class '%s': release.\n",cd->class_id); + pr_debug("device class '%s': release.\n", cd->class_id); if (cls->release) cls->release(cd); @@ -272,6 +306,40 @@ static struct kset_hotplug_ops class_hotplug_ops = { static decl_subsys(class_obj, &ktype_class_device, &class_hotplug_ops); + +static int class_device_add_attrs(struct class_device * cd) +{ + int i; + int error = 0; + struct class * cls = cd->class; + + if (cls->class_dev_attrs) { + for (i = 0; attr_name(cls->class_dev_attrs[i]); i++) { + error = class_device_create_file(cd, + &cls->class_dev_attrs[i]); + if (error) + goto Err; + } + } + Done: + return error; + Err: + while (--i >= 0) + class_device_remove_file(cd,&cls->class_dev_attrs[i]); + goto Done; +} + +static void class_device_remove_attrs(struct class_device * cd) +{ + int i; + struct class * cls = cd->class; + + if (cls->class_dev_attrs) { + for (i = 0; attr_name(cls->class_dev_attrs[i]); i++) + class_device_remove_file(cd,&cls->class_dev_attrs[i]); + } +} + void class_device_initialize(struct class_device *class_dev) { kobj_set_kset_s(class_dev, class_obj_subsys); @@ -311,7 +379,7 @@ int class_device_add(struct class_device *class_dev) class_intf->add(class_dev); up_write(&parent->subsys.rwsem); } - + class_device_add_attrs(class_dev); class_device_dev_link(class_dev); class_device_driver_link(class_dev); @@ -344,7 +412,8 @@ void class_device_del(struct class_device *class_dev) class_device_dev_unlink(class_dev); class_device_driver_unlink(class_dev); - + class_device_remove_attrs(class_dev); + kobject_del(&class_dev->kobj); if (parent)