* [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
* 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
* [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
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®