Messages in this thread | | | Subject | Re: [PATCH v6 20/24] iio: buffer: add ioctl() to support opening extra buffers for IIO device | From | Lars-Peter Clausen <> | Date | Sun, 28 Feb 2021 08:57:00 +0100 |
| |
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;
| |