From: David Lechner <dlechner@baylibre.com>
To: Archit Anant <architanant5@gmail.com>, jic23@kernel.org
Cc: lars@metafoo.de, Michael.Hennerich@analog.com,
nuno.sa@analog.com, andy@kernel.org, linux-iio@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2] iio: adc: ad799x: convert to fully managed resources
Date: Mon, 2 Mar 2026 09:06:17 -0600 [thread overview]
Message-ID: <9fe26547-0d1e-4701-8212-06d23cc1fbd2@baylibre.com> (raw)
In-Reply-To: <20260302052559.19494-1-architanant5@gmail.com>
On 3/1/26 11:25 PM, Archit Anant wrote:
> Refactor the driver to use device-managed allocations and actions,
> allowing for the complete removal of the ad799x_remove() function
> and simplifying the error paths in probe().
>
> Key changes:
> - Replace the dynamic rx_buf allocation with a fixed-size, DMA-safe
> buffer using IIO_DECLARE_DMA_BUFFER_WITH_TS() in the state struct.
> This avoids memory leaks during scan mode updates and removes the
> need for manual kfree().
I agree with Andy tht this first change should be split out to a
separate patch.
> - Cache the VCC and VREF voltages in the state structure during probe()
> to avoid querying the regulator API during fast-path read_raw() calls.
> - Use devm_add_action_or_reset() to register regulator_disable()
> callbacks for both VCC and VREF regulators.
And regulator stuff as another patch.
> - Convert iio_triggered_buffer_setup() and iio_device_register() to
> their devm_ variants, ensuring safe, reverse-order unwinding.
>
> Signed-off-by: Archit Anant <architanant5@gmail.com>
> ---
> Changes in v2:
> - Refactored entire resource management to eliminate remove() function
> based on feedback from David Lechner and Jonathan Cameron.
> - Cached voltages to prevent mixing manual regulator disables with
> devm-managed device unregistration.
>
> drivers/iio/adc/ad799x.c | 83 +++++++++++++++++++---------------------
> 1 file changed, 40 insertions(+), 43 deletions(-)
>
> diff --git a/drivers/iio/adc/ad799x.c b/drivers/iio/adc/ad799x.c
> index 108bb22162ef..4a3db6f0a8d8 100644
> --- a/drivers/iio/adc/ad799x.c
> +++ b/drivers/iio/adc/ad799x.c
> @@ -39,6 +39,7 @@
> #include <linux/iio/triggered_buffer.h>
>
> #define AD799X_CHANNEL_SHIFT 4
> +#define AD799X_MAX_CHANNELS 8
>
> /*
> * AD7991, AD7995 and AD7999 defines
> @@ -133,8 +134,12 @@ struct ad799x_state {
> unsigned int id;
> u16 config;
>
> - u8 *rx_buf;
> unsigned int transfer_size;
> +
> + int vcc_uv;
> + int vref_uv;
> +
> + IIO_DECLARE_DMA_BUFFER_WITH_TS(__be16, rx_buf, AD799X_MAX_CHANNELS);
See v1 discussion. IIO_DECLARE_DMA_BUFFER_WITH_TS() is not needed
after all since this is I2C. IIO_DECLARE_BUFFER_WITH_TS() can be
used instead.
> };
>
> static int ad799x_write_config(struct ad799x_state *st, u16 val)
> @@ -217,11 +222,11 @@ static irqreturn_t ad799x_trigger_handler(int irq, void *p)
> }
>
> b_sent = i2c_smbus_read_i2c_block_data(st->client,
> - cmd, st->transfer_size, st->rx_buf);
> + cmd, st->transfer_size, (u8 *)st->rx_buf);
> if (b_sent < 0)
> goto out;
>
> - iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf,
> + iio_push_to_buffers_with_timestamp(indio_dev, &st->rx_buf,
> iio_get_time_ns(indio_dev));
> out:
> iio_trigger_notify_done(indio_dev->trig);
> @@ -234,11 +239,6 @@ static int ad799x_update_scan_mode(struct iio_dev *indio_dev,
> {
> struct ad799x_state *st = iio_priv(indio_dev);
>
> - kfree(st->rx_buf);
> - st->rx_buf = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
> - if (!st->rx_buf)
> - return -ENOMEM;
> -
> st->transfer_size = bitmap_weight(scan_mask,
> iio_get_masklength(indio_dev)) * 2;
>
> @@ -307,9 +307,9 @@ static int ad799x_read_raw(struct iio_dev *indio_dev,
> return IIO_VAL_INT;
> case IIO_CHAN_INFO_SCALE:
> if (st->vref)
> - ret = regulator_get_voltage(st->vref);
> + ret = st->vref_uv;
> else
> - ret = regulator_get_voltage(st->reg);
> + ret = st->vcc_uv;
>
> if (ret < 0)
> return ret;
It should not be possible for ret < 0 now.
And we should be able to avoid assigning to ret and rather
assign directly to *val now.
> @@ -781,6 +781,13 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
> },
> };
>
> +static void ad799x_reg_disable(void *data)
> +{
> + struct regulator *reg = data;
> +
> + regulator_disable(reg);
> +}
> +
> static int ad799x_probe(struct i2c_client *client)
> {
> const struct i2c_device_id *id = i2c_client_get_device_id(client);
> @@ -813,6 +820,14 @@ static int ad799x_probe(struct i2c_client *client)
> ret = regulator_enable(st->reg);
> if (ret)
> return ret;
> + ret = devm_add_action_or_reset(&client->dev, ad799x_reg_disable, st->reg);
> + if (ret)
> + return ret;
> +
> + ret = regulator_get_voltage(st->reg);
> + if (ret < 0)
> + return ret;
> + st->vcc_uv = ret;
>
> /* check if an external reference is supplied */
> if (chip_info->has_vref) {
> @@ -820,7 +835,7 @@ static int ad799x_probe(struct i2c_client *client)
> ret = PTR_ERR_OR_ZERO(st->vref);
> if (ret) {
> if (ret != -ENODEV)
> - goto error_disable_reg;
> + return ret;
> st->vref = NULL;
> dev_info(&client->dev, "Using VCC reference voltage\n");
> }
> @@ -830,7 +845,14 @@ static int ad799x_probe(struct i2c_client *client)
> extra_config |= AD7991_REF_SEL;
> ret = regulator_enable(st->vref);
> if (ret)
> - goto error_disable_reg;
> + return ret;
> + ret = devm_add_action_or_reset(&client->dev, ad799x_reg_disable, st->vref);
> + if (ret)
> + return ret;
> + ret = regulator_get_voltage(st->vref);
> + if (ret < 0)
> + return ret;
> + st->vref_uv = ret;
> }
> }
>
> @@ -845,12 +867,12 @@ static int ad799x_probe(struct i2c_client *client)
>
> ret = ad799x_update_config(st, st->chip_config->default_config | extra_config);
> if (ret)
> - goto error_disable_vref;
> + return ret;
>
> - ret = iio_triggered_buffer_setup(indio_dev, NULL,
> + ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev, NULL,
> &ad799x_trigger_handler, NULL);
> if (ret)
> - goto error_disable_vref;
> + return ret;
>
> if (client->irq > 0) {
> ret = devm_request_threaded_irq(&client->dev,
> @@ -862,40 +884,16 @@ static int ad799x_probe(struct i2c_client *client)
> client->name,
> indio_dev);
> if (ret)
> - goto error_cleanup_ring;
> + return ret;
> }
>
> mutex_init(&st->lock);
>
> - ret = iio_device_register(indio_dev);
> + ret = devm_iio_device_register(&client->dev, indio_dev);
We can just return directly here now.
> if (ret)
> - goto error_cleanup_ring;
> + return ret;
>
> return 0;
> -
> -error_cleanup_ring:
> - iio_triggered_buffer_cleanup(indio_dev);
> -error_disable_vref:
> - if (st->vref)
> - regulator_disable(st->vref);
> -error_disable_reg:
> - regulator_disable(st->reg);
> -
> - return ret;
> -}
> -
> -static void ad799x_remove(struct i2c_client *client)
> -{
> - struct iio_dev *indio_dev = i2c_get_clientdata(client);
> - struct ad799x_state *st = iio_priv(indio_dev);
> -
> - iio_device_unregister(indio_dev);
> -
> - iio_triggered_buffer_cleanup(indio_dev);
> - if (st->vref)
> - regulator_disable(st->vref);
> - regulator_disable(st->reg);
> - kfree(st->rx_buf);
> }
>
> static int ad799x_suspend(struct device *dev)
> @@ -965,7 +963,6 @@ static struct i2c_driver ad799x_driver = {
> .pm = pm_sleep_ptr(&ad799x_pm_ops),
> },
> .probe = ad799x_probe,
> - .remove = ad799x_remove,
> .id_table = ad799x_id,
> };
> module_i2c_driver(ad799x_driver);
prev parent reply other threads:[~2026-03-02 15:06 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-02 5:25 [PATCH v2] iio: adc: ad799x: convert to fully managed resources Archit Anant
2026-03-02 8:09 ` Andy Shevchenko
2026-03-02 15:06 ` David Lechner [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=9fe26547-0d1e-4701-8212-06d23cc1fbd2@baylibre.com \
--to=dlechner@baylibre.com \
--cc=Michael.Hennerich@analog.com \
--cc=andy@kernel.org \
--cc=architanant5@gmail.com \
--cc=jic23@kernel.org \
--cc=lars@metafoo.de \
--cc=linux-iio@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=nuno.sa@analog.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.