Thread (67 messages) 67 messages, 12 authors, 2022-10-06

Re: [PATCH v6 20/24] iio: buffer: add ioctl() to support opening extra buffers for IIO device

From: Alexandru Ardelean <hidden>
Date: 2021-02-28 18:05:55
Also in: lkml

On Sun, Feb 28, 2021 at 9:58 AM Lars-Peter Clausen [off-list ref] wrote:
On 2/15/21 11:40 AM, Alexandru Ardelean wrote:
quoted
[...]
  /**
   * iio_buffer_wakeup_poll - Wakes up the buffer waitqueue
   * @indio_dev: The IIO device
@@ -1343,6 +1371,96 @@ static void iio_buffer_unregister_legacy_sysfs_groups(struct iio_dev *indio_dev)
      kfree(iio_dev_opaque->legacy_scan_el_group.attrs);
  }
[...]
+static long iio_device_buffer_getfd(struct iio_dev *indio_dev, unsigned long arg)
+{
+     struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
+     int __user *ival = (int __user *)arg;
+     struct iio_dev_buffer_pair *ib;
+     struct iio_buffer *buffer;
+     int fd, idx, ret;
+
+     if (copy_from_user(&idx, ival, sizeof(idx)))
+             return -EFAULT;
If we only want to pass an int, we can pass that directly, no need to
pass it as a pointer.

int fd = arg;
I guess I can simplify this a bit.
quoted
+
+     if (idx >= iio_dev_opaque->attached_buffers_cnt)
+             return -ENODEV;
+
+     iio_device_get(indio_dev);
+
+     buffer = iio_dev_opaque->attached_buffers[idx];
+
+     if (test_and_set_bit(IIO_BUSY_BIT_POS, &buffer->flags)) {
+             ret = -EBUSY;
+             goto error_iio_dev_put;
+     }
+
+     ib = kzalloc(sizeof(*ib), GFP_KERNEL);
+     if (!ib) {
+             ret = -ENOMEM;
+             goto error_clear_busy_bit;
+     }
+
+     ib->indio_dev = indio_dev;
+     ib->buffer = buffer;
+
+     fd = anon_inode_getfd("iio:buffer", &iio_buffer_chrdev_fileops,
+                           ib, O_RDWR | O_CLOEXEC);
I wonder if we need to allow to pass flags, like e.g. O_NONBLOCK.

Something like
https://elixir.bootlin.com/linux/latest/source/fs/signalfd.c#L288
Umm, no idea.
I guess we could.
Would a syscall make more sense than an ioctl() here?
I guess for the ioctl() case we would need to change the type (of the
data) to some sort of

struct iio_buffer_get_fd {
      unsigned int buffer_idx;
      unsigned int fd_flags;
};

Or do we just let userspace use fcntl() to change flags to O_NONBLOCK ?
quoted
+     if (fd < 0) {
+             ret = fd;
+             goto error_free_ib;
+     }
+
+     if (copy_to_user(ival, &fd, sizeof(fd))) {
+             put_unused_fd(fd);
+             ret = -EFAULT;
+             goto error_free_ib;
+     }
Here we copy back the fd, but also return it. Just return is probably
enough.
Hmm.
Yes, it is a bit duplicate.
But it is a good point. Maybe we should return 0 to userspace.
quoted
+
+     return fd;
+
+error_free_ib:
+     kfree(ib);
+error_clear_busy_bit:
+     clear_bit(IIO_BUSY_BIT_POS, &buffer->flags);
+error_iio_dev_put:
+     iio_device_put(indio_dev);
+     return ret;
+}
[...]
diff --git a/include/linux/iio/iio-opaque.h b/include/linux/iio/iio-opaque.h
index b6ebc04af3e7..32addd5e790e 100644
--- a/include/linux/iio/iio-opaque.h
+++ b/include/linux/iio/iio-opaque.h
@@ -9,6 +9,7 @@
   * @event_interface:                event chrdevs associated with interrupt lines
   * @attached_buffers:               array of buffers statically attached by the driver
   * @attached_buffers_cnt:   number of buffers in the array of statically attached buffers
+ * @buffer_ioctl_handler:    ioctl() handler for this IIO device's buffer interface
   * @buffer_list:            list of all buffers currently attached
   * @channel_attr_list:              keep track of automatically created channel
   *                          attributes
@@ -28,6 +29,7 @@ struct iio_dev_opaque {
      struct iio_event_interface      *event_interface;
      struct iio_buffer               **attached_buffers;
      unsigned int                    attached_buffers_cnt;
+     struct iio_ioctl_handler        *buffer_ioctl_handler;
Can we just embedded this struct so we do not have to
allocate/deallocate it?
Unfortunately we can't.
The type of ' struct iio_ioctl_handler ' is stored in iio_core.h.
So, we don't know the size here. So we need to keep it as a pointer
and allocate it.
It is a bit of an unfortunate consequence of the design of this
generic ioctl() registering.
quoted
      struct list_head                buffer_list;
      struct list_head                channel_attr_list;
      struct attribute_group          chan_attr_group;
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help