linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / drivers / base / class.c
index de89083..df7fdab 100644 (file)
@@ -10,6 +10,7 @@
  *
  */
 
+#include <linux/config.h>
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -90,14 +91,14 @@ void class_remove_file(struct class * cls, const struct class_attribute * attr)
                sysfs_remove_file(&cls->subsys.kset.kobj, &attr->attr);
 }
 
-static struct class *class_get(struct class *cls)
+struct class * class_get(struct class * cls)
 {
        if (cls)
                return container_of(subsys_get(&cls->subsys), struct class, subsys);
        return NULL;
 }
 
-static void class_put(struct class * cls)
+void class_put(struct class * cls)
 {
        if (cls)
                subsys_put(&cls->subsys);
@@ -141,7 +142,6 @@ int class_register(struct class * cls)
        pr_debug("device class '%s': registering\n", cls->name);
 
        INIT_LIST_HEAD(&cls->children);
-       INIT_LIST_HEAD(&cls->devices);
        INIT_LIST_HEAD(&cls->interfaces);
        init_MUTEX(&cls->sem);
        error = kobject_set_name(&cls->subsys.kset.kobj, "%s", cls->name);
@@ -456,35 +456,6 @@ static void class_device_remove_attrs(struct class_device * cd)
        }
 }
 
-static int class_device_add_groups(struct class_device * cd)
-{
-       int i;
-       int error = 0;
-
-       if (cd->groups) {
-               for (i = 0; cd->groups[i]; i++) {
-                       error = sysfs_create_group(&cd->kobj, cd->groups[i]);
-                       if (error) {
-                               while (--i >= 0)
-                                       sysfs_remove_group(&cd->kobj, cd->groups[i]);
-                               goto out;
-                       }
-               }
-       }
-out:
-       return error;
-}
-
-static void class_device_remove_groups(struct class_device * cd)
-{
-       int i;
-       if (cd->groups) {
-               for (i = 0; cd->groups[i]; i++) {
-                       sysfs_remove_group(&cd->kobj, cd->groups[i]);
-               }
-       }
-}
-
 static ssize_t show_dev(struct class_device *class_dev, char *buf)
 {
        return print_dev_t(buf, class_dev->devt);
@@ -504,21 +475,22 @@ void class_device_initialize(struct class_device *class_dev)
        INIT_LIST_HEAD(&class_dev->node);
 }
 
-char *make_class_name(const char *name, struct kobject *kobj)
+static char *make_class_name(struct class_device *class_dev)
 {
-       char *class_name;
+       char *name;
        int size;
 
-       size = strlen(name) + strlen(kobject_name(kobj)) + 2;
+       size = strlen(class_dev->class->name) +
+               strlen(kobject_name(&class_dev->kobj)) + 2;
 
-       class_name = kmalloc(size, GFP_KERNEL);
-       if (!class_name)
+       name = kmalloc(size, GFP_KERNEL);
+       if (!name)
                return ERR_PTR(-ENOMEM);
 
-       strcpy(class_name, name);
-       strcat(class_name, ":");
-       strcat(class_name, kobject_name(kobj));
-       return class_name;
+       strcpy(name, class_dev->class->name);
+       strcat(name, ":");
+       strcat(name, kobject_name(&class_dev->kobj));
+       return name;
 }
 
 int class_device_add(struct class_device *class_dev)
@@ -534,22 +506,18 @@ int class_device_add(struct class_device *class_dev)
                return -EINVAL;
 
        if (!strlen(class_dev->class_id))
-               goto out1;
+               goto register_done;
 
        parent_class = class_get(class_dev->class);
        if (!parent_class)
-               goto out1;
-
+               goto register_done;
        parent_class_dev = class_device_get(class_dev->parent);
 
        pr_debug("CLASS: registering class device: ID = '%s'\n",
                 class_dev->class_id);
 
        /* first, register with generic layer. */
-       error = kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id);
-       if (error)
-               goto out2;
-
+       kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id);
        if (parent_class_dev)
                class_dev->kobj.parent = &parent_class_dev->kobj;
        else
@@ -557,92 +525,57 @@ int class_device_add(struct class_device *class_dev)
 
        error = kobject_add(&class_dev->kobj);
        if (error)
-               goto out2;
+               goto register_done;
 
        /* add the needed attributes to this device */
-       sysfs_create_link(&class_dev->kobj, &parent_class->subsys.kset.kobj, "subsystem");
        class_dev->uevent_attr.attr.name = "uevent";
        class_dev->uevent_attr.attr.mode = S_IWUSR;
        class_dev->uevent_attr.attr.owner = parent_class->owner;
        class_dev->uevent_attr.store = store_uevent;
