Convert the manual regulator_disable() handling to use
devm_add_action_or_reset(). This guarantees that the regulators are
disabled in the correct reverse order of allocation during device
teardown or probe failure.
This removes the need to manually disable the regulators in the
remove() function.
Suggested-by: David Lechner <dlechner@baylibre.com>
Signed-off-by: Archit Anant <architanant5@gmail.com>
---
drivers/iio/adc/ad799x.c | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/drivers/iio/adc/ad799x.c b/drivers/iio/adc/ad799x.c
index 35e0589428d0..1a96b5417ecf 100644
--- a/drivers/iio/adc/ad799x.c
+++ b/drivers/iio/adc/ad799x.c
@@ -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);
@@ -818,6 +825,10 @@ static int ad799x_probe(struct i2c_client *client)
goto error_disable_reg;
st->vcc_uv = ret;
+ ret = devm_add_action_or_reset(&client->dev, ad799x_reg_disable, st->reg);
+ if (ret)
+ return ret;
+
/* check if an external reference is supplied */
if (chip_info->has_vref) {
st->vref = devm_regulator_get_optional(&client->dev, "vref");
@@ -840,6 +851,11 @@ static int ad799x_probe(struct i2c_client *client)
if (ret < 0)
goto error_disable_vref;
st->vref_uv = ret;
+
+ ret = devm_add_action_or_reset(&client->dev, ad799x_reg_disable,
+ st->vref);
+ if (ret)
+ goto error_disable_reg;
}
}
@@ -901,9 +917,6 @@ static void ad799x_remove(struct i2c_client *client)
iio_device_unregister(indio_dev);
iio_triggered_buffer_cleanup(indio_dev);
- if (st->vref)
- regulator_disable(st->vref);
- regulator_disable(st->reg);
}
static int ad799x_suspend(struct device *dev)
--
2.39.5
On 3/2/26 7:06 AM, Archit Anant wrote:
> Convert the manual regulator_disable() handling to use
> devm_add_action_or_reset(). This guarantees that the regulators are
> disabled in the correct reverse order of allocation during device
> teardown or probe failure.
>
> This removes the need to manually disable the regulators in the
> remove() function.
>
> Suggested-by: David Lechner <dlechner@baylibre.com>
> Signed-off-by: Archit Anant <architanant5@gmail.com>
> ---
> drivers/iio/adc/ad799x.c | 19 ++++++++++++++++---
> 1 file changed, 16 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/iio/adc/ad799x.c b/drivers/iio/adc/ad799x.c
> index 35e0589428d0..1a96b5417ecf 100644
> --- a/drivers/iio/adc/ad799x.c
> +++ b/drivers/iio/adc/ad799x.c
> @@ -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);
> @@ -818,6 +825,10 @@ static int ad799x_probe(struct i2c_client *client)
> goto error_disable_reg;
> st->vcc_uv = ret;
>
> + ret = devm_add_action_or_reset(&client->dev, ad799x_reg_disable, st->reg);
> + if (ret)
> + return ret;
> +
> /* check if an external reference is supplied */
> if (chip_info->has_vref) {
> st->vref = devm_regulator_get_optional(&client->dev, "vref");
> @@ -840,6 +851,11 @@ static int ad799x_probe(struct i2c_client *client)
> if (ret < 0)
> goto error_disable_vref;
> st->vref_uv = ret;
> +
> + ret = devm_add_action_or_reset(&client->dev, ad799x_reg_disable,
> + st->vref);
> + if (ret)
> + goto error_disable_reg;
This goto and others should be removed in this patch. devm handles it now.
> }
> }
>
> @@ -901,9 +917,6 @@ static void ad799x_remove(struct i2c_client *client)
> iio_device_unregister(indio_dev);
>
> iio_triggered_buffer_cleanup(indio_dev);
> - if (st->vref)
> - regulator_disable(st->vref);
> - regulator_disable(st->reg);
> }
>
> static int ad799x_suspend(struct device *dev)
On Mon, Mar 02, 2026 at 06:36:31PM +0530, Archit Anant wrote:
> Convert the manual regulator_disable() handling to use
> devm_add_action_or_reset(). This guarantees that the regulators are
> disabled in the correct reverse order of allocation during device
> teardown or probe failure.
>
> This removes the need to manually disable the regulators in the
> remove() function.
...
> +static void ad799x_reg_disable(void *data)
> +{
> + struct regulator *reg = data;
Unneeded.
> + regulator_disable(reg);
> +}
static void ad799x_reg_disable(void *reg)
{
regulator_disable(reg);
}
...
> static int ad799x_probe(struct i2c_client *client)
With
struct device *dev = &client->dev;
it will look better.
...
> + ret = devm_add_action_or_reset(&client->dev, ad799x_reg_disable, st->reg);
ret = devm_add_action_or_reset(dev, ad799x_reg_disable, st->reg);
> + if (ret)
> + return ret;
...
> + ret = devm_add_action_or_reset(&client->dev, ad799x_reg_disable,
> + st->vref);
ret = devm_add_action_or_reset(dev, ad799x_reg_disable, st->vref);
> + if (ret)
> + goto error_disable_reg;
--
With Best Regards,
Andy Shevchenko
© 2016 - 2026 Red Hat, Inc.