On Sun, Feb 28, 2021 at 9:58 AM Lars-Peter Clausen <lars@xxxxxxxxxx> wrote: > > 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; I guess I can simplify this a bit. > > > + > > + 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 ? > > > + 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. > > > + > > + 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. > > > struct list_head buffer_list; > > struct list_head channel_attr_list; > > struct attribute_group chan_attr_group; > >