diff mbox series

iio: adc: meson_saradc: Better handle BL30 not releaseing the hardware

Message ID 20230216140725.1181867-1-u.kleine-koenig@pengutronix.de (mailing list archive)
State Superseded
Headers show
Series iio: adc: meson_saradc: Better handle BL30 not releaseing the hardware | expand

Commit Message

Uwe Kleine-König Feb. 16, 2023, 2:07 p.m. UTC
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.

So only skip hardware accesses with an error message if
meson_sar_adc_lock() fails, but disable clocks and regulator and return
zero to suppress another error message by the driver core.

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

maybe someone with more hardware specific knowledge can improve the
procedure here. Maybe some HW access is fine even without the lock to
quiescent it, or maybe the lock can be dropped completely? Or the
ordering can be changed to reduce the number of if blocks.

Best regards
Uwe

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


base-commit: 1b929c02afd37871d5afb9d498426f83432e71c2

Comments

Martin Blumenstingl Feb. 18, 2023, 3:50 p.m. UTC | #1
Hi Uwe,

On Thu, Feb 16, 2023 at 3:07 PM Uwe Kleine-König
<u.kleine-koenig@pengutronix.de> wrote:
>
> 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.
>
> So only skip hardware accesses with an error message if
> meson_sar_adc_lock() fails, but disable clocks and regulator and return
> zero to suppress another error message by the driver core.
The clocks and regulators are shared with the BL30 firmware.
In practice I have not seen meson_sar_adc_lock() fail yet.

I think it's enough to print an error message if locking fails, then
continue as if nothing happened. Unlocking obviously has to be skipped
as well in this case.
There's not much we can do to recover from this and I consider the
BL30 firmware to be hanging (or broken) if it doesn't release the
lock.


Best regards,
Martin
diff mbox series

Patch

diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c
index 85b6826cc10c..636fee27b6b2 100644
--- a/drivers/iio/adc/meson_saradc.c
+++ b/drivers/iio/adc/meson_saradc.c
@@ -957,29 +957,30 @@  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;
 
 	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);
 
-	regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3,
-			   MESON_SAR_ADC_REG3_ADC_EN, 0);
+	if (!ret) {
+		regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3,
+				   MESON_SAR_ADC_REG3_ADC_EN, 0);
 
-	meson_sar_adc_set_bandgap(indio_dev, false);
+		meson_sar_adc_set_bandgap(indio_dev, false);
+	}
 
 	clk_disable_unprepare(priv->core_clk);
 
 	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,7 +1284,9 @@  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)