]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
iio: light: as73211: fix channel handling in only-color triggered buffer
authorJavier Carrasco <javier.carrasco.cruz@gmail.com>
Sat, 14 Dec 2024 22:55:50 +0000 (23:55 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 13 Mar 2025 11:47:10 +0000 (12:47 +0100)
commit ab09c6cfe01b317f515bcd944668697241a54b9d upstream.

The channel index is off by one unit if AS73211_SCAN_MASK_ALL is not
set (optimized path for color channel readings), and it must be shifted
instead of leaving an empty channel for the temperature when it is off.

Once the channel index is fixed, the uninitialized channel must be set
to zero to avoid pushing uninitialized data.

Add available_scan_masks for all channels and only-color channels to let
the IIO core demux and repack the enabled channels.

Cc: stable@vger.kernel.org
Fixes: 403e5586b52e ("iio: light: as73211: New driver")
Tested-by: Christian Eggers <ceggers@arri.de>
Signed-off-by: Javier Carrasco <javier.carrasco.cruz@gmail.com>
Link: https://patch.msgid.link/20241214-iio_memset_scan_holes-v4-1-260b395b8ed5@gmail.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/iio/light/as73211.c

index 7b32dfaee9b32cbad7dfae385ce05b85d6c6f9da..76b334dc5fbf359b9cb1b10b1d3f292242f15c57 100644 (file)
@@ -155,6 +155,12 @@ struct as73211_data {
        BIT(AS73211_SCAN_INDEX_TEMP) | \
        AS73211_SCAN_MASK_COLOR)
 
+static const unsigned long as73211_scan_masks[] = {
+       AS73211_SCAN_MASK_COLOR,
+       AS73211_SCAN_MASK_ALL,
+       0
+};
+
 static const struct iio_chan_spec as73211_channels[] = {
        {
                .type = IIO_TEMP,
@@ -603,9 +609,12 @@ static irqreturn_t as73211_trigger_handler(int irq __always_unused, void *p)
 
                /* AS73211 starts reading at address 2 */
                ret = i2c_master_recv(data->client,
-                               (char *)&scan.chan[1], 3 * sizeof(scan.chan[1]));
+                               (char *)&scan.chan[0], 3 * sizeof(scan.chan[0]));
                if (ret < 0)
                        goto done;
+
+               /* Avoid pushing uninitialized data */
+               scan.chan[3] = 0;
        }
 
        if (data_result) {
@@ -613,9 +622,15 @@ static irqreturn_t as73211_trigger_handler(int irq __always_unused, void *p)
                 * Saturate all channels (in case of overflows). Temperature channel
                 * is not affected by overflows.
                 */
-               scan.chan[1] = cpu_to_le16(U16_MAX);
-               scan.chan[2] = cpu_to_le16(U16_MAX);
-               scan.chan[3] = cpu_to_le16(U16_MAX);
+               if (*indio_dev->active_scan_mask == AS73211_SCAN_MASK_ALL) {
+                       scan.chan[1] = cpu_to_le16(U16_MAX);
+                       scan.chan[2] = cpu_to_le16(U16_MAX);
+                       scan.chan[3] = cpu_to_le16(U16_MAX);
+               } else {
+                       scan.chan[0] = cpu_to_le16(U16_MAX);
+                       scan.chan[1] = cpu_to_le16(U16_MAX);
+                       scan.chan[2] = cpu_to_le16(U16_MAX);
+               }
        }
 
        iio_push_to_buffers_with_timestamp(indio_dev, &scan, iio_get_time_ns(indio_dev));
@@ -685,6 +700,7 @@ static int as73211_probe(struct i2c_client *client)
        indio_dev->channels = as73211_channels;
        indio_dev->num_channels = ARRAY_SIZE(as73211_channels);
        indio_dev->modes = INDIO_DIRECT_MODE;
+       indio_dev->available_scan_masks = as73211_scan_masks;
 
        ret = i2c_smbus_read_byte_data(data->client, AS73211_REG_OSR);
        if (ret < 0)