lkml.org 
[lkml]   [2021]   [Feb]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
SubjectRe: [PATCH v6 20/24] iio: buffer: add ioctl() to support opening extra buffers for IIO device
From
Date
On 2/15/21 11:40 AM, Alexandru Ardelean wrote:
> [...]
> /**
> * 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;

> +
> + 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

> + 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.

> +
> + 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?

> struct list_head buffer_list;
> struct list_head channel_attr_list;
> struct attribute_group chan_attr_group;


\
 
 \ /
  Last update: 2021-02-28 08:59    [W:2.019 / U:0.000 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site