mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-03-30 19:07:15 +00:00
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: Guenter Roeck <linux@roeck-us.net> Cc: Jean Delvare <khali@linux-fr.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
388a8c353d
commit
39ef311204
2 changed files with 91 additions and 31 deletions
|
@ -1667,6 +1667,46 @@ static void device_create_release(struct device *dev)
|
||||||
kfree(dev);
|
kfree(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct device *
|
||||||
|
device_create_groups_vargs(struct class *class, struct device *parent,
|
||||||
|
dev_t devt, void *drvdata,
|
||||||
|
const struct attribute_group **groups,
|
||||||
|
const char *fmt, va_list args)
|
||||||
|
{
|
||||||
|
struct device *dev = NULL;
|
||||||
|
int retval = -ENODEV;
|
||||||
|
|
||||||
|
if (class == NULL || IS_ERR(class))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
||||||
|
if (!dev) {
|
||||||
|
retval = -ENOMEM;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->devt = devt;
|
||||||
|
dev->class = class;
|
||||||
|
dev->parent = parent;
|
||||||
|
dev->groups = groups;
|
||||||
|
dev->release = device_create_release;
|
||||||
|
dev_set_drvdata(dev, drvdata);
|
||||||
|
|
||||||
|
retval = kobject_set_name_vargs(&dev->kobj, fmt, args);
|
||||||
|
if (retval)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
retval = device_register(dev);
|
||||||
|
if (retval)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
return dev;
|
||||||
|
|
||||||
|
error:
|
||||||
|
put_device(dev);
|
||||||
|
return ERR_PTR(retval);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* device_create_vargs - creates a device and registers it with sysfs
|
* device_create_vargs - creates a device and registers it with sysfs
|
||||||
* @class: pointer to the struct class that this device should be registered to
|
* @class: pointer to the struct class that this device should be registered to
|
||||||
|
@ -1696,37 +1736,8 @@ struct device *device_create_vargs(struct class *class, struct device *parent,
|
||||||
dev_t devt, void *drvdata, const char *fmt,
|
dev_t devt, void *drvdata, const char *fmt,
|
||||||
va_list args)
|
va_list args)
|
||||||
{
|
{
|
||||||
struct device *dev = NULL;
|
return device_create_groups_vargs(class, parent, devt, drvdata, NULL,
|
||||||
int retval = -ENODEV;
|
fmt, args);
|
||||||
|
|
||||||
if (class == NULL || IS_ERR(class))
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
|
||||||
if (!dev) {
|
|
||||||
retval = -ENOMEM;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev->devt = devt;
|
|
||||||
dev->class = class;
|
|
||||||
dev->parent = parent;
|
|
||||||
dev->release = device_create_release;
|
|
||||||
dev_set_drvdata(dev, drvdata);
|
|
||||||
|
|
||||||
retval = kobject_set_name_vargs(&dev->kobj, fmt, args);
|
|
||||||
if (retval)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
retval = device_register(dev);
|
|
||||||
if (retval)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
return dev;
|
|
||||||
|
|
||||||
error:
|
|
||||||
put_device(dev);
|
|
||||||
return ERR_PTR(retval);
|
|
||||||
}
|
}
|
||||||
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,
|
||||||
}
|
}
|
||||||
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)
|
||||||
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);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Add table
Reference in a new issue