[PATCH v2] iio: adc: meson_saradc: Better handle BL30 not releaseing the hardware

Uwe Kleine-König u.kleine-koenig at pengutronix.de
Sun Feb 19 12:44:39 PST 2023


meson_sar_adc_lock() might return an error if BL30 doesn't release its
lock on the hardware. Just returning early from .remove() is wrong
however as this keeps the clocks and regulators on which is never
cleaned up later.

Given the BL30 not giving up its lock is a strong hint for broken
behaviour, and there is nothing we can do about that: Just clean up
ignoring the fact that we're not holding the lock.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig at pengutronix.de>
---
Hello,

changes since (implicit) v1:

 - Ignore failure to get the lock as suggested by Martin.
 - Adapt a caller for meson_sar_adc_hw_disable() returning void now
   (which used the return value)

 drivers/iio/adc/meson_saradc.c | 21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c
index 85b6826cc10c..18937a262af6 100644
--- a/drivers/iio/adc/meson_saradc.c
+++ b/drivers/iio/adc/meson_saradc.c
@@ -957,14 +957,18 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev)
 	return ret;
 }
 
-static int meson_sar_adc_hw_disable(struct iio_dev *indio_dev)
+static void meson_sar_adc_hw_disable(struct iio_dev *indio_dev)
 {
 	struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
 	int ret;
 
+	/*
+	 * If taking the lock fails we have to assume that BL30 is broken. The
+	 * best we can do then is to release the resources anyhow.
+	 */
 	ret = meson_sar_adc_lock(indio_dev);
 	if (ret)
-		return ret;
+		dev_err(indio_dev->dev.parent, "Failed to lock ADC (%pE)\n", ERR_PTR(ret));
 
 	clk_disable_unprepare(priv->adc_clk);
 
@@ -977,9 +981,8 @@ static int meson_sar_adc_hw_disable(struct iio_dev *indio_dev)
 
 	regulator_disable(priv->vref);
 
-	meson_sar_adc_unlock(indio_dev);
-
-	return 0;
+	if (!ret)
+		meson_sar_adc_unlock(indio_dev);
 }
 
 static irqreturn_t meson_sar_adc_irq(int irq, void *data)
@@ -1283,14 +1286,18 @@ static int meson_sar_adc_remove(struct platform_device *pdev)
 
 	iio_device_unregister(indio_dev);
 
-	return meson_sar_adc_hw_disable(indio_dev);
+	meson_sar_adc_hw_disable(indio_dev);
+
+	return 0;
 }
 
 static int meson_sar_adc_suspend(struct device *dev)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 
-	return meson_sar_adc_hw_disable(indio_dev);
+	meson_sar_adc_hw_disable(indio_dev);
+
+	return 0;
 }
 
 static int meson_sar_adc_resume(struct device *dev)

base-commit: 925cf0457d7e62ce08878ffb789189ac08ca8677
-- 
2.39.1




More information about the linux-arm-kernel mailing list