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@xxxxxxxxxx> --- drivers/iio/iio_core.h | 6 ++++++ drivers/iio/industrialio-buffer.c | 10 ++++++---- drivers/iio/industrialio-core.c | 18 ++++++++++++++++-- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/drivers/iio/iio_core.h b/drivers/iio/iio_core.h index 43d44ec92781..ad6716fe1a93 100644 --- a/drivers/iio/iio_core.h +++ b/drivers/iio/iio_core.h @@ -12,11 +12,17 @@ #include <linux/kernel.h> #include <linux/device.h> +struct iio_buffer; struct iio_chan_spec; 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 887c71272e9c..62cb90385246 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -112,8 +112,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; @@ -178,8 +179,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 088e59042226..0d1880837776 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -1666,13 +1666,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; } @@ -1686,10 +1697,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; } @@ -1709,7 +1722,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