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

Configure Feed

Select the types of activity you want to include in your feed.

iio: sanity check available_scan_masks array

When IIO goes through the available scan masks in order to select the
best suiting one, it will just accept the first listed subset of channels
which meets the user's requirements. If driver lists a mask which is a
subset of some of the masks previously in the array of
avaliable_scan_masks, then the latter one will never be selected.

Add a warning if driver registers masks which can't be used due to the
available_scan_masks-array ordering.

Suggested-by: Jonathan Cameron <jic23@kernel.org>
Signed-off-by: Matti Vaittinen <mazziesaccount@gmail.com>
Link: https://lore.kernel.org/r/e55ef0b26a6d3b323bab24920c131c79a01ba08e.1697452986.git.mazziesaccount@gmail.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Matti Vaittinen and committed by
Jonathan Cameron
2718f154 e4cfeca8

+63
+63
drivers/iio/industrialio-core.c
··· 1896 1896 1897 1897 static const struct iio_buffer_setup_ops noop_ring_setup_ops; 1898 1898 1899 + static void iio_sanity_check_avail_scan_masks(struct iio_dev *indio_dev) 1900 + { 1901 + unsigned int num_masks, masklength, longs_per_mask; 1902 + const unsigned long *av_masks; 1903 + int i; 1904 + 1905 + av_masks = indio_dev->available_scan_masks; 1906 + masklength = indio_dev->masklength; 1907 + longs_per_mask = BITS_TO_LONGS(masklength); 1908 + 1909 + /* 1910 + * The code determining how many available_scan_masks is in the array 1911 + * will be assuming the end of masks when first long with all bits 1912 + * zeroed is encountered. This is incorrect for masks where mask 1913 + * consists of more than one long, and where some of the available masks 1914 + * has long worth of bits zeroed (but has subsequent bit(s) set). This 1915 + * is a safety measure against bug where array of masks is terminated by 1916 + * a single zero while mask width is greater than width of a long. 1917 + */ 1918 + if (longs_per_mask > 1) 1919 + dev_warn(indio_dev->dev.parent, 1920 + "multi long available scan masks not fully supported\n"); 1921 + 1922 + if (bitmap_empty(av_masks, masklength)) 1923 + dev_warn(indio_dev->dev.parent, "empty scan mask\n"); 1924 + 1925 + for (num_masks = 0; *av_masks; num_masks++) 1926 + av_masks += longs_per_mask; 1927 + 1928 + if (num_masks < 2) 1929 + return; 1930 + 1931 + av_masks = indio_dev->available_scan_masks; 1932 + 1933 + /* 1934 + * Go through all the masks from first to one before the last, and see 1935 + * that no mask found later from the available_scan_masks array is a 1936 + * subset of mask found earlier. If this happens, then the mask found 1937 + * later will never get used because scanning the array is stopped when 1938 + * the first suitable mask is found. Drivers should order the array of 1939 + * available masks in the order of preference (presumably the least 1940 + * costy to access masks first). 1941 + */ 1942 + for (i = 0; i < num_masks - 1; i++) { 1943 + const unsigned long *mask1; 1944 + int j; 1945 + 1946 + mask1 = av_masks + i * longs_per_mask; 1947 + for (j = i + 1; j < num_masks; j++) { 1948 + const unsigned long *mask2; 1949 + 1950 + mask2 = av_masks + j * longs_per_mask; 1951 + if (bitmap_subset(mask2, mask1, masklength)) 1952 + dev_warn(indio_dev->dev.parent, 1953 + "available_scan_mask %d subset of %d. Never used\n", 1954 + j, i); 1955 + } 1956 + } 1957 + } 1958 + 1899 1959 int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod) 1900 1960 { 1901 1961 struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); ··· 1993 1933 "Failed to create buffer sysfs interfaces\n"); 1994 1934 goto error_unreg_debugfs; 1995 1935 } 1936 + 1937 + if (indio_dev->available_scan_masks) 1938 + iio_sanity_check_avail_scan_masks(indio_dev); 1996 1939 1997 1940 ret = iio_device_register_sysfs(indio_dev); 1998 1941 if (ret) {