Commit 39ef3112 authored by Guenter Roeck's avatar Guenter Roeck Committed by Greg Kroah-Hartman

driver core: Introduce device_create_groups

device_create_groups lets callers create devices as well as associated
sysfs attributes with a single call. This avoids race conditions seen
if sysfs attributes on new devices are created later.

[fixed up comment block placement and add checks for printk buffer
formats - gregkh]
Signed-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
Cc: Jean Delvare <khali@linux-fr.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 388a8c35
...@@ -1667,34 +1667,11 @@ static void device_create_release(struct device *dev) ...@@ -1667,34 +1667,11 @@ static void device_create_release(struct device *dev)
kfree(dev); kfree(dev);
} }
/** static struct device *
* device_create_vargs - creates a device and registers it with sysfs device_create_groups_vargs(struct class *class, struct device *parent,
* @class: pointer to the struct class that this device should be registered to dev_t devt, void *drvdata,
* @parent: pointer to the parent struct device of this new device, if any const struct attribute_group **groups,
* @devt: the dev_t for the char device to be added const char *fmt, va_list args)
* @drvdata: the data to be added to the device for callbacks
* @fmt: string for the device's name
* @args: va_list for the device's name
*
* This function can be used by char device classes. A struct device
* will be created in sysfs, registered to the specified class.
*
* A "dev" file will be created, showing the dev_t for the device, if
* the dev_t is not 0,0.
* If a pointer to a parent struct device is passed in, the newly created
* struct device will be a child of that device in sysfs.
* The pointer to the struct device will be returned from the call.
* Any further sysfs files that might be required can be created using this
* pointer.
*
* Returns &struct device pointer on success, or ERR_PTR() on error.
*
* Note: the struct class passed to this function must have previously
* been created with a call to class_create().
*/
struct device *device_create_vargs(struct class *class, struct device *parent,
dev_t devt, void *drvdata, const char *fmt,
va_list args)
{ {
struct device *dev = NULL; struct device *dev = NULL;
int retval = -ENODEV; int retval = -ENODEV;
...@@ -1711,6 +1688,7 @@ struct device *device_create_vargs(struct class *class, struct device *parent, ...@@ -1711,6 +1688,7 @@ struct device *device_create_vargs(struct class *class, struct device *parent,
dev->devt = devt; dev->devt = devt;
dev->class = class; dev->class = class;
dev->parent = parent; dev->parent = parent;
dev->groups = groups;
dev->release = device_create_release; dev->release = device_create_release;
dev_set_drvdata(dev, drvdata); dev_set_drvdata(dev, drvdata);
...@@ -1728,6 +1706,39 @@ struct device *device_create_vargs(struct class *class, struct device *parent, ...@@ -1728,6 +1706,39 @@ struct device *device_create_vargs(struct class *class, struct device *parent,
put_device(dev); put_device(dev);
return ERR_PTR(retval); return ERR_PTR(retval);
} }
/**
* device_create_vargs - creates a device and registers it with sysfs
* @class: pointer to the struct class that this device should be registered to
* @parent: pointer to the parent struct device of this new device, if any
* @devt: the dev_t for the char device to be added
* @drvdata: the data to be added to the device for callbacks
* @fmt: string for the device's name
* @args: va_list for the device's name
*
* This function can be used by char device classes. A struct device
* will be created in sysfs, registered to the specified class.
*
* A "dev" file will be created, showing the dev_t for the device, if
* the dev_t is not 0,0.
* If a pointer to a parent struct device is passed in, the newly created
* struct device will be a child of that device in sysfs.
* The pointer to the struct device will be returned from the call.
* Any further sysfs files that might be required can be created using this
* pointer.
*
* Returns &struct device pointer on success, or ERR_PTR() on error.
*
* Note: the struct class passed to this function must have previously
* been created with a call to class_create().
*/
struct device *device_create_vargs(struct class *class, struct device *parent,
dev_t devt, void *drvdata, const char *fmt,
va_list args)
{
return device_create_groups_vargs(class, parent, devt, drvdata, NULL,
fmt, args);
}
EXPORT_SYMBOL_GPL(device_create_vargs); EXPORT_SYMBOL_GPL(device_create_vargs);
/** /**
...@@ -1767,6 +1778,50 @@ struct device *device_create(struct class *class, struct device *parent, ...@@ -1767,6 +1778,50 @@ struct device *device_create(struct class *class, struct device *parent,
} }
EXPORT_SYMBOL_GPL(device_create); EXPORT_SYMBOL_GPL(device_create);
/**
* device_create_with_groups - creates a device and registers it with sysfs
* @class: pointer to the struct class that this device should be registered to
* @parent: pointer to the parent struct device of this new device, if any
* @devt: the dev_t for the char device to be added
* @drvdata: the data to be added to the device for callbacks
* @groups: NULL-terminated list of attribute groups to be created
* @fmt: string for the device's name
*
* This function can be used by char device classes. A struct device
* will be created in sysfs, registered to the specified class.
* Additional attributes specified in the groups parameter will also
* be created automatically.
*
* A "dev" file will be created, showing the dev_t for the device, if
* the dev_t is not 0,0.
* If a pointer to a parent struct device is passed in, the newly created
* struct device will be a child of that device in sysfs.
* The pointer to the struct device will be returned from the call.
* Any further sysfs files that might be required can be created using this
* pointer.
*
* Returns &struct device pointer on success, or ERR_PTR() on error.
*
* Note: the struct class passed to this function must have previously
* been created with a call to class_create().
*/
struct device *device_create_with_groups(struct class *class,
struct device *parent, dev_t devt,
void *drvdata,
const struct attribute_group **groups,
const char *fmt, ...)
{
va_list vargs;
struct device *dev;
va_start(vargs, fmt);
dev = device_create_groups_vargs(class, parent, devt, drvdata, groups,
fmt, vargs);
va_end(vargs);
return dev;
}
EXPORT_SYMBOL_GPL(device_create_with_groups);
static int __match_devt(struct device *dev, const void *data) static int __match_devt(struct device *dev, const void *data)
{ {
const dev_t *devt = data; const dev_t *devt = data;
......
...@@ -938,6 +938,11 @@ extern __printf(5, 6) ...@@ -938,6 +938,11 @@ extern __printf(5, 6)
struct device *device_create(struct class *cls, struct device *parent, struct device *device_create(struct class *cls, struct device *parent,
dev_t devt, void *drvdata, dev_t devt, void *drvdata,
const char *fmt, ...); const char *fmt, ...);
extern __printf(6, 7)
struct device *device_create_with_groups(struct class *cls,
struct device *parent, dev_t devt, void *drvdata,
const struct attribute_group **groups,
const char *fmt, ...);
extern void device_destroy(struct class *cls, dev_t devt); extern void device_destroy(struct class *cls, dev_t devt);
/* /*
......
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