aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/iio/iio_core.h3
-rw-r--r--drivers/iio/industrialio-buffer.c12
-rw-r--r--drivers/iio/industrialio-core.c30
-rw-r--r--drivers/iio/industrialio-event.c5
-rw-r--r--drivers/iio/industrialio-trigger.c6
5 files changed, 46 insertions, 10 deletions
diff --git a/drivers/iio/iio_core.h b/drivers/iio/iio_core.h
index fced02cadcc3..7d5b179c1fe7 100644
--- a/drivers/iio/iio_core.h
+++ b/drivers/iio/iio_core.h
@@ -46,6 +46,9 @@ int __iio_add_chan_devattr(const char *postfix,
struct list_head *attr_list);
void iio_free_chan_devattr_list(struct list_head *attr_list);
+int iio_device_register_sysfs_group(struct iio_dev *indio_dev,
+ const struct attribute_group *group);
+
ssize_t iio_format_value(char *buf, unsigned int type, int size, int *vals);
/* Event interface flags */
diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index 2f7426a2f47c..cc846988fdb9 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -1287,7 +1287,9 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer,
buffer->buffer_group.name = "buffer";
buffer->buffer_group.attrs = attr;
- indio_dev->groups[indio_dev->groupcounter++] = &buffer->buffer_group;
+ ret = iio_device_register_sysfs_group(indio_dev, &buffer->buffer_group);
+ if (ret)
+ goto error_free_buffer_attrs;
attrcount = 0;
INIT_LIST_HEAD(&buffer->scan_el_dev_attr_list);
@@ -1330,14 +1332,20 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer,
list_for_each_entry(p, &buffer->scan_el_dev_attr_list, l)
buffer->scan_el_group.attrs[attrn++] = &p->dev_attr.attr;
- indio_dev->groups[indio_dev->groupcounter++] = &buffer->scan_el_group;
+
+ ret = iio_device_register_sysfs_group(indio_dev, &buffer->scan_el_group);
+ if (ret)
+ goto error_free_scan_el_attrs;
return 0;
+error_free_scan_el_attrs:
+ kfree(buffer->scan_el_group.attrs);
error_free_scan_mask:
bitmap_free(buffer->scan_mask);
error_cleanup_dynamic:
iio_free_chan_devattr_list(&buffer->scan_el_dev_attr_list);
+error_free_buffer_attrs:
kfree(buffer->buffer_group.attrs);
return ret;
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 92efbc245098..924f3a167125 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -1454,6 +1454,25 @@ static ssize_t iio_store_timestamp_clock(struct device *dev,
return len;
}
+int iio_device_register_sysfs_group(struct iio_dev *indio_dev,
+ const struct attribute_group *group)
+{
+ struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
+ const struct attribute_group **new, **old = iio_dev_opaque->groups;
+ unsigned int cnt = iio_dev_opaque->groupcounter;
+
+ new = krealloc(old, sizeof(*new) * (cnt + 2), GFP_KERNEL);
+ if (!new)
+ return -ENOMEM;
+
+ new[iio_dev_opaque->groupcounter++] = group;
+ new[iio_dev_opaque->groupcounter] = NULL;
+
+ iio_dev_opaque->groups = new;
+
+ return 0;
+}
+
static DEVICE_ATTR(current_timestamp_clock, S_IRUGO | S_IWUSR,
iio_show_timestamp_clock, iio_store_timestamp_clock);
@@ -1527,8 +1546,10 @@ static int iio_device_register_sysfs(struct iio_dev *indio_dev)
if (clk)
iio_dev_opaque->chan_attr_group.attrs[attrn++] = clk;
- indio_dev->groups[indio_dev->groupcounter++] =
- &iio_dev_opaque->chan_attr_group;
+ ret = iio_device_register_sysfs_group(indio_dev,
+ &iio_dev_opaque->chan_attr_group);
+ if (ret)
+ goto error_clear_attrs;
return 0;
@@ -1545,6 +1566,7 @@ static void iio_device_unregister_sysfs(struct iio_dev *indio_dev)
iio_free_chan_devattr_list(&iio_dev_opaque->channel_attr_list);
kfree(iio_dev_opaque->chan_attr_group.attrs);
iio_dev_opaque->chan_attr_group.attrs = NULL;
+ kfree(iio_dev_opaque->groups);
}
static void iio_dev_release(struct device *device)
@@ -1594,7 +1616,6 @@ struct iio_dev *iio_device_alloc(struct device *parent, int sizeof_priv)
ALIGN(sizeof(struct iio_dev_opaque), IIO_ALIGN);
dev->dev.parent = parent;
- dev->dev.groups = dev->groups;
dev->dev.type = &iio_device_type;
dev->dev.bus = &iio_bus_type;
device_initialize(&dev->dev);
@@ -1857,6 +1878,9 @@ int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod)
indio_dev->chrdev.owner = this_mod;
}
+ /* assign device groups now; they should be all registered now */
+ indio_dev->dev.groups = iio_dev_opaque->groups;
+
ret = cdev_device_add(&indio_dev->chrdev, &indio_dev->dev);
if (ret < 0)
goto error_unreg_eventset;
diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c
index 7e532117ac55..ea8947cc21e4 100644
--- a/drivers/iio/industrialio-event.c
+++ b/drivers/iio/industrialio-event.c
@@ -544,7 +544,10 @@ int iio_device_register_eventset(struct iio_dev *indio_dev)
/* Add all elements from the list. */
list_for_each_entry(p, &ev_int->dev_attr_list, l)
ev_int->group.attrs[attrn++] = &p->dev_attr.attr;
- indio_dev->groups[indio_dev->groupcounter++] = &ev_int->group;
+
+ ret = iio_device_register_sysfs_group(indio_dev, &ev_int->group);
+ if (ret)
+ goto error_free_setup_event_lines;
ev_int->ioctl_handler.ioctl = iio_event_ioctl;
iio_device_ioctl_handler_register(&iio_dev_opaque->indio_dev,
diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c
index 438d5012e8b8..a035d5c2a445 100644
--- a/drivers/iio/industrialio-trigger.c
+++ b/drivers/iio/industrialio-trigger.c
@@ -694,10 +694,8 @@ EXPORT_SYMBOL(iio_trigger_validate_own_device);
int iio_device_register_trigger_consumer(struct iio_dev *indio_dev)
{
- indio_dev->groups[indio_dev->groupcounter++] =
- &iio_trigger_consumer_attr_group;
-
- return 0;
+ return iio_device_register_sysfs_group(indio_dev,
+ &iio_trigger_consumer_attr_group);
}
void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev)