iio: core: wrap iio device & buffer into struct for character devices
authorAlexandru Ardelean <alexandru.ardelean@analog.com>
Mon, 15 Feb 2021 10:40:35 +0000 (12:40 +0200)
committerJonathan Cameron <Jonathan.Cameron@huawei.com>
Thu, 11 Mar 2021 20:47:04 +0000 (20:47 +0000)
In order to keep backwards compatibility with the current chardev
mechanism, and in order to add support for multiple buffers per IIO device,
we need to pass both the IIO device & IIO buffer to the chardev.

This is particularly needed for the iio_buffer_read_outer() function, where
we need to pass another buffer object than 'indio_dev->buffer'.

Since we'll also open some chardevs via anon inodes, we can pass extra
buffers in that function by assigning another object to the
iio_dev_buffer_pair object.

Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
Link: https://lore.kernel.org/r/20210215104043.91251-17-alexandru.ardelean@analog.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
drivers/iio/iio_core.h
drivers/iio/industrialio-buffer.c
drivers/iio/industrialio-core.c

index 731f517..87868ff 100644 (file)
@@ -18,6 +18,11 @@ struct iio_dev;
 
 extern struct device_type iio_device_type;
 
+struct iio_dev_buffer_pair {
+       struct iio_dev          *indio_dev;
+       struct iio_buffer       *buffer;
+};
+
 #define IIO_IOCTL_UNHANDLED    1
 struct iio_ioctl_handler {
        struct list_head entry;
index ea91f95..232a60f 100644 (file)
@@ -104,8 +104,9 @@ static bool iio_buffer_ready(struct iio_dev *indio_dev, struct iio_buffer *buf,
 ssize_t iio_buffer_read_outer(struct file *filp, char __user *buf,
                              size_t n, loff_t *f_ps)
 {
-       struct iio_dev *indio_dev = filp->private_data;
-       struct iio_buffer *rb = indio_dev->buffer;
+       struct iio_dev_buffer_pair *ib = filp->private_data;
+       struct iio_buffer *rb = ib->buffer;
+       struct iio_dev *indio_dev = ib->indio_dev;
        DEFINE_WAIT_FUNC(wait, woken_wake_function);
        size_t datum_size;
        size_t to_wait;
@@ -170,8 +171,9 @@ ssize_t iio_buffer_read_outer(struct file *filp, char __user *buf,
 __poll_t iio_buffer_poll(struct file *filp,
                             struct poll_table_struct *wait)
 {
-       struct iio_dev *indio_dev = filp->private_data;
-       struct iio_buffer *rb = indio_dev->buffer;
+       struct iio_dev_buffer_pair *ib = filp->private_data;
+       struct iio_buffer *rb = ib->buffer;
+       struct iio_dev *indio_dev = ib->indio_dev;
 
        if (!indio_dev->info || rb == NULL)
                return 0;
index b8b149c..b96acfe 100644 (file)
@@ -1705,13 +1705,24 @@ static int iio_chrdev_open(struct inode *inode, struct file *filp)
 {
        struct iio_dev *indio_dev = container_of(inode->i_cdev,
                                                struct iio_dev, chrdev);
+       struct iio_dev_buffer_pair *ib;
 
        if (test_and_set_bit(IIO_BUSY_BIT_POS, &indio_dev->flags))
                return -EBUSY;
 
        iio_device_get(indio_dev);
 
-       filp->private_data = indio_dev;
+       ib = kmalloc(sizeof(*ib), GFP_KERNEL);
+       if (!ib) {
+               iio_device_put(indio_dev);
+               clear_bit(IIO_BUSY_BIT_POS, &indio_dev->flags);
+               return -ENOMEM;
+       }
+
+       ib->indio_dev = indio_dev;
+       ib->buffer = indio_dev->buffer;
+
+       filp->private_data = ib;
 
        return 0;
 }
@@ -1725,8 +1736,10 @@ static int iio_chrdev_open(struct inode *inode, struct file *filp)
  */
 static int iio_chrdev_release(struct inode *inode, struct file *filp)
 {
+       struct iio_dev_buffer_pair *ib = filp->private_data;
        struct iio_dev *indio_dev = container_of(inode->i_cdev,
                                                struct iio_dev, chrdev);
+       kfree(ib);
        clear_bit(IIO_BUSY_BIT_POS, &indio_dev->flags);
        iio_device_put(indio_dev);
 
@@ -1748,7 +1761,8 @@ void iio_device_ioctl_handler_unregister(struct iio_ioctl_handler *h)
 
 static long iio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
-       struct iio_dev *indio_dev = filp->private_data;
+       struct iio_dev_buffer_pair *ib = filp->private_data;
+       struct iio_dev *indio_dev = ib->indio_dev;
        struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
        struct iio_ioctl_handler *h;
        int ret = -ENODEV;