-       error = class_device_create_file(class_dev, &class_dev->uevent_attr);
-       if (error)
-               goto out3;
+       class_device_create_file(class_dev, &class_dev->uevent_attr);
 
        if (MAJOR(class_dev->devt)) {
                struct class_device_attribute *attr;
                attr = kzalloc(sizeof(*attr), GFP_KERNEL);
                if (!attr) {
                        error = -ENOMEM;
-                       goto out4;
+                       kobject_del(&class_dev->kobj);
+                       goto register_done;
                }
                attr->attr.name = "dev";
                attr->attr.mode = S_IRUGO;
                attr->attr.owner = parent_class->owner;
                attr->show = show_dev;
-               error = class_device_create_file(class_dev, attr);
-               if (error) {
-                       kfree(attr);
-                       goto out4;
-               }
-
+               class_device_create_file(class_dev, attr);
                class_dev->devt_attr = attr;
        }
 
-       error = class_device_add_attrs(class_dev);
-       if (error)
-               goto out5;
-
+       class_device_add_attrs(class_dev);
        if (class_dev->dev) {
-               class_name = make_class_name(class_dev->class->name,
-                                            &class_dev->kobj);
-               error = sysfs_create_link(&class_dev->kobj,
-                                         &class_dev->dev->kobj, "device");
-               if (error)
-                       goto out6;
-               error = sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj,
-                                         class_name);
-               if (error)
-                       goto out7;
+               class_name = make_class_name(class_dev);
+               sysfs_create_link(&class_dev->kobj,
+                                 &class_dev->dev->kobj, "device");
+               sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj,
+                                 class_name);
        }
 
-       error = class_device_add_groups(class_dev);
-       if (error)
-               goto out8;
-
        kobject_uevent(&class_dev->kobj, KOBJ_ADD);
 
        /* notify any interfaces this device is now here */
-       down(&parent_class->sem);
-       list_add_tail(&class_dev->node, &parent_class->children);
-       list_for_each_entry(class_intf, &parent_class->interfaces, node) {
-               if (class_intf->add)
-                       class_intf->add(class_dev, class_intf);
+       if (parent_class) {
+               down(&parent_class->sem);
+               list_add_tail(&class_dev->node, &parent_class->children);
+               list_for_each_entry(class_intf, &parent_class->interfaces, node)
+                       if (class_intf->add)
+                               class_intf->add(class_dev, class_intf);
+               up(&parent_class->sem);
        }
-       up(&parent_class->sem);
-
-       goto out1;
 
- out8:
-       if (class_dev->dev)
-               sysfs_remove_link(&class_dev->kobj, class_name);
- out7:
-       if (class_dev->dev)
-               sysfs_remove_link(&class_dev->kobj, "device");
- out6:
-       class_device_remove_attrs(class_dev);
- out5:
-       if (class_dev->devt_attr)
-               class_device_remove_file(class_dev, class_dev->devt_attr);
- out4:
-       class_device_remove_file(class_dev, &class_dev->uevent_attr);
- out3:
-       kobject_del(&class_dev->kobj);
- out2:
-       if(parent_class_dev)
+ register_done:
+       if (error) {
+               class_put(parent_class);
                class_device_put(parent_class_dev);
-       class_put(parent_class);
- out1:
+       }
        class_device_put(class_dev);
        kfree(class_name);
        return error;
@@ -732,17 +665,14 @@ void class_device_del(struct class_device *class_dev)
        }
 
        if (class_dev->dev) {
-               class_name = make_class_name(class_dev->class->name,
-                                            &class_dev->kobj);
+               class_name = make_class_name(class_dev);
                sysfs_remove_link(&class_dev->kobj, "device");
                sysfs_remove_link(&class_dev->dev->kobj, class_name);
        }
-       sysfs_remove_link(&class_dev->kobj, "subsystem");
        class_device_remove_file(class_dev, &class_dev->uevent_attr);
        if (class_dev->devt_attr)
                class_device_remove_file(class_dev, class_dev->devt_attr);
        class_device_remove_attrs(class_dev);
-       class_device_remove_groups(class_dev);
 
        kobject_uevent(&class_dev->kobj, KOBJ_REMOVE);
        kobject_del(&class_dev->kobj);
@@ -799,16 +729,14 @@ int class_device_rename(struct class_device *class_dev, char *new_name)
                 new_name);
 
        if (class_dev->dev)
-               old_class_name = make_class_name(class_dev->class->name,
-                                                &class_dev->kobj);
+               old_class_name = make_class_name(class_dev);
 
        strlcpy(class_dev->class_id, new_name, KOBJ_NAME_LEN);
 
        error = kobject_rename(&class_dev->kobj, new_name);
 
        if (class_dev->dev) {
-               new_class_name = make_class_name(class_dev->class->name,
-                                                &class_dev->kobj);
+               new_class_name = make_class_name(class_dev);
                sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj,
                                  new_class_name);
                sysfs_remove_link(&class_dev->dev->kobj, old_class_name);
@@ -899,6 +827,8 @@ EXPORT_SYMBOL_GPL(class_create_file);
 EXPORT_SYMBOL_GPL(class_remove_file);
 EXPORT_SYMBOL_GPL(class_register);
 EXPORT_SYMBOL_GPL(class_unregister);
+EXPORT_SYMBOL_GPL(class_get);
+EXPORT_SYMBOL_GPL(class_put);
 EXPORT_SYMBOL_GPL(class_create);
 EXPORT_SYMBOL_GPL(class_destroy);