Skip to content

Commit

Permalink
Driver core: add device_create_vargs and device_create_drvdata
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Greg Kroah-Hartman committed May 20, 2008
1 parent c110a2b commit 8882b39
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 6 deletions.
85 changes: 79 additions & 6 deletions drivers/base/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1084,11 +1084,13 @@ static void device_create_release(struct device *dev)
}

/**
* device_create - 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
* @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.
Expand All @@ -1104,10 +1106,10 @@ static void device_create_release(struct device *dev)
* Note: the struct class passed to this function must have previously
* been created with a call to class_create().
*/
struct device *device_create(struct class *class, struct device *parent,
dev_t devt, const char *fmt, ...)
struct device *device_create_vargs(struct class *class, struct device *parent,
dev_t devt, void *drvdata, const char *fmt,
va_list args)
{
va_list args;
struct device *dev = NULL;
int retval = -ENODEV;

Expand All @@ -1124,10 +1126,9 @@ struct device *device_create(struct class *class, struct device *parent,
dev->class = class;
dev->parent = parent;
dev->release = device_create_release;
dev_set_drvdata(dev, drvdata);

va_start(args, fmt);
vsnprintf(dev->bus_id, BUS_ID_SIZE, fmt, args);
va_end(args);
retval = device_register(dev);
if (retval)
goto error;
Expand All @@ -1138,6 +1139,78 @@ struct device *device_create(struct class *class, struct device *parent,
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
* @parent: pointer to the parent struct device of this new device, if any
* @devt: the dev_t for the char device to be added
* @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(struct class *class, struct device *parent,
dev_t devt, const char *fmt, ...)
{
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;
}
EXPORT_SYMBOL_GPL(device_create);

static int __match_devt(struct device *dev, void *data)
Expand Down
12 changes: 12 additions & 0 deletions include/linux/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

/*
Expand Down

0 comments on commit 8882b39

Please sign in to comment.