[PATCH v3 09/11] iio: core: wrap iio device & buffer into struct for character devices

From: Alexandru Ardelean
Date: Mon Feb 01 2021 - 10:26:43 EST


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 | 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 49996bed5f4c..692f721588e2 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 c68130885d83..8af85838d1c2 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -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,10 +1736,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;
}
@@ -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;
--
2.17.1