int counter_sysfs_add()

in counter-sysfs.c [901:959]


int counter_sysfs_add(struct counter_device *const counter)
{
	struct device *const dev = &counter->dev;
	const size_t num_groups = counter->num_signals + counter->num_counts + 1;
	struct counter_attribute_group *cattr_groups;
	size_t i, j;
	int err;
	struct attribute_group *groups;
	struct counter_attribute *p;

	/* Allocate space for attribute groups (signals, counts, and ext) */
	cattr_groups = devm_kcalloc(dev, num_groups, sizeof(*cattr_groups),
				    GFP_KERNEL);
	if (!cattr_groups)
		return -ENOMEM;

	/* Initialize attribute lists */
	for (i = 0; i < num_groups; i++)
		INIT_LIST_HEAD(&cattr_groups[i].attr_list);

	/* Add Counter device sysfs attributes */
	err = counter_sysfs_attr_add(counter, cattr_groups);
	if (err < 0)
		return err;

	/* Allocate attribute group pointers for association with device */
	dev->groups = devm_kcalloc(dev, num_groups + 1, sizeof(*dev->groups),
				   GFP_KERNEL);
	if (!dev->groups)
		return -ENOMEM;

	/* Allocate space for attribute groups */
	groups = devm_kcalloc(dev, num_groups, sizeof(*groups), GFP_KERNEL);
	if (!groups)
		return -ENOMEM;

	/* Prepare each group of attributes for association */
	for (i = 0; i < num_groups; i++) {
		groups[i].name = cattr_groups[i].name;

		/* Allocate space for attribute pointers */
		groups[i].attrs = devm_kcalloc(dev,
					       cattr_groups[i].num_attr + 1,
					       sizeof(*groups[i].attrs),
					       GFP_KERNEL);
		if (!groups[i].attrs)
			return -ENOMEM;

		/* Add attribute pointers to attribute group */
		j = 0;
		list_for_each_entry(p, &cattr_groups[i].attr_list, l)
			groups[i].attrs[j++] = &p->dev_attr.attr;

		/* Associate attribute group */
		dev->groups[i] = &groups[i];
	}

	return 0;
}