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

iio: core: register chardev only if needed

We only need a chardev if we need to support buffers and/or events.

With this change, a chardev will be created only if an IIO buffer is
attached OR an event_interface is configured.

Otherwise, no chardev will be created, and the IIO device will get
registered with the 'device_add()' call.

Quite a lot of IIO devices don't really need a chardev, so this is a minor
improvement to the IIO core, as the IIO device will take up (slightly)
fewer resources.

In order to not create a chardev, we mostly just need to not initialize the
indio_dev->dev.devt field. If that is un-initialized, cdev_device_add()
behaves like device_add().

This change has a small chance of breaking some userspace ABI, because it
removes un-needed chardevs. While these chardevs (that are being removed)
have always been unusable, it is likely that some scripts may check their
existence (for whatever logic).
And we also hope that before opening these chardevs, userspace would have
already checked for some pre-conditions to make sure that opening these
chardevs makes sense.
For the most part, there is also the hope that it would be easier to change
userspace code than revert this. But in the case that reverting this is
required, it should be easy enough to do it.

Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
Link: https://lore.kernel.org/r/20210215104043.91251-9-alexandru.ardelean@analog.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Alexandru Ardelean and committed by
Jonathan Cameron
8ebaa3ff c1271618

+18 -5
+18 -5
drivers/iio/industrialio-core.c
··· 1763 1763 .release = iio_chrdev_release, 1764 1764 }; 1765 1765 1766 + static const struct file_operations iio_event_fileops = { 1767 + .owner = THIS_MODULE, 1768 + .llseek = noop_llseek, 1769 + .unlocked_ioctl = iio_ioctl, 1770 + .compat_ioctl = compat_ptr_ioctl, 1771 + .open = iio_chrdev_open, 1772 + .release = iio_chrdev_release, 1773 + }; 1774 + 1766 1775 static int iio_check_unique_scan_index(struct iio_dev *indio_dev) 1767 1776 { 1768 1777 int i, j; ··· 1799 1790 1800 1791 int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod) 1801 1792 { 1793 + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); 1802 1794 const char *label; 1803 1795 int ret; 1804 1796 ··· 1818 1808 ret = iio_check_unique_scan_index(indio_dev); 1819 1809 if (ret < 0) 1820 1810 return ret; 1821 - 1822 - /* configure elements for the chrdev */ 1823 - indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id); 1824 1811 1825 1812 iio_device_register_debugfs(indio_dev); 1826 1813 ··· 1847 1840 indio_dev->setup_ops == NULL) 1848 1841 indio_dev->setup_ops = &noop_ring_setup_ops; 1849 1842 1850 - cdev_init(&indio_dev->chrdev, &iio_buffer_fileops); 1843 + if (indio_dev->buffer) 1844 + cdev_init(&indio_dev->chrdev, &iio_buffer_fileops); 1845 + else if (iio_dev_opaque->event_interface) 1846 + cdev_init(&indio_dev->chrdev, &iio_event_fileops); 1851 1847 1852 - indio_dev->chrdev.owner = this_mod; 1848 + if (indio_dev->buffer || iio_dev_opaque->event_interface) { 1849 + indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id); 1850 + indio_dev->chrdev.owner = this_mod; 1851 + } 1853 1852 1854 1853 ret = cdev_device_add(&indio_dev->chrdev, &indio_dev->dev); 1855 1854 if (ret < 0)