|
@@ -528,9 +528,12 @@ static int device_add_attrs(struct device *dev)
|
|
|
int error;
|
|
|
|
|
|
if (class) {
|
|
|
- error = device_add_attributes(dev, class->dev_attrs);
|
|
|
+ error = device_add_groups(dev, class->dev_groups);
|
|
|
if (error)
|
|
|
return error;
|
|
|
+ error = device_add_attributes(dev, class->dev_attrs);
|
|
|
+ if (error)
|
|
|
+ goto err_remove_class_groups;
|
|
|
error = device_add_bin_attributes(dev, class->dev_bin_attrs);
|
|
|
if (error)
|
|
|
goto err_remove_class_attrs;
|
|
@@ -563,6 +566,9 @@ static int device_add_attrs(struct device *dev)
|
|
|
err_remove_class_attrs:
|
|
|
if (class)
|
|
|
device_remove_attributes(dev, class->dev_attrs);
|
|
|
+ err_remove_class_groups:
|
|
|
+ if (class)
|
|
|
+ device_remove_groups(dev, class->dev_groups);
|
|
|
|
|
|
return error;
|
|
|
}
|
|
@@ -581,6 +587,7 @@ static void device_remove_attrs(struct device *dev)
|
|
|
if (class) {
|
|
|
device_remove_attributes(dev, class->dev_attrs);
|
|
|
device_remove_bin_attributes(dev, class->dev_bin_attrs);
|
|
|
+ device_remove_groups(dev, class->dev_groups);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1667,34 +1674,11 @@ 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.
|
|
|
- *
|
|
|
- * 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)
|
|
|
+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;
|
|
@@ -1711,6 +1695,7 @@ struct device *device_create_vargs(struct class *class, struct device *parent,
|
|
|
dev->devt = devt;
|
|
|
dev->class = class;
|
|
|
dev->parent = parent;
|
|
|
+ dev->groups = groups;
|
|
|
dev->release = device_create_release;
|
|
|
dev_set_drvdata(dev, drvdata);
|
|
|
|
|
@@ -1728,6 +1713,39 @@ error:
|
|
|
put_device(dev);
|
|
|
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);
|
|
|
|
|
|
/**
|
|
@@ -1767,6 +1785,50 @@ struct device *device_create(struct class *class, struct device *parent,
|
|
|
}
|
|
|
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)
|
|
|
{
|
|
|
const dev_t *devt = data;
|