Driver core: add device_create_vargs and device_create_drvdata
We want to have the drvdata field set properly when creating the device as sysfs callbacks can assume it is present and it can race the later setting of this field. So, create two new functions, deviec_create_vargs() and device_create_drvdata() that take this new field. device_create_drvdata() will go away in 2.6.27 as the drvdata field will just be moved to the device_create() call as it should be. Cc: Kay Sievers <kay.sievers@vrfy.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
c110a2bd82
commit
8882b39421
@ -1083,6 +1083,102 @@ static void device_create_release(struct device *dev)
|
||||
kfree(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* 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;
|
||||
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->release = device_create_release;
|
||||
dev_set_drvdata(dev, drvdata);
|
||||
|
||||
vsnprintf(dev->bus_id, BUS_ID_SIZE, fmt, args);
|
||||
retval = device_register(dev);
|
||||
if (retval)
|
||||
goto error;
|
||||
|
||||
return dev;
|
||||
|
||||
error:
|
||||
kfree(dev);
|
||||
return ERR_PTR(retval);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_create_vargs);
|
||||
|
||||
/**
|
||||
* device_create_drvdata - 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
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Note: the struct class passed to this function must have previously
|
||||
* been created with a call to class_create().
|
||||
*/
|
||||
struct device *device_create_drvdata(struct class *class,
|
||||
struct device *parent,
|
||||
dev_t devt,
|
||||
void *drvdata,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
va_list vargs;
|
||||
struct device *dev;
|
||||
|
||||
va_start(vargs, fmt);
|
||||
dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs);
|
||||
va_end(vargs);
|
||||
return dev;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_create_drvdata);
|
||||
|
||||
/**
|
||||
* device_create - creates a device and registers it with sysfs
|
||||
* @class: pointer to the struct class that this device should be registered to
|
||||
@ -1107,36 +1203,13 @@ static void device_create_release(struct device *dev)
|
||||
struct device *device_create(struct class *class, struct device *parent,
|
||||
dev_t devt, 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->release = device_create_release;
|
||||
|
||||
va_start(args, fmt);
|
||||
vsnprintf(dev->bus_id, BUS_ID_SIZE, fmt, args);
|
||||
va_end(args);
|
||||
retval = device_register(dev);
|
||||
if (retval)
|
||||
goto error;
|
||||
va_list vargs;
|
||||
struct device *dev;
|
||||
|
||||
va_start(vargs, fmt);
|
||||
dev = device_create_vargs(class, parent, devt, NULL, fmt, vargs);
|
||||
va_end(vargs);
|
||||
return dev;
|
||||
|
||||
error:
|
||||
kfree(dev);
|
||||
return ERR_PTR(retval);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_create);
|
||||
|
||||
|
@ -449,9 +449,21 @@ extern int __must_check device_reprobe(struct device *dev);
|
||||
/*
|
||||
* Easy functions for dynamically creating devices on the fly
|
||||
*/
|
||||
extern struct device *device_create_vargs(struct class *cls,
|
||||
struct device *parent,
|
||||
dev_t devt,
|
||||
void *drvdata,
|
||||
const char *fmt,
|
||||
va_list vargs);
|
||||
extern struct device *device_create(struct class *cls, struct device *parent,
|
||||
dev_t devt, const char *fmt, ...)
|
||||
__attribute__((format(printf, 4, 5)));
|
||||
extern struct device *device_create_drvdata(struct class *cls,
|
||||
struct device *parent,
|
||||
dev_t devt,
|
||||
void *drvdata,
|
||||
const char *fmt, ...)
|
||||
__attribute__((format(printf, 5, 6)));
|
||||
extern void device_destroy(struct class *cls, dev_t devt);
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user