Commit 1498221d authored by Stephen Hemminger's avatar Stephen Hemminger Committed by David S. Miller

[CLASS DEVICE]: add attribute_group creation

Extend the support of attribute groups in class_device's to allow
groups to be created as part of the registration process. This allows
network device's to avoid race between registration and creating
groups.

Note that unlike attributes that are a property of the class object,
the groups are a property of the class_device object. This is done
because there are different types of network devices (wireless for
example).
Signed-off-by: default avatarStephen Hemminger <shemminger@osdl.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5528e568
...@@ -456,6 +456,35 @@ static void class_device_remove_attrs(struct class_device * cd) ...@@ -456,6 +456,35 @@ 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) static ssize_t show_dev(struct class_device *class_dev, char *buf)
{ {
return print_dev_t(buf, class_dev->devt); return print_dev_t(buf, class_dev->devt);
...@@ -559,6 +588,8 @@ int class_device_add(struct class_device *class_dev) ...@@ -559,6 +588,8 @@ int class_device_add(struct class_device *class_dev)
class_name); class_name);
} }
class_device_add_groups(class_dev);
kobject_uevent(&class_dev->kobj, KOBJ_ADD); kobject_uevent(&class_dev->kobj, KOBJ_ADD);
/* notify any interfaces this device is now here */ /* notify any interfaces this device is now here */
...@@ -672,6 +703,7 @@ void class_device_del(struct class_device *class_dev) ...@@ -672,6 +703,7 @@ void class_device_del(struct class_device *class_dev)
if (class_dev->devt_attr) if (class_dev->devt_attr)
class_device_remove_file(class_dev, class_dev->devt_attr); class_device_remove_file(class_dev, class_dev->devt_attr);
class_device_remove_attrs(class_dev); class_device_remove_attrs(class_dev);
class_device_remove_groups(class_dev);
kobject_uevent(&class_dev->kobj, KOBJ_REMOVE); kobject_uevent(&class_dev->kobj, KOBJ_REMOVE);
kobject_del(&class_dev->kobj); kobject_del(&class_dev->kobj);
......
...@@ -200,6 +200,7 @@ extern int class_device_create_file(struct class_device *, ...@@ -200,6 +200,7 @@ extern int class_device_create_file(struct class_device *,
* @node: for internal use by the driver core only. * @node: for internal use by the driver core only.
* @kobj: for internal use by the driver core only. * @kobj: for internal use by the driver core only.
* @devt_attr: for internal use by the driver core only. * @devt_attr: for internal use by the driver core only.
* @groups: optional additional groups to be created
* @dev: if set, a symlink to the struct device is created in the sysfs * @dev: if set, a symlink to the struct device is created in the sysfs
* directory for this struct class device. * directory for this struct class device.
* @class_data: pointer to whatever you want to store here for this struct * @class_data: pointer to whatever you want to store here for this struct
...@@ -228,6 +229,7 @@ struct class_device { ...@@ -228,6 +229,7 @@ struct class_device {
struct device * dev; /* not necessary, but nice to have */ struct device * dev; /* not necessary, but nice to have */
void * class_data; /* class-specific data */ void * class_data; /* class-specific data */
struct class_device *parent; /* parent of this child device, if there is one */ struct class_device *parent; /* parent of this child device, if there is one */
struct attribute_group ** groups; /* optional groups */
void (*release)(struct class_device *dev); void (*release)(struct class_device *dev);
int (*uevent)(struct class_device *dev, char **envp, int (*uevent)(struct class_device *dev, char **envp,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment