* [PATCH v5 0/2] staging: iio: adc: ad7816: Fix SPI read race condition and DMA safety
@ 2026-09-11 11:04 Abdelnasser Hussein
2026-09-11 11:04 ` [PATCH v5 1/2] staging: iio: adc: ad7816: Serialize SPI read operations Abdelnasser Hussein
2026-09-11 11:04 ` [PATCH v5 2/2] staging: iio: adc: ad7816: Use DMA-safe buffer for SPI read Abdelnasser Hussein
0 siblings, 2 replies; 5+ messages in thread
From: Abdelnasser Hussein @ 2026-09-11 11:04 UTC (permalink / raw)
To: jic23, gregkh, nuno.sa, Michael.Hennerich
Cc: dlechner, andy, linux, linux-iio, linux-staging, linux-kernel,
joshua.crofts1, Abdelnasser Hussein
This series addresses two separate issues in the ad7816 driver:
1. A race condition during SPI reads where multiple threads could
disrupt the GPIO state.
2. A DMA safety issue caused by using a stack-allocated buffer for
SPI transfers.
Changes in v5:
- Split the changes into two separate patches for bisectability, as
requested by reviewers.
- Patch 1 focuses only on serializing the SPI read operations using
guard(mutex) and devm_mutex_init().
- Patch 2 focuses only on replacing the stack buffer with a dedicated
rx_buf aligned with IIO_DMA_MINALIGN.
- Updated commit messages to better describe the architectural issues.
Abdelnasser Hussein (2):
staging: iio: adc: ad7816: Serialize SPI read operations
staging: iio: adc: ad7816: Use DMA-safe buffer for SPI read
drivers/staging/iio/adc/ad7816.c | 25 +++++++++++++++++--------
1 file changed, 17 insertions(+), 8 deletions(-)
--
2.54.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v5 1/2] staging: iio: adc: ad7816: Serialize SPI read operations
2026-09-11 11:04 [PATCH v5 0/2] staging: iio: adc: ad7816: Fix SPI read race condition and DMA safety Abdelnasser Hussein
@ 2026-09-11 11:04 ` Abdelnasser Hussein
2026-09-11 11:18 ` Joshua Crofts
2026-09-11 11:04 ` [PATCH v5 2/2] staging: iio: adc: ad7816: Use DMA-safe buffer for SPI read Abdelnasser Hussein
1 sibling, 1 reply; 5+ messages in thread
From: Abdelnasser Hussein @ 2026-09-11 11:04 UTC (permalink / raw)
To: jic23, gregkh, nuno.sa, Michael.Hennerich
Cc: dlechner, andy, linux, linux-iio, linux-staging, linux-kernel,
joshua.crofts1, Abdelnasser Hussein
The ad7816_spi_read() function performs a sequence of GPIO state
changes followed by an SPI transfer. If multiple read operations
occur simultaneously, the GPIO state could be changed by one thread
while another is in the middle of a read. This leads to a race
condition where the sensor state is disrupted, resulting in corrupted
data being read.
Introduce a mutex to serialize the read sequence, ensuring that the
GPIO toggling and the SPI transfer are treated as a single atomic
operation.
Signed-off-by: Abdelnasser Hussein <abdelnasserhussein11@gmail.com>
---
drivers/staging/iio/adc/ad7816.c | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/drivers/staging/iio/adc/ad7816.c b/drivers/staging/iio/adc/ad7816.c
index 0e32a2295990..d0355763aa8f 100644
--- a/drivers/staging/iio/adc/ad7816.c
+++ b/drivers/staging/iio/adc/ad7816.c
@@ -5,15 +5,17 @@
* Copyright 2010 Analog Devices Inc.
*/
-#include <linux/interrupt.h>
-#include <linux/gpio/consumer.h>
+#include <linux/cleanup.h>
#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/interrupt.h>
#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/sysfs.h>
#include <linux/list.h>
-#include <linux/spi/spi.h>
#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/sysfs.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@@ -50,6 +52,7 @@ struct ad7816_chip_info {
u8 oti_data[AD7816_CS_MAX + 1];
u8 channel_id; /* 0 always be temperature */
u8 mode;
+ struct mutex lock; /* protect device state during SPI transfers */
};
enum ad7816_type {
@@ -67,6 +70,8 @@ static int ad7816_spi_read(struct ad7816_chip_info *chip, u16 *data)
int ret;
__be16 buf;
+ guard(mutex)(&chip->lock);
+
gpiod_set_value(chip->rdwr_pin, 1);
gpiod_set_value(chip->rdwr_pin, 0);
ret = spi_write(spi_dev, &chip->channel_id, sizeof(chip->channel_id));
@@ -91,7 +96,7 @@ static int ad7816_spi_read(struct ad7816_chip_info *chip, u16 *data)
gpiod_set_value(chip->rdwr_pin, 0);
gpiod_set_value(chip->rdwr_pin, 1);
- ret = spi_read(spi_dev, &buf, sizeof(*data));
+ ret = spi_read(spi_dev, &buf, sizeof(buf));
if (ret < 0) {
dev_err(&spi_dev->dev, "SPI data read error\n");
return ret;
@@ -360,6 +365,10 @@ static int ad7816_probe(struct spi_device *spi_dev)
return -ENOMEM;
chip = iio_priv(indio_dev);
+ ret = devm_mutex_init(&spi_dev->dev, &chip->lock);
+ if (ret)
+ return ret;
+
chip->spi_dev = spi_dev;
for (i = 0; i <= AD7816_CS_MAX; i++)
chip->oti_data[i] = 203;
--
2.54.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v5 2/2] staging: iio: adc: ad7816: Use DMA-safe buffer for SPI read
2026-09-11 11:04 [PATCH v5 0/2] staging: iio: adc: ad7816: Fix SPI read race condition and DMA safety Abdelnasser Hussein
2026-09-11 11:04 ` [PATCH v5 1/2] staging: iio: adc: ad7816: Serialize SPI read operations Abdelnasser Hussein
@ 2026-09-11 11:04 ` Abdelnasser Hussein
1 sibling, 0 replies; 5+ messages in thread
From: Abdelnasser Hussein @ 2026-09-11 11:04 UTC (permalink / raw)
To: jic23, gregkh, nuno.sa, Michael.Hennerich
Cc: dlechner, andy, linux, linux-iio, linux-staging, linux-kernel,
joshua.crofts1, Abdelnasser Hussein
Stack buffers are unsafe for DMA with VMAP_STACK enabled because
they are not physically contiguous and can share cache lines. This
causes data corruption.
Fix this by using a dedicated rx_buf aligned with IIO_DMA_MINALIGN
in the device state structure to ensure cache coherency.
Fixes: 7024425db64a ("staging: iio: adc: new driver for AD7816 devices")
Signed-off-by: Abdelnasser Hussein <abdelnasserhussein11@gmail.com>
---
drivers/staging/iio/adc/ad7816.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/staging/iio/adc/ad7816.c b/drivers/staging/iio/adc/ad7816.c
index d0355763aa8f..19da164945c7 100644
--- a/drivers/staging/iio/adc/ad7816.c
+++ b/drivers/staging/iio/adc/ad7816.c
@@ -53,6 +53,7 @@ struct ad7816_chip_info {
u8 channel_id; /* 0 always be temperature */
u8 mode;
struct mutex lock; /* protect device state during SPI transfers */
+ __be16 rx_buf __aligned(IIO_DMA_MINALIGN);
};
enum ad7816_type {
@@ -68,7 +69,6 @@ static int ad7816_spi_read(struct ad7816_chip_info *chip, u16 *data)
{
struct spi_device *spi_dev = chip->spi_dev;
int ret;
- __be16 buf;
guard(mutex)(&chip->lock);
@@ -96,13 +96,13 @@ static int ad7816_spi_read(struct ad7816_chip_info *chip, u16 *data)
gpiod_set_value(chip->rdwr_pin, 0);
gpiod_set_value(chip->rdwr_pin, 1);
- ret = spi_read(spi_dev, &buf, sizeof(buf));
+ ret = spi_read(spi_dev, &chip->rx_buf, sizeof(chip->rx_buf));
if (ret < 0) {
dev_err(&spi_dev->dev, "SPI data read error\n");
return ret;
}
- *data = be16_to_cpu(buf);
+ *data = be16_to_cpu(chip->rx_buf);
return ret;
}
--
2.54.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v5 1/2] staging: iio: adc: ad7816: Serialize SPI read operations
2026-09-11 11:04 ` [PATCH v5 1/2] staging: iio: adc: ad7816: Serialize SPI read operations Abdelnasser Hussein
@ 2026-09-11 11:18 ` Joshua Crofts
2026-09-11 13:21 ` nasser
0 siblings, 1 reply; 5+ messages in thread
From: Joshua Crofts @ 2026-09-11 11:18 UTC (permalink / raw)
To: Abdelnasser Hussein
Cc: jic23, gregkh, nuno.sa, Michael.Hennerich, dlechner, andy, linux,
linux-iio, linux-staging, linux-kernel
On Fri, 11 Sep 2026 14:04:55 +0300
Abdelnasser Hussein <abdelnasserhussein11@gmail.com> wrote:
...
> -#include <linux/interrupt.h>
> -#include <linux/gpio/consumer.h>
> +#include <linux/cleanup.h>
> #include <linux/device.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/interrupt.h>
> #include <linux/kernel.h>
> -#include <linux/slab.h>
> -#include <linux/sysfs.h>
> #include <linux/list.h>
> -#include <linux/spi/spi.h>
> #include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/slab.h>
> +#include <linux/spi/spi.h>
> +#include <linux/sysfs.h>
>
Ideally the addition of new headers should go in a separate precursor patch.
(excluding cleanup.h and mutex.h, you'd add those in this patch).
> #include <linux/iio/iio.h>
> #include <linux/iio/sysfs.h>
> @@ -50,6 +52,7 @@ struct ad7816_chip_info {
> u8 oti_data[AD7816_CS_MAX + 1];
> u8 channel_id; /* 0 always be temperature */
> u8 mode;
> + struct mutex lock; /* protect device state during SPI transfers */
> };
>
> enum ad7816_type {
> @@ -67,6 +70,8 @@ static int ad7816_spi_read(struct ad7816_chip_info *chip, u16 *data)
> int ret;
> __be16 buf;
>
> + guard(mutex)(&chip->lock);
> +
> gpiod_set_value(chip->rdwr_pin, 1);
> gpiod_set_value(chip->rdwr_pin, 0);
> ret = spi_write(spi_dev, &chip->channel_id, sizeof(chip->channel_id));
> @@ -91,7 +96,7 @@ static int ad7816_spi_read(struct ad7816_chip_info *chip, u16 *data)
>
> gpiod_set_value(chip->rdwr_pin, 0);
> gpiod_set_value(chip->rdwr_pin, 1);
> - ret = spi_read(spi_dev, &buf, sizeof(*data));
> + ret = spi_read(spi_dev, &buf, sizeof(buf));
No, you're mixing changes again.
--
Kind regards,
Joshua Crofts
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v5 1/2] staging: iio: adc: ad7816: Serialize SPI read operations
2026-09-11 11:18 ` Joshua Crofts
@ 2026-09-11 13:21 ` nasser
0 siblings, 0 replies; 5+ messages in thread
From: nasser @ 2026-09-11 13:21 UTC (permalink / raw)
To: Joshua Crofts
Cc: jic23, gregkh, nuno.sa, Michael.Hennerich, dlechner, andy, linux,
linux-iio, linux-staging, linux-kernel
Hi Joshua,
Thank you very much for your continuous guidance and patience with my
patches. I truly appreciate your feedback.
You are completely right. I mistakenly thought I could clean up and
sort the headers alongside the mutex addition without needing to
isolate it in a separate patch. I also apologize for letting the
`sizeof(buf)` change slip into the mutex patch.
I will prepare a v6 series shortly where I will:
1. Add a separate precursor patch solely for sorting and cleaning up
the headers.
2. Keep the mutex patch strictly focused on serializing the read
operations (adding only <linux/mutex.h> and <linux/cleanup.h>).
3. Move the `sizeof()` argument change to the DMA buffer patch where
it logically belongs.
Thanks again for pointing these out.
Best regards,
Abdelnasser
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-09-11 13:21 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-11 11:04 [PATCH v5 0/2] staging: iio: adc: ad7816: Fix SPI read race condition and DMA safety Abdelnasser Hussein
2026-09-11 11:04 ` [PATCH v5 1/2] staging: iio: adc: ad7816: Serialize SPI read operations Abdelnasser Hussein
2026-09-11 11:18 ` Joshua Crofts
2026-09-11 13:21 ` nasser
2026-09-11 11:04 ` [PATCH v5 2/2] staging: iio: adc: ad7816: Use DMA-safe buffer for SPI read Abdelnasser Hussein
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®