Re: [PATCH v2 06/12] iio: buffer: re-route scan_elements via it's kobj_type

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Jan 22, 2021 at 5:57 PM Alexandru Ardelean
<alexandru.ardelean@xxxxxxxxxx> wrote:
>
> The scan_elements attributes are solely located inside
> 'industrialio-buffer-sysfs.c'. In order to support more than one buffer per
> IIO device, we need to expand scan_elements attributes directly to IIO
> buffer object, and not the IIO device.
>
> This also requires that a new 'iio_buffer_attr' type be added which is
> mostly a copy of 'iio_dev_attr', but this expands to an IIO buffer object.
>
> The 'iio_dev_attr' type could have been re-used here, but managing 'device'
> objects is a bit more tricky (than it looks at first). A 'device' object
> needs to be initialized & managed and we only need to the 'kobj' to expand
> from the 'bufferX' directory back to an IIO buffer.
> kobjects are simpler to manage.

Something odd happened here.
I'm only seeing half the patches.
No idea if the others will show.
I'll leave this here for a while, and if they don't show up tomorrow
I'll re-send.
In the meantime, the set is visible here:
https://github.com/analogdevicesinc/linux/commits/iio-multibuffer3

>
> Signed-off-by: Alexandru Ardelean <alexandru.ardelean@xxxxxxxxxx>
> ---
>  drivers/iio/iio_core.h            |   5 +
>  drivers/iio/industrialio-buffer.c | 160 +++++++++++++++++++++++-------
>  drivers/iio/industrialio-core.c   |   1 -
>  3 files changed, 128 insertions(+), 38 deletions(-)
>
> diff --git a/drivers/iio/iio_core.h b/drivers/iio/iio_core.h
> index fced02cadcc3..43d44ec92781 100644
> --- a/drivers/iio/iio_core.h
> +++ b/drivers/iio/iio_core.h
> @@ -31,6 +31,11 @@ void iio_device_ioctl_handler_register(struct iio_dev *indio_dev,
>                                        struct iio_ioctl_handler *h);
>  void iio_device_ioctl_handler_unregister(struct iio_ioctl_handler *h);
>
> +int iio_attr_init(struct attribute *attr,
> +                 const char *postfix,
> +                 struct iio_chan_spec const *chan,
> +                 enum iio_shared_by shared_by);
> +
>  int __iio_add_chan_devattr(const char *postfix,
>                            struct iio_chan_spec const *chan,
>                            ssize_t (*func)(struct device *dev,
> diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
> index 628d78125126..524b897a1877 100644
> --- a/drivers/iio/industrialio-buffer.c
> +++ b/drivers/iio/industrialio-buffer.c
> @@ -26,6 +26,26 @@
>  #include <linux/iio/buffer.h>
>  #include <linux/iio/buffer_impl.h>
>
> +/**
> + * struct iio_buf_attr - iio buffer specific attribute
> + * @attr:      underlying attribute
> + * @address:   associated register address
> + * @l:         list head for maintaining list of dynamically created attrs
> + * @c:         specification for the underlying channel
> + * @show:      sysfs show hook for this attribute
> + * @store:     sysfs store hook for this attribute
> + */
> +struct iio_buf_attr {
> +       struct attribute attr;
> +       u64 address;
> +       struct list_head l;
> +       struct iio_chan_spec const *c;
> +       ssize_t (*show)(struct iio_buffer *buffer, struct iio_buf_attr *attr,
> +                       char *buf);
> +       ssize_t (*store)(struct iio_buffer *buffer, struct iio_buf_attr *attr,
> +                        const char *buf, size_t count);
> +};
> +
>  static const char * const iio_endian_prefix[] = {
>         [IIO_BE] = "be",
>         [IIO_LE] = "le",
> @@ -210,18 +230,17 @@ void iio_buffer_init(struct iio_buffer *buffer)
>  }
>  EXPORT_SYMBOL(iio_buffer_init);
>
> -static ssize_t iio_show_scan_index(struct device *dev,
> -                                  struct device_attribute *attr,
> +static ssize_t iio_show_scan_index(struct iio_buffer *buffer,
> +                                  struct iio_buf_attr *attr,
>                                    char *buf)
>  {
> -       return sprintf(buf, "%u\n", to_iio_dev_attr(attr)->c->scan_index);
> +       return sprintf(buf, "%u\n", attr->c->scan_index);
>  }
>
> -static ssize_t iio_show_fixed_type(struct device *dev,
> -                                  struct device_attribute *attr,
> +static ssize_t iio_show_fixed_type(struct iio_buffer *buffer,
> +                                  struct iio_buf_attr *this_attr,
>                                    char *buf)
>  {
> -       struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
>         u8 type = this_attr->c->scan_type.endianness;
>
>         if (type == IIO_CPU) {
> @@ -248,17 +267,14 @@ static ssize_t iio_show_fixed_type(struct device *dev,
>                        this_attr->c->scan_type.shift);
>  }
>
> -static ssize_t iio_scan_el_show(struct device *dev,
> -                               struct device_attribute *attr,
> +static ssize_t iio_scan_el_show(struct iio_buffer *buffer,
> +                               struct iio_buf_attr *attr,
>                                 char *buf)
>  {
>         int ret;
> -       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> -       struct iio_buffer *buffer = indio_dev->buffer;
>
>         /* Ensure ret is 0 or 1. */
> -       ret = !!test_bit(to_iio_dev_attr(attr)->address,
> -                      buffer->scan_mask);
> +       ret = !!test_bit(attr->address, buffer->scan_mask);
>
>         return sprintf(buf, "%d\n", ret);
>  }
> @@ -359,16 +375,14 @@ static int iio_scan_mask_query(struct iio_dev *indio_dev,
>         return !!test_bit(bit, buffer->scan_mask);
>  };
>
> -static ssize_t iio_scan_el_store(struct device *dev,
> -                                struct device_attribute *attr,
> +static ssize_t iio_scan_el_store(struct iio_buffer *buffer,
> +                                struct iio_buf_attr *this_attr,
>                                  const char *buf,
>                                  size_t len)
>  {
> +       struct iio_dev *indio_dev = buffer->indio_dev;
>         int ret;
>         bool state;
> -       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> -       struct iio_buffer *buffer = indio_dev->buffer;
> -       struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
>
>         ret = strtobool(buf, &state);
>         if (ret < 0)
> @@ -398,24 +412,20 @@ static ssize_t iio_scan_el_store(struct device *dev,
>
>  }
>
> -static ssize_t iio_scan_el_ts_show(struct device *dev,
> -                                  struct device_attribute *attr,
> +static ssize_t iio_scan_el_ts_show(struct iio_buffer *buffer,
> +                                  struct iio_buf_attr *attr,
>                                    char *buf)
>  {
> -       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> -       struct iio_buffer *buffer = indio_dev->buffer;
> -
>         return sprintf(buf, "%d\n", buffer->scan_timestamp);
>  }
>
> -static ssize_t iio_scan_el_ts_store(struct device *dev,
> -                                   struct device_attribute *attr,
> +static ssize_t iio_scan_el_ts_store(struct iio_buffer *buffer,
> +                                   struct iio_buf_attr *attr,
>                                     const char *buf,
>                                     size_t len)
>  {
> +       struct iio_dev *indio_dev = buffer->indio_dev;
>         int ret;
> -       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> -       struct iio_buffer *buffer = indio_dev->buffer;
>         bool state;
>
>         ret = strtobool(buf, &state);
> @@ -434,13 +444,88 @@ static ssize_t iio_scan_el_ts_store(struct device *dev,
>         return ret ? ret : len;
>  }
>
> +static int __iio_add_chan_bufattr(const char *postfix,
> +                                 struct iio_chan_spec const *chan,
> +                                 ssize_t (*readfunc)(struct iio_buffer *buffer,
> +                                                     struct iio_buf_attr *attr,
> +                                                     char *buf),
> +                                 ssize_t (*writefunc)(struct iio_buffer *buffer,
> +                                                      struct iio_buf_attr *attr,
> +                                                      const char *buf,
> +                                                      size_t len),
> +                                 u64 mask,
> +                                 enum iio_shared_by shared_by,
> +                                 struct device *dev,
> +                                 struct list_head *attr_list)
> +{
> +       struct iio_buf_attr *iio_attr, *t;
> +       int ret;
> +
> +       iio_attr = kzalloc(sizeof(*iio_attr), GFP_KERNEL);
> +       if (iio_attr == NULL)
> +               return -ENOMEM;
> +
> +       ret = iio_attr_init(&iio_attr->attr, postfix, chan, shared_by);
> +       if (ret)
> +               goto error_iio_buf_attr_free;
> +
> +       iio_attr->c = chan;
> +       iio_attr->address = mask;
> +       list_for_each_entry(t, attr_list, l) {
> +               if (strcmp(t->attr.name, iio_attr->attr.name) == 0) {
> +                       if (shared_by == IIO_SEPARATE)
> +                               dev_err(dev, "tried to double register : %s\n",
> +                                       t->attr.name);
> +                       ret = -EBUSY;
> +                       goto error_iio_buf_attr_deinit;
> +               }
> +       }
> +       list_add(&iio_attr->l, attr_list);
> +
> +       if (readfunc) {
> +               iio_attr->attr.mode |= S_IRUGO;
> +               iio_attr->show = readfunc;
> +       }
> +
> +       if (writefunc) {
> +               iio_attr->attr.mode |= S_IWUSR;
> +               iio_attr->store = writefunc;
> +       }
> +
> +       return 0;
> +
> +error_iio_buf_attr_deinit:
> +       kfree(iio_attr->attr.name);
> +error_iio_buf_attr_free:
> +       kfree(iio_attr);
> +       return ret;
> +}
> +
> +/**
> + * iio_free_chan_bufattr_list() - Free a list of IIO buffer attributes
> + * @attr_list: List of IIO buffer attributes
> + *
> + * This function frees the memory allocated for each of the IIO buffer
> + * attributes in the list.
> + */
> +static void iio_free_chan_bufattr_list(struct list_head *attr_list)
> +{
> +       struct iio_buf_attr *p, *n;
> +
> +       list_for_each_entry_safe(p, n, attr_list, l) {
> +               list_del(&p->l);
> +               kfree(p->attr.name);
> +               kfree(p);
> +       }
> +}
> +
>  static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev,
>                                         struct iio_buffer *buffer,
>                                         const struct iio_chan_spec *chan)
>  {
>         int ret, attrcount = 0;
>
> -       ret = __iio_add_chan_devattr("index",
> +       ret = __iio_add_chan_bufattr("index",
>                                      chan,
>                                      &iio_show_scan_index,
>                                      NULL,
> @@ -451,7 +536,7 @@ static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev,
>         if (ret)
>                 return ret;
>         attrcount++;
> -       ret = __iio_add_chan_devattr("type",
> +       ret = __iio_add_chan_bufattr("type",
>                                      chan,
>                                      &iio_show_fixed_type,
>                                      NULL,
> @@ -463,7 +548,7 @@ static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev,
>                 return ret;
>         attrcount++;
>         if (chan->type != IIO_TIMESTAMP)
> -               ret = __iio_add_chan_devattr("en",
> +               ret = __iio_add_chan_bufattr("en",
>                                              chan,
>                                              &iio_scan_el_show,
>                                              &iio_scan_el_store,
> @@ -472,7 +557,7 @@ static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev,
>                                              &indio_dev->dev,
>                                              &buffer->scan_el_dev_attr_list);
>         else
> -               ret = __iio_add_chan_devattr("en",
> +               ret = __iio_add_chan_bufattr("en",
>                                              chan,
>                                              &iio_scan_el_ts_show,
>                                              &iio_scan_el_ts_store,
> @@ -1251,6 +1336,7 @@ static struct attribute *iio_buffer_attrs[] = {
>  };
>
>  #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
> +#define to_iio_buf_attr(_attr) container_of(_attr, struct iio_buf_attr, attr)
>
>  static ssize_t iio_buffer_dir_attr_show(struct kobject *kobj,
>                                         struct attribute *attr,
> @@ -1291,9 +1377,9 @@ static ssize_t iio_scan_el_dir_attr_show(struct kobject *kobj,
>                                          char *buf)
>  {
>         struct iio_buffer *buffer = container_of(kobj, struct iio_buffer, scan_el_dir);
> -       struct device_attribute *dattr = to_dev_attr(attr);
> +       struct iio_buf_attr *battr = to_iio_buf_attr(attr);
>
> -       return dattr->show(&buffer->indio_dev->dev, dattr, buf);
> +       return battr->show(buffer, battr, buf);
>  }
>
>  static ssize_t iio_scan_el_dir_attr_store(struct kobject *kobj,
> @@ -1302,9 +1388,9 @@ static ssize_t iio_scan_el_dir_attr_store(struct kobject *kobj,
>                                           size_t len)
>  {
>         struct iio_buffer *buffer = container_of(kobj, struct iio_buffer, scan_el_dir);
> -       struct device_attribute *dattr = to_dev_attr(attr);
> +       struct iio_buf_attr *battr = to_iio_buf_attr(attr);
>
> -       return dattr->store(&buffer->indio_dev->dev, dattr, buf, len);
> +       return battr->store(buffer, battr, buf, len);
>  }
>
>  static const struct sysfs_ops iio_scan_el_dir_sysfs_ops = {
> @@ -1372,7 +1458,7 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer,
>                                              struct iio_dev *indio_dev,
>                                              unsigned int idx)
>  {
> -       struct iio_dev_attr *p;
> +       struct iio_buf_attr *p;
>         struct attribute **attr;
>         int ret, i, attrn, attrcount;
>         const struct iio_chan_spec *channels;
> @@ -1453,7 +1539,7 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer,
>
>         attrn = 0;
>         list_for_each_entry(p, &buffer->scan_el_dev_attr_list, l)
> -               buffer->scan_el_attrs[attrn++] = &p->dev_attr.attr;
> +               buffer->scan_el_attrs[attrn++] = &p->attr;
>
>         ret = iio_sysfs_add_attrs(&buffer->scan_el_dir, buffer->scan_el_attrs);
>         if (ret)
> @@ -1469,7 +1555,7 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer,
>         bitmap_free(buffer->scan_mask);
>  error_cleanup_dynamic:
>         iio_sysfs_del_attrs(&buffer->buffer_dir, buffer->buffer_attrs);
> -       iio_free_chan_devattr_list(&buffer->scan_el_dev_attr_list);
> +       iio_free_chan_bufattr_list(&buffer->scan_el_dev_attr_list);
>  error_buffer_kobject_put:
>         kobject_put(&buffer->buffer_dir);
>  error_buffer_free_attrs:
> diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
> index b8f7261945f5..088e59042226 100644
> --- a/drivers/iio/industrialio-core.c
> +++ b/drivers/iio/industrialio-core.c
> @@ -967,7 +967,6 @@ static ssize_t iio_write_channel_info(struct device *dev,
>         return len;
>  }
>
> -static
>  int iio_attr_init(struct attribute *attr,
>                   const char *postfix,
>                   struct iio_chan_spec const *chan,
> --
> 2.17.1
>



[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux