Add capability checks for operation with backends that do not necessarily
support full set of features, but are otherwise compatible with the device.
This ensures a fully functional device, but with limited capabilities.
Signed-off-by: Tomas Melin <tomas.melin@vaisala.com>
---
drivers/iio/adc/ad9467.c | 72 ++++++++++++++++++++++++++++++------------------
1 file changed, 45 insertions(+), 27 deletions(-)
diff --git a/drivers/iio/adc/ad9467.c b/drivers/iio/adc/ad9467.c
index 59c3fa3bcc9b0b8b36b78c3b54fd7977cae23496..eb57f72211430fc2c41baa9ed1a1e0ecf798ad57 100644
--- a/drivers/iio/adc/ad9467.c
+++ b/drivers/iio/adc/ad9467.c
@@ -912,8 +912,11 @@ static int __ad9467_update_clock(struct ad9467_state *st, long r_clk)
if (ret)
return ret;
- guard(mutex)(&st->lock);
- return ad9467_calibrate(st);
+ if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION)) {
+ guard(mutex)(&st->lock);
+ return ad9467_calibrate(st);
+ }
+ return 0;
}
static int ad9467_write_raw(struct iio_dev *indio_dev,
@@ -1119,12 +1122,15 @@ static ssize_t ad9467_chan_test_mode_read(struct file *file,
len = scnprintf(buf, sizeof(buf), "Running \"%s\" Test:\n\t",
ad9467_test_modes[chan->mode]);
- ret = iio_backend_debugfs_print_chan_status(st->back, chan->idx,
- buf + len,
- sizeof(buf) - len);
- if (ret < 0)
- return ret;
- len += ret;
+ if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION)) {
+ ret = iio_backend_debugfs_print_chan_status(st->back,
+ chan->idx,
+ buf + len,
+ sizeof(buf) - len);
+ if (ret < 0)
+ return ret;
+ len += ret;
+ }
} else if (chan->mode == AN877_ADC_TESTMODE_OFF) {
len = scnprintf(buf, sizeof(buf), "No test Running...\n");
} else {
@@ -1188,16 +1194,19 @@ static ssize_t ad9467_chan_test_mode_write(struct file *file,
return ret;
/* some patterns have a backend matching monitoring block */
- if (mode == AN877_ADC_TESTMODE_PN9_SEQ) {
- ret = ad9467_backend_testmode_on(st, chan->idx,
+ if (iio_backend_has_caps(st->back,
+ IIO_BACKEND_CAP_CALIBRATION)) {
+ if (mode == AN877_ADC_TESTMODE_PN9_SEQ) {
+ ret = ad9467_backend_testmode_on(st, chan->idx,
IIO_BACKEND_ADI_PRBS_9A);
- if (ret)
- return ret;
- } else if (mode == AN877_ADC_TESTMODE_PN23_SEQ) {
- ret = ad9467_backend_testmode_on(st, chan->idx,
+ if (ret)
+ return ret;
+ } else if (mode == AN877_ADC_TESTMODE_PN23_SEQ) {
+ ret = ad9467_backend_testmode_on(st, chan->idx,
IIO_BACKEND_ADI_PRBS_23A);
- if (ret)
- return ret;
+ if (ret)
+ return ret;
+ }
}
}
@@ -1263,8 +1272,10 @@ static void ad9467_debugfs_init(struct iio_dev *indio_dev)
if (!st->chan_test)
return;
- debugfs_create_file("calibration_table_dump", 0400, d, st,
- &ad9467_calib_table_fops);
+ if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION)) {
+ debugfs_create_file("calibration_table_dump", 0400, d, st,
+ &ad9467_calib_table_fops);
+ }
for (chan = 0; chan < st->info->num_channels; chan++) {
snprintf(attr_name, sizeof(attr_name), "in_voltage%u_test_mode",
@@ -1339,17 +1350,24 @@ static int ad9467_probe(struct spi_device *spi)
if (ret)
return ret;
- ret = devm_iio_backend_request_buffer(&spi->dev, st->back, indio_dev);
- if (ret)
- return ret;
+ if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_BUFFERING)) {
+ ret = devm_iio_backend_request_buffer(&spi->dev, st->back,
+ indio_dev);
+ if (ret)
+ return ret;
+ }
- ret = devm_iio_backend_enable(&spi->dev, st->back);
- if (ret)
- return ret;
+ if (!iio_backend_has_caps(st->back, IIO_BACKEND_CAP_ALWAYS_ON)) {
+ ret = devm_iio_backend_enable(&spi->dev, st->back);
+ if (ret)
+ return ret;
+ }
- ret = ad9467_calibrate(st);
- if (ret)
- return ret;
+ if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION)) {
+ ret = ad9467_calibrate(st);
+ if (ret)
+ return ret;
+ }
ret = devm_iio_device_register(&spi->dev, indio_dev);
if (ret)
--
2.47.3
On Wed, Jan 21, 2026 at 12:08:33PM +0000, Tomas Melin wrote:
> Add capability checks for operation with backends that do not necessarily
> support full set of features, but are otherwise compatible with the device.
> This ensures a fully functional device, but with limited capabilities.
...
> static int __ad9467_update_clock(struct ad9467_state *st, long r_clk)
> if (ret)
> return ret;
>
> - guard(mutex)(&st->lock);
I would leave this as is. Yes, practically we don't need to cover
iio_backend_has_caps() with mutex to access the data, but it just makes code
slightly more maintainable in my opinion. If anything appears here, it would
probably mean some kind of if (...) do_blablabla(...); pattern that will need
a mutex.
> - return ad9467_calibrate(st);
> + if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION)) {
> + guard(mutex)(&st->lock);
> + return ad9467_calibrate(st);
> + }
> + return 0;
> }
--
With Best Regards,
Andy Shevchenko
Hi,
On 21/01/2026 14:58, Andy Shevchenko wrote:
> On Wed, Jan 21, 2026 at 12:08:33PM +0000, Tomas Melin wrote:
>> Add capability checks for operation with backends that do not necessarily
>> support full set of features, but are otherwise compatible with the device.
>> This ensures a fully functional device, but with limited capabilities.
>
> ...
>
>> static int __ad9467_update_clock(struct ad9467_state *st, long r_clk)
>
>> if (ret)
>> return ret;
>>
>> - guard(mutex)(&st->lock);
>
> I would leave this as is. Yes, practically we don't need to cover
> iio_backend_has_caps() with mutex to access the data, but it just makes code
> slightly more maintainable in my opinion. If anything appears here, it would
> probably mean some kind of if (...) do_blablabla(...); pattern that will need
> a mutex.
I have no strong opinion on this. Current option was chosen as it seemed
cleaner in the sense that it a) takes the mutex only when needed and b)
check for caps does not require the mutex to be held. Based on this I
still suggest keeping as is but will change if you insist.
Thanks,
Tomas
>
>> - return ad9467_calibrate(st);
>> + if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION)) {
>> + guard(mutex)(&st->lock);
>> + return ad9467_calibrate(st);
>> + }
>> + return 0;
>> }
>
On Fri, Jan 23, 2026 at 09:10:20AM +0200, Tomas Melin wrote:
> On 21/01/2026 14:58, Andy Shevchenko wrote:
> > On Wed, Jan 21, 2026 at 12:08:33PM +0000, Tomas Melin wrote:
...
> >> static int __ad9467_update_clock(struct ad9467_state *st, long r_clk)
> >
> >> if (ret)
> >> return ret;
> >>
> >> - guard(mutex)(&st->lock);
> >
> > I would leave this as is. Yes, practically we don't need to cover
> > iio_backend_has_caps() with mutex to access the data, but it just makes code
> > slightly more maintainable in my opinion. If anything appears here, it would
> > probably mean some kind of if (...) do_blablabla(...); pattern that will need
> > a mutex.
>
> I have no strong opinion on this. Current option was chosen as it seemed
> cleaner in the sense that it a) takes the mutex only when needed and b)
> check for caps does not require the mutex to be held. Based on this I
> still suggest keeping as is but will change if you insist.
If you want your way, do not use guard()(). guard()() inside branches is
unintuitive and not the common way of doing it. Most likely you wanted
scoped_guard(). So, to me, guard() indented to more than 1 tab is suspicious
(I don't say it's forbidden or wrong).
> >> - return ad9467_calibrate(st);
> >> + if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION)) {
> >> + guard(mutex)(&st->lock);
> >> + return ad9467_calibrate(st);
> >> + }
> >> + return 0;
> >> }
--
With Best Regards,
Andy Shevchenko
© 2016 - 2026 Red Hat, Inc.