diff --git a/drivers/base/core.c b/drivers/base/core.c index 5d4b7e04471..641c0c42bb4 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -197,6 +197,35 @@ static ssize_t store_uevent(struct device *dev, struct device_attribute *attr, return count; } +static int device_add_groups(struct device *dev) +{ + int i; + int error = 0; + + if (dev->groups) { + for (i = 0; dev->groups[i]; i++) { + error = sysfs_create_group(&dev->kobj, dev->groups[i]); + if (error) { + while (--i >= 0) + sysfs_remove_group(&dev->kobj, dev->groups[i]); + goto out; + } + } + } +out: + return error; +} + +static void device_remove_groups(struct device *dev) +{ + int i; + if (dev->groups) { + for (i = 0; dev->groups[i]; i++) { + sysfs_remove_group(&dev->kobj, dev->groups[i]); + } + } +} + static ssize_t show_dev(struct device *dev, struct device_attribute *attr, char *buf) { @@ -350,6 +379,8 @@ int device_add(struct device *dev) sysfs_create_link(&dev->parent->kobj, &dev->kobj, class_name); } + if ((error = device_add_groups(dev))) + goto GroupError; if ((error = device_pm_add(dev))) goto PMError; if ((error = bus_add_device(dev))) @@ -376,6 +407,8 @@ int device_add(struct device *dev) BusError: device_pm_remove(dev); PMError: + device_remove_groups(dev); + GroupError: if (dev->devt_attr) { device_remove_file(dev, dev->devt_attr); kfree(dev->devt_attr); @@ -470,6 +503,7 @@ void device_del(struct device * dev) up(&dev->class->sem); } device_remove_file(dev, &dev->uevent_attr); + device_remove_groups(dev); /* Notify the platform of the removal, in case they * need to do anything... diff --git a/include/linux/device.h b/include/linux/device.h index b3646462d6d..994d3ebd53f 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -344,6 +344,7 @@ struct device { struct list_head node; struct class *class; /* optional*/ dev_t devt; /* dev_t, creates the sysfs "dev" */ + struct attribute_group **groups; /* optional groups */ void (*release)(struct device * dev); };