Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+83 −28
Original line number Original line Diff line number Diff line
@@ -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,
	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,
	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,
}
}
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;
+5 −0
Original line number Original line Diff line number Diff line
@@ -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);


/*
/*