Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iio: core: wrap iio device & buffer into struct for character devices

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>

authored by

Alexandru Ardelean and committed by
Jonathan Cameron
be24dcb1 4991f3ea

+27 -6
+5
drivers/iio/iio_core.h
··· 18 18 19 19 extern struct device_type iio_device_type; 20 20 21 + struct iio_dev_buffer_pair { 22 + struct iio_dev *indio_dev; 23 + struct iio_buffer *buffer; 24 + }; 25 + 21 26 #define IIO_IOCTL_UNHANDLED 1 22 27 struct iio_ioctl_handler { 23 28 struct list_head entry;
+6 -4
drivers/iio/industrialio-buffer.c
··· 104 104 ssize_t iio_buffer_read_outer(struct file *filp, char __user *buf, 105 105 size_t n, loff_t *f_ps) 106 106 { 107 - struct iio_dev *indio_dev = filp->private_data; 108 - struct iio_buffer *rb = indio_dev->buffer; 107 + struct iio_dev_buffer_pair *ib = filp->private_data; 108 + struct iio_buffer *rb = ib->buffer; 109 + struct iio_dev *indio_dev = ib->indio_dev; 109 110 DEFINE_WAIT_FUNC(wait, woken_wake_function); 110 111 size_t datum_size; 111 112 size_t to_wait; ··· 171 170 __poll_t iio_buffer_poll(struct file *filp, 172 171 struct poll_table_struct *wait) 173 172 { 174 - struct iio_dev *indio_dev = filp->private_data; 175 - struct iio_buffer *rb = indio_dev->buffer; 173 + struct iio_dev_buffer_pair *ib = filp->private_data; 174 + struct iio_buffer *rb = ib->buffer; 175 + struct iio_dev *indio_dev = ib->indio_dev; 176 176 177 177 if (!indio_dev->info || rb == NULL) 178 178 return 0;
+16 -2
drivers/iio/industrialio-core.c
··· 1705 1705 { 1706 1706 struct iio_dev *indio_dev = container_of(inode->i_cdev, 1707 1707 struct iio_dev, chrdev); 1708 + struct iio_dev_buffer_pair *ib; 1708 1709 1709 1710 if (test_and_set_bit(IIO_BUSY_BIT_POS, &indio_dev->flags)) 1710 1711 return -EBUSY; 1711 1712 1712 1713 iio_device_get(indio_dev); 1713 1714 1714 - filp->private_data = indio_dev; 1715 + ib = kmalloc(sizeof(*ib), GFP_KERNEL); 1716 + if (!ib) { 1717 + iio_device_put(indio_dev); 1718 + clear_bit(IIO_BUSY_BIT_POS, &indio_dev->flags); 1719 + return -ENOMEM; 1720 + } 1721 + 1722 + ib->indio_dev = indio_dev; 1723 + ib->buffer = indio_dev->buffer; 1724 + 1725 + filp->private_data = ib; 1715 1726 1716 1727 return 0; 1717 1728 } ··· 1736 1725 */ 1737 1726 static int iio_chrdev_release(struct inode *inode, struct file *filp) 1738 1727 { 1728 + struct iio_dev_buffer_pair *ib = filp->private_data; 1739 1729 struct iio_dev *indio_dev = container_of(inode->i_cdev, 1740 1730 struct iio_dev, chrdev); 1731 + kfree(ib); 1741 1732 clear_bit(IIO_BUSY_BIT_POS, &indio_dev->flags); 1742 1733 iio_device_put(indio_dev); 1743 1734 ··· 1761 1748 1762 1749 static long iio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 1763 1750 { 1764 - struct iio_dev *indio_dev = filp->private_data; 1751 + struct iio_dev_buffer_pair *ib = filp->private_data; 1752 + struct iio_dev *indio_dev = ib->indio_dev; 1765 1753 struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 1766 1754 struct iio_ioctl_handler *h; 1767 1755 int ret = -ENODEV;