public inbox for linux-iio@vger.kernel.org
 help / color / mirror / Atom feed
From: Archit Anant <architanant5@gmail.com>
To: jic23@kernel.org, dlechner@baylibre.com
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,
	Archit Anant <architanant5@gmail.com>,
	Andy Shevchenko <andriy.shevchenko@intel.com>
Subject: [PATCH v7 5/5] iio: adc: ad799x: convert to fully managed resources and drop remove()
Date: Fri,  3 Apr 2026 13:36:14 +0530	[thread overview]
Message-ID: <20260403080614.14213-6-architanant5@gmail.com> (raw)
In-Reply-To: <20260403080614.14213-1-architanant5@gmail.com>

Convert the driver's remaining manual resource management to use the
devm_ infrastructure, allowing for the complete removal of the
ad799x_remove() function and the simplification of the probe error paths.

Specifically:
- Initialize the mutex using devm_mutex_init() and move it to the top
  of probe() (before IRQ registration) to prevent a race condition where
  an interrupt could attempt to take an uninitialized lock.
- Use devm_add_action_or_reset() to ensure that the VCC and VREF
  regulators are disabled safely and in the correct order during driver
  teardown or probe failure.
- Refactor the optional VREF error handling path for better readability.
- Convert iio_triggered_buffer_setup() and iio_device_register() to
  their devm_ variants.

Because all resources are now managed by the devm core, the unwinding
order is guaranteed to follow the reverse order of allocation. All manual
error handling goto labels in ad799x_probe() have been removed.

Suggested-by: Jonathan Cameron <jic23@kernel.org>
Suggested-by: David Lechner <dlechner@baylibre.com>
Suggested-by: Andy Shevchenko <andriy.shevchenko@intel.com>
Signed-off-by: Archit Anant <architanant5@gmail.com>
---
 drivers/iio/adc/ad799x.c | 69 ++++++++++++++++------------------------
 1 file changed, 28 insertions(+), 41 deletions(-)

diff --git a/drivers/iio/adc/ad799x.c b/drivers/iio/adc/ad799x.c
index e37bb64edd2b..9170109d64ef 100644
--- a/drivers/iio/adc/ad799x.c
+++ b/drivers/iio/adc/ad799x.c
@@ -775,6 +775,11 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
 	},
 };
 
+static void ad799x_reg_disable(void *reg)
+{
+	regulator_disable(reg);
+}
+
 static int ad799x_probe(struct i2c_client *client)
 {
 	struct device *dev = &client->dev;
@@ -793,6 +798,9 @@ static int ad799x_probe(struct i2c_client *client)
 	st = iio_priv(indio_dev);
 	/* this is only used for device removal purposes */
 	i2c_set_clientdata(client, indio_dev);
+	ret = devm_mutex_init(dev, &st->lock);
+	if (ret)
+		return ret;
 
 	st->id = id->driver_data;
 	if (client->irq > 0 && chip_info->irq_config.info)
@@ -809,15 +817,19 @@ static int ad799x_probe(struct i2c_client *client)
 	if (ret)
 		return ret;
 
+	ret = devm_add_action_or_reset(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(dev, "vref");
 		ret = PTR_ERR_OR_ZERO(st->vref);
-		if (ret) {
-			if (ret != -ENODEV)
-				goto error_disable_reg;
+		if (ret == -ENODEV) {
 			st->vref = NULL;
 			dev_info(dev, "Using VCC reference voltage\n");
+		} else if (ret) {
+			return ret;
 		}
 
 		if (st->vref) {
@@ -825,10 +837,15 @@ 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(dev, ad799x_reg_disable, st->vref);
+			if (ret)
+				return ret;
+
 			ret = regulator_get_voltage(st->vref);
 			if (ret < 0)
-				goto error_disable_vref;
+				return ret;
 			st->vref_uV = ret;
 		}
 	}
@@ -836,7 +853,7 @@ static int ad799x_probe(struct i2c_client *client)
 	if (!st->vref) {
 		ret = regulator_get_voltage(st->reg);
 		if (ret < 0)
-			goto error_disable_reg;
+			return ret;
 		st->vref_uV = ret;
 	}
 
@@ -851,12 +868,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(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(dev,
@@ -868,39 +885,10 @@ 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);
-	if (ret)
-		goto error_cleanup_ring;
-
-	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);
+	return devm_iio_device_register(dev, indio_dev);
 }
 
 static int ad799x_suspend(struct device *dev)
@@ -970,7 +958,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);
-- 
2.39.5


  parent reply	other threads:[~2026-04-03  8:06 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-03  8:06 [PATCH v7 0/5] iio: adc: ad799x: modernize resource management Archit Anant
2026-04-03  8:06 ` [PATCH v7 1/5] iio: adc: ad799x: sort headers alphabetically Archit Anant
2026-04-03  8:06 ` [PATCH v7 2/5] iio: adc: ad799x: use local device pointer in probe Archit Anant
2026-04-03  8:06 ` [PATCH v7 3/5] iio: adc: ad799x: use a static buffer for scan data Archit Anant
2026-04-03  8:06 ` [PATCH v7 4/5] iio: adc: ad799x: cache regulator voltages during probe Archit Anant
2026-04-04 16:04   ` David Lechner
2026-04-03  8:06 ` Archit Anant [this message]
2026-04-04 16:09   ` [PATCH v7 5/5] iio: adc: ad799x: convert to fully managed resources and drop remove() David Lechner
2026-04-04 16:10 ` [PATCH v7 0/5] iio: adc: ad799x: modernize resource management David Lechner

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=20260403080614.14213-6-architanant5@gmail.com \
    --to=architanant5@gmail.com \
    --cc=Michael.Hennerich@analog.com \
    --cc=andriy.shevchenko@intel.com \
    --cc=andy@kernel.org \
    --cc=dlechner@baylibre.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox