]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
iio: adc: ad4695: Fix call ordering in offload buffer postenable
authorRadu Sabau <radu.sabau@analog.com>
Wed, 8 Apr 2026 10:32:13 +0000 (13:32 +0300)
committerJonathan Cameron <jic23@kernel.org>
Tue, 28 Apr 2026 15:36:09 +0000 (16:36 +0100)
ad4695_enter_advanced_sequencer_mode() was called after
spi_offload_trigger_enable(). That is wrong because
ad4695_enter_advanced_sequencer_mode() issues regular SPI transfers to
put the ADC into advanced sequencer mode, and not all SPI offload capable
controllers support regular SPI transfers while offloading is enabled.

Fix this by calling ad4695_enter_advanced_sequencer_mode() before
spi_offload_trigger_enable(), so the ADC is fully configured before the
first CNV pulse can occur. This is consistent with the same constraint
that already applies to the BUSY_GP_EN write above it.

Update the error unwind labels accordingly: add err_exit_conversion_mode
so that a failure of spi_offload_trigger_enable() correctly exits
conversion mode before clearing BUSY_GP_EN.

Fixes: f09f140e3ea8 ("iio: adc: ad4695: Add support for SPI offload")
Reviewed-by: Nuno Sá <nuno.sa@analog.com>
Reviewed-by: David Lechner <dlechner@baylibre.com>
Signed-off-by: Radu Sabau <radu.sabau@analog.com>
Cc: Stable@vger.kernel.org
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
drivers/iio/adc/ad4695.c

index cda419638d9a88debb3501d05a513b17a4ecde95..53642de7330dc5ca87286abaae977f3536189af4 100644 (file)
@@ -876,14 +876,14 @@ static int ad4695_offload_buffer_postenable(struct iio_dev *indio_dev)
        if (ret)
                goto err_unoptimize_message;
 
-       ret = spi_offload_trigger_enable(st->offload, st->offload_trigger,
-                                        &config);
+       ret = ad4695_enter_advanced_sequencer_mode(st, num_slots);
        if (ret)
                goto err_disable_busy_output;
 
-       ret = ad4695_enter_advanced_sequencer_mode(st, num_slots);
+       ret = spi_offload_trigger_enable(st->offload, st->offload_trigger,
+                                        &config);
        if (ret)
-               goto err_offload_trigger_disable;
+               goto err_exit_conversion_mode;
 
        mutex_lock(&st->cnv_pwm_lock);
        pwm_get_state(st->cnv_pwm, &state);
@@ -895,23 +895,16 @@ static int ad4695_offload_buffer_postenable(struct iio_dev *indio_dev)
        ret = pwm_apply_might_sleep(st->cnv_pwm, &state);
        mutex_unlock(&st->cnv_pwm_lock);
        if (ret)
-               goto err_offload_exit_conversion_mode;
+               goto err_offload_trigger_disable;
 
        return 0;
 
-err_offload_exit_conversion_mode:
-       /*
-        * We have to unwind in a different order to avoid triggering offload.
-        * ad4695_exit_conversion_mode() triggers a conversion, so it has to be
-        * done after spi_offload_trigger_disable().
-        */
-       spi_offload_trigger_disable(st->offload, st->offload_trigger);
-       ad4695_exit_conversion_mode(st);
-       goto err_disable_busy_output;
-
 err_offload_trigger_disable:
        spi_offload_trigger_disable(st->offload, st->offload_trigger);
 
+err_exit_conversion_mode:
+       ad4695_exit_conversion_mode(st);
+
 err_disable_busy_output:
        regmap_clear_bits(st->regmap, AD4695_REG_GP_MODE,
                          AD4695_REG_GP_MODE_BUSY_GP_EN);