From: Rodrigo Alencar <[email protected]>

Move logic to create a channel prefix for naming attribute files into a
separate __iio_chan_prefix_emit() function for reuse. The dev pointer is
passed to __iio_device_attr_init() so that WARN() replaced by dev_err().
The new helper is going to be used to expose channel relationships as
sysfs attributes.

Signed-off-by: Rodrigo Alencar <[email protected]>
---
 drivers/iio/industrialio-core.c | 169 ++++++++++++++++------------------------
 1 file changed, 68 insertions(+), 101 deletions(-)

diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 98fc00343dc5..ecc69adf61de 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -25,6 +25,7 @@
 #include <linux/poll.h>
 #include <linux/property.h>
 #include <linux/sched.h>
+#include <linux/seq_buf.h>
 #include <linux/slab.h>
 #include <linux/wait.h>
 
@@ -199,6 +200,58 @@ static const char * const iio_chan_info_postfix[] = {
        [IIO_CHAN_INFO_CONVDELAY] = "convdelay",
        [IIO_CHAN_INFO_POWERFACTOR] = "powerfactor",
 };
+
+static ssize_t __iio_chan_prefix_emit(struct device *dev,
+                                     const struct iio_chan_spec *chan,
+                                     enum iio_shared_by shared_by,
+                                     char *buf, size_t len)
+{
+       const char *type = iio_chan_type_name_spec[chan->type];
+       const char *dir = iio_direction[chan->output];
+       struct seq_buf s;
+
+       seq_buf_init(&s, buf, len);
+
+       switch (shared_by) {
+       case IIO_SHARED_BY_ALL:
+               break;
+       case IIO_SHARED_BY_DIR:
+               seq_buf_printf(&s, "%s", dir);
+               break;
+       case IIO_SHARED_BY_TYPE:
+               seq_buf_printf(&s, "%s_%s", dir, type);
+               if (chan->differential)
+                       seq_buf_printf(&s, "-%s", type);
+               break;
+       case IIO_SEPARATE:
+               if (chan->indexed) {
+                       seq_buf_printf(&s, "%s_%s%d", dir, type, chan->channel);
+                       if (chan->differential)
+                               seq_buf_printf(&s, "-%s%d", type, 
chan->channel2);
+               } else {
+                       if (chan->differential) {
+                               dev_err(dev, "Differential channels must be 
indexed\n");
+                               return -EINVAL;
+                       }
+                       seq_buf_printf(&s, "%s_%s", dir, type);
+               }
+
+               if (chan->modified) {
+                       if (chan->differential) {
+                               dev_err(dev, "Differential channels can not 
have modifier\n");
+                               return -EINVAL;
+                       }
+                       seq_buf_printf(&s, "_%s", 
iio_modifier_names[chan->channel2]);
+               }
+
+               if (chan->extend_name)
+                       seq_buf_printf(&s, "_%s", chan->extend_name);
+               break;
+       }
+
+       return seq_buf_has_overflowed(&s) ? -EOVERFLOW : s.len;
+}
+
 /**
  * iio_device_id() - query the unique ID for the device
  * @indio_dev:         Device structure whose ID is being queried
@@ -1088,7 +1141,8 @@ static ssize_t iio_write_channel_info(struct device *dev,
 }
 
 static
-int __iio_device_attr_init(struct device_attribute *dev_attr,
+int __iio_device_attr_init(struct device *dev,
+                          struct device_attribute *dev_attr,
                           const char *postfix,
                           struct iio_chan_spec const *chan,
                           ssize_t (*readfunc)(struct device *dev,
@@ -1100,106 +1154,22 @@ int __iio_device_attr_init(struct device_attribute 
*dev_attr,
                                                size_t len),
                           enum iio_shared_by shared_by)
 {
-       int ret = 0;
-       char *name = NULL;
-       char *full_postfix;
+       char prefix[NAME_MAX + 1];
+       ssize_t ret;
 
        sysfs_attr_init(&dev_attr->attr);
 
-       /* Build up postfix of <extend_name>_<modifier>_postfix */
-       if (chan->modified && (shared_by == IIO_SEPARATE)) {
-               if (chan->extend_name)
-                       full_postfix = kasprintf(GFP_KERNEL, "%s_%s_%s",
-                                                
iio_modifier_names[chan->channel2],
-                                                chan->extend_name,
-                                                postfix);
-               else
-                       full_postfix = kasprintf(GFP_KERNEL, "%s_%s",
-                                                
iio_modifier_names[chan->channel2],
-                                                postfix);
-       } else {
-               if (chan->extend_name == NULL || shared_by != IIO_SEPARATE)
-                       full_postfix = kstrdup(postfix, GFP_KERNEL);
-               else
-                       full_postfix = kasprintf(GFP_KERNEL,
-                                                "%s_%s",
-                                                chan->extend_name,
-                                                postfix);
-       }
-       if (full_postfix == NULL)
+       ret = __iio_chan_prefix_emit(dev, chan, shared_by, prefix, 
sizeof(prefix));
+       if (ret < 0)
+               return ret;
+
+       if (ret)
+               dev_attr->attr.name = kasprintf(GFP_KERNEL, "%s_%s", prefix, 
postfix);
+       else
+               dev_attr->attr.name = kstrdup(postfix, GFP_KERNEL);
+       if (!dev_attr->attr.name)
                return -ENOMEM;
 
-       if (chan->differential) { /* Differential can not have modifier */
-               switch (shared_by) {
-               case IIO_SHARED_BY_ALL:
-                       name = kasprintf(GFP_KERNEL, "%s", full_postfix);
-                       break;
-               case IIO_SHARED_BY_DIR:
-                       name = kasprintf(GFP_KERNEL, "%s_%s",
-                                               iio_direction[chan->output],
-                                               full_postfix);
-                       break;
-               case IIO_SHARED_BY_TYPE:
-                       name = kasprintf(GFP_KERNEL, "%s_%s-%s_%s",
-                                           iio_direction[chan->output],
-                                           iio_chan_type_name_spec[chan->type],
-                                           iio_chan_type_name_spec[chan->type],
-                                           full_postfix);
-                       break;
-               case IIO_SEPARATE:
-                       if (!chan->indexed) {
-                               WARN(1, "Differential channels must be 
indexed\n");
-                               ret = -EINVAL;
-                               goto error_free_full_postfix;
-                       }
-                       name = kasprintf(GFP_KERNEL,
-                                           "%s_%s%d-%s%d_%s",
-                                           iio_direction[chan->output],
-                                           iio_chan_type_name_spec[chan->type],
-                                           chan->channel,
-                                           iio_chan_type_name_spec[chan->type],
-                                           chan->channel2,
-                                           full_postfix);
-                       break;
-               }
-       } else { /* Single ended */
-               switch (shared_by) {
-               case IIO_SHARED_BY_ALL:
-                       name = kasprintf(GFP_KERNEL, "%s", full_postfix);
-                       break;
-               case IIO_SHARED_BY_DIR:
-                       name = kasprintf(GFP_KERNEL, "%s_%s",
-                                               iio_direction[chan->output],
-                                               full_postfix);
-                       break;
-               case IIO_SHARED_BY_TYPE:
-                       name = kasprintf(GFP_KERNEL, "%s_%s_%s",
-                                           iio_direction[chan->output],
-                                           iio_chan_type_name_spec[chan->type],
-                                           full_postfix);
-                       break;
-
-               case IIO_SEPARATE:
-                       if (chan->indexed)
-                               name = kasprintf(GFP_KERNEL, "%s_%s%d_%s",
-                                                   iio_direction[chan->output],
-                                                   
iio_chan_type_name_spec[chan->type],
-                                                   chan->channel,
-                                                   full_postfix);
-                       else
-                               name = kasprintf(GFP_KERNEL, "%s_%s_%s",
-                                                   iio_direction[chan->output],
-                                                   
iio_chan_type_name_spec[chan->type],
-                                                   full_postfix);
-                       break;
-               }
-       }
-       if (name == NULL) {
-               ret = -ENOMEM;
-               goto error_free_full_postfix;
-       }
-       dev_attr->attr.name = name;
-
        if (readfunc) {
                dev_attr->attr.mode |= 0444;
                dev_attr->show = readfunc;
@@ -1210,10 +1180,7 @@ int __iio_device_attr_init(struct device_attribute 
*dev_attr,
                dev_attr->store = writefunc;
        }
 
-error_free_full_postfix:
-       kfree(full_postfix);
-
-       return ret;
+       return 0;
 }
 
 static void __iio_device_attr_deinit(struct device_attribute *dev_attr)
@@ -1242,7 +1209,7 @@ int __iio_add_chan_devattr(const char *postfix,
        iio_attr = kzalloc_obj(*iio_attr);
        if (iio_attr == NULL)
                return -ENOMEM;
-       ret = __iio_device_attr_init(&iio_attr->dev_attr,
+       ret = __iio_device_attr_init(dev, &iio_attr->dev_attr,
                                     postfix, chan,
                                     readfunc, writefunc, shared_by);
        if (ret)

-- 
2.43.0



Reply via email to