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

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

 



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



[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