Re: [PATCH v4 4/6] iio: dac: ad5504: introduce local lock to protect state and spi transfers
From: Andy Shevchenko
Date: Tue Aug 18 2026 - 02:17:16 EST
On Mon, Aug 17, 2026 at 05:11:13PM -0400, Taha Ed-Dafili wrote:
> The AD5504 driver currently lacks locking, exposing it to several
> multi-threading race conditions:
> 1. The shared DMA-safe SPI transfer buffers (st->data) can be
> corrupted if multiple threads trigger read_raw or write_raw
> simultaneously.
> 2. The ad5504_write_dac_powerdown() routine executes a sequence of
> back-to-back SPI writes (a CTRL register update followed by a
> mandatory NOOP). This entire sequence must be atomic.
> 3. Internal state variables like pwr_down_mask and pwr_down_mode
> can be read and modified concurrently.
>
> Introduce a mutex in the ad5504_state structure and initialize it via
> devm_mutex_init() in probe. Use the modern scoped guard(mutex) macro
> at the top-level public IIO callbacks (read_raw, write_raw, and the
> powerdown attributes) to safely serialize access to the device state
> and the SPI bus.
>
> In ad5504_read_raw() and ad5504_write_raw(), guard(mutex) is scoped to
> the IIO_CHAN_INFO_RAW case only, since IIO_CHAN_INFO_SCALE merely reads
> vref_mv, which is fixed at probe time and never modified afterward and
> therefore needs no serialization. Because guard(mutex) declares a
> cleanup-scoped variable, it cannot appear directly after a case label;
> wrap the case body in a compound statement (case IIO_CHAN_INFO_RAW: {
> ... }) to give it the block scope it requires.
Was this message written with a help with AI?
...
> + case IIO_CHAN_INFO_RAW: {
> + guard(mutex)(&st->lock);
Always use blank line(s) to separate the guard()() from the rest of the code.
> if (val >= (1 << chan->scan_type.realbits) || val < 0)
> return -EINVAL;
...
> struct ad5504_state *st = iio_priv(indio_dev);
>
> + guard(mutex)(&st->lock);
This is even stronger as we also require the blank line before return.
> return st->pwr_down_mode;
...
And so on...
--
With Best Regards,
Andy Shevchenko