iio: addac: stx104: Fix race condition for stx104_write_raw()
authorWilliam Breathitt Gray <william.gray@linaro.org>
Thu, 6 Apr 2023 14:40:10 +0000 (10:40 -0400)
committerJonathan Cameron <Jonathan.Cameron@huawei.com>
Mon, 10 Apr 2023 11:26:33 +0000 (12:26 +0100)
The priv->chan_out_states array and actual DAC value can become
mismatched if stx104_write_raw() is called concurrently. Prevent such a
race condition by utilizing a mutex.

Fixes: 97a445dad37a ("iio: Add IIO support for the DAC on the Apex Embedded Systems STX104")
Signed-off-by: William Breathitt Gray <william.gray@linaro.org>
Link: https://lore.kernel.org/r/c95c9a77fcef36b2a052282146950f23bbc1ebdc.1680790580.git.william.gray@linaro.org
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
drivers/iio/addac/stx104.c

index e45b70aa5bb7a24159b0d8b99c8bb07d663c3137..4239aafe42fc8c8ee27c278c6b2cfc5279fc2c97 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
+#include <linux/mutex.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
 
@@ -69,10 +70,12 @@ struct stx104_reg {
 
 /**
  * struct stx104_iio - IIO device private data structure
+ * @lock: synchronization lock to prevent I/O race conditions
  * @chan_out_states:   channels' output states
  * @reg:               I/O address offset for the device registers
  */
 struct stx104_iio {
+       struct mutex lock;
        unsigned int chan_out_states[STX104_NUM_OUT_CHAN];
        struct stx104_reg __iomem *reg;
 };
@@ -178,9 +181,12 @@ static int stx104_write_raw(struct iio_dev *indio_dev,
                        if ((unsigned int)val > 65535)
                                return -EINVAL;
 
+                       mutex_lock(&priv->lock);
+
                        priv->chan_out_states[chan->channel] = val;
                        iowrite16(val, &priv->reg->dac[chan->channel]);
 
+                       mutex_unlock(&priv->lock);
                        return 0;
                }
                return -EINVAL;
@@ -351,6 +357,8 @@ static int stx104_probe(struct device *dev, unsigned int id)
 
        indio_dev->name = dev_name(dev);
 
+       mutex_init(&priv->lock);
+
        /* configure device for software trigger operation */
        iowrite8(0, &priv->reg->acr);