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

Commit 621a1672 authored by Dmitry Torokhov's avatar Dmitry Torokhov Committed by Greg Kroah-Hartman
Browse files

driver core: Use attribute groups in struct device_type



Driver core: use attribute groups in struct device_type

Attribute groups are more flexible than attribute lists
(an attribute list can be represented by anonymous group)
so switch struct device_type to use them.

Also rework attribute creation for devices so that they all
cleaned up properly in case of errors.

Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
Cc: Kay Sievers <kay.sievers@novell.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent b8c5cec2
Loading
Loading
Loading
Loading
+69 −46
Original line number Diff line number Diff line
@@ -246,63 +246,94 @@ static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
	return count;
}

static int device_add_groups(struct device *dev)
static int device_add_attributes(struct device *dev,
				 struct device_attribute *attrs)
{
	int error = 0;
	int i;

	if (attrs) {
		for (i = 0; attr_name(attrs[i]); i++) {
			error = device_create_file(dev, &attrs[i]);
			if (error)
				break;
		}
		if (error)
			while (--i >= 0)
				device_remove_file(dev, &attrs[i]);
	}
	return error;
}

static void device_remove_attributes(struct device *dev,
				     struct device_attribute *attrs)
{
	int i;

	if (attrs)
		for (i = 0; attr_name(attrs[i]); i++)
			device_remove_file(dev, &attrs[i]);
}

static int device_add_groups(struct device *dev,
			     struct attribute_group **groups)
{
	int error = 0;
	int i;

	if (dev->groups) {
		for (i = 0; dev->groups[i]; i++) {
			error = sysfs_create_group(&dev->kobj, dev->groups[i]);
	if (groups) {
		for (i = 0; groups[i]; i++) {
			error = sysfs_create_group(&dev->kobj, groups[i]);
			if (error) {
				while (--i >= 0)
					sysfs_remove_group(&dev->kobj, dev->groups[i]);
				goto out;
					sysfs_remove_group(&dev->kobj, groups[i]);
				break;
			}
		}
	}
out:
	return error;
}

static void device_remove_groups(struct device *dev)
static void device_remove_groups(struct device *dev,
				 struct attribute_group **groups)
{
	int i;
	if (dev->groups) {
		for (i = 0; dev->groups[i]; i++) {
			sysfs_remove_group(&dev->kobj, dev->groups[i]);
		}
	}

	if (groups)
		for (i = 0; groups[i]; i++)
			sysfs_remove_group(&dev->kobj, groups[i]);
}

static int device_add_attrs(struct device *dev)
{
	struct class *class = dev->class;
	struct device_type *type = dev->type;
	int error = 0;
	int i;
	int error;

	if (class && class->dev_attrs) {
		for (i = 0; attr_name(class->dev_attrs[i]); i++) {
			error = device_create_file(dev, &class->dev_attrs[i]);
	if (class) {
		error = device_add_attributes(dev, class->dev_attrs);
		if (error)
				break;
		}
		if (error)
			while (--i >= 0)
				device_remove_file(dev, &class->dev_attrs[i]);
			return error;
	}

	if (type && type->attrs) {
		for (i = 0; attr_name(type->attrs[i]); i++) {
			error = device_create_file(dev, &type->attrs[i]);
	if (type) {
		error = device_add_groups(dev, type->groups);
		if (error)
				break;
			goto err_remove_class_attrs;
	}

	error = device_add_groups(dev, dev->groups);
	if (error)
			while (--i >= 0)
				device_remove_file(dev, &type->attrs[i]);
	}
		goto err_remove_type_groups;

	return 0;

 err_remove_type_groups:
	if (type)
		device_remove_groups(dev, type->groups);
 err_remove_class_attrs:
	if (class)
		device_remove_attributes(dev, class->dev_attrs);

	return error;
}
@@ -311,17 +342,14 @@ static void device_remove_attrs(struct device *dev)
{
	struct class *class = dev->class;
	struct device_type *type = dev->type;
	int i;

	if (class && class->dev_attrs) {
		for (i = 0; attr_name(class->dev_attrs[i]); i++)
			device_remove_file(dev, &class->dev_attrs[i]);
	}
	device_remove_groups(dev, dev->groups);

	if (type && type->attrs) {
		for (i = 0; attr_name(type->attrs[i]); i++)
			device_remove_file(dev, &type->attrs[i]);
	}
	if (type)
		device_remove_groups(dev, type->groups);

	if (class)
		device_remove_attributes(dev, class->dev_attrs);
}


@@ -638,8 +666,6 @@ int device_add(struct device *dev)

	if ((error = device_add_attrs(dev)))
		goto AttrsError;
	if ((error = device_add_groups(dev)))
		goto GroupError;
	if ((error = device_pm_add(dev)))
		goto PMError;
	if ((error = bus_add_device(dev)))
@@ -674,8 +700,6 @@ int device_add(struct device *dev)
	if (dev->bus)
		blocking_notifier_call_chain(&dev->bus->bus_notifier,
					     BUS_NOTIFY_DEL_DEVICE, dev);
	device_remove_groups(dev);
 GroupError:
	device_remove_attrs(dev);
 AttrsError:
	if (dev->devt_attr) {
@@ -838,7 +862,6 @@ void device_del(struct device * dev)
		}
	}
	device_remove_file(dev, &dev->uevent_attr);
	device_remove_groups(dev);
	device_remove_attrs(dev);
	bus_remove_device(dev);

+1 −1
Original line number Diff line number Diff line
@@ -332,7 +332,7 @@ extern struct class_device *class_device_create(struct class *cls,
extern void class_device_destroy(struct class *cls, dev_t devt);

struct device_type {
	struct device_attribute *attrs;
	struct attribute_group **groups;
	int (*uevent)(struct device *dev, char **envp, int num_envp,
		      char *buffer, int buffer_size);
	void (*release)(struct device *dev);