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.ardel...@analog.com>
---
 drivers/iio/iio_core.h            |  5 +++++
 drivers/iio/industrialio-buffer.c | 10 ++++++----
 drivers/iio/industrialio-core.c   | 18 ++++++++++++++++--
 3 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/drivers/iio/iio_core.h b/drivers/iio/iio_core.h
index 731f5170d5b9..87868fff7d37 100644
--- a/drivers/iio/iio_core.h
+++ b/drivers/iio/iio_core.h
@@ -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;
diff --git a/drivers/iio/industrialio-buffer.c 
b/drivers/iio/industrialio-buffer.c
index d79d81485a3f..a6148ed24e41 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -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;
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 2e8e656e41dd..1be94df3e591 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -1703,13 +1703,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;
 }
@@ -1723,10 +1734,12 @@ 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);
        clear_bit(IIO_BUSY_BIT_POS, &indio_dev->flags);
        iio_device_put(indio_dev);
+       kfree(ib);
 
        return 0;
 }
@@ -1746,7 +1759,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;
-- 
2.17.1

Reply via email to