[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: Stephen Hemminger <shemminger@osdl.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
5528e568a7
commit
1498221d51
|
@ -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)
|
||||||
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)
|
||||||
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 *,
|
||||||
* @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 {
|
||||||
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,
|
||||||
|
|
Loading…
Reference in New Issue