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;
}