summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/base/class.c72
1 files changed, 54 insertions, 18 deletions
diff --git a/drivers/base/class.c b/drivers/base/class.c
index b1ea4df85c7d..48ad5df72812 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -535,18 +535,22 @@ int class_device_add(struct class_device *class_dev)
return -EINVAL;
if (!strlen(class_dev->class_id))
- goto register_done;
+ goto out1;
parent_class = class_get(class_dev->class);
if (!parent_class)
- goto register_done;
+ goto out1;
+
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. */
- kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id);
+ error = kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id);
+ if (error)
+ goto out2;
+
if (parent_class_dev)
class_dev->kobj.parent = &parent_class_dev->kobj;
else
@@ -554,41 +558,56 @@ int class_device_add(struct class_device *class_dev)
error = kobject_add(&class_dev->kobj);
if (error)
- goto register_done;
+ goto out2;
/* add the needed attributes to this device */
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;
- class_device_create_file(class_dev, &class_dev->uevent_attr);
+ error = class_device_create_file(class_dev, &class_dev->uevent_attr);
+ if (error)
+ goto out3;
if (MAJOR(class_dev->devt)) {
struct class_device_attribute *attr;
attr = kzalloc(sizeof(*attr), GFP_KERNEL);
if (!attr) {
error = -ENOMEM;
- kobject_del(&class_dev->kobj);
- goto register_done;
+ goto out4;
}
attr->attr.name = "dev";
attr->attr.mode = S_IRUGO;
attr->attr.owner = parent_class->owner;
attr->show = show_dev;
- class_device_create_file(class_dev, attr);
+ error = class_device_create_file(class_dev, attr);
+ if (error) {
+ kfree(attr);
+ goto out4;
+ }
+
class_dev->devt_attr = attr;
}
- class_device_add_attrs(class_dev);
+ error = class_device_add_attrs(class_dev);
+ if (error)
+ goto out5;
+
if (class_dev->dev) {
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 = 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_device_add_groups(class_dev);
+ error = class_device_add_groups(class_dev);
+ if (error)
+ goto out8;
kobject_uevent(&class_dev->kobj, KOBJ_ADD);
@@ -601,11 +620,28 @@ int class_device_add(struct class_device *class_dev)
}
up(&parent_class->sem);
- register_done:
- if (error) {
- class_put(parent_class);
+ 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)
class_device_put(parent_class_dev);
- }
+ class_put(parent_class);
+ out1:
class_device_put(class_dev);
kfree(class_name);
return error;
OpenPOWER on IntegriCloud