iio: adc: ad7124: Fix missbalanced regulator enable / disable on error.

If the devm_regulator_get() call succeeded but not the regulator_enable()
then regulator_disable() would be called on a regulator that was not
enabled.

Fix this by moving regulator enabling / disabling over to
devm_ management via devm_add_action_or_reset.

Alexandru's sign-off here because he pulled Jonathan's patch into
a larger set which Jonathan then applied.

Fixes: b3af341bbd ("iio: adc: Add ad7124 support")
Reviewed-by: Alexandru Ardelean <ardeleanalex@gmail.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Alexandru Ardelean <aardelean@deviqon.com>
Cc: <Stable@vger.kernel.org>
This commit is contained in:
Jonathan Cameron 2021-05-13 15:07:41 +03:00
parent ba9c25d94d
commit 4573472315

View File

@ -850,6 +850,11 @@ static int ad7124_setup(struct ad7124_state *st)
return ret; return ret;
} }
static void ad7124_reg_disable(void *r)
{
regulator_disable(r);
}
static int ad7124_probe(struct spi_device *spi) static int ad7124_probe(struct spi_device *spi)
{ {
const struct ad7124_chip_info *info; const struct ad7124_chip_info *info;
@ -895,17 +900,20 @@ static int ad7124_probe(struct spi_device *spi)
ret = regulator_enable(st->vref[i]); ret = regulator_enable(st->vref[i]);
if (ret) if (ret)
return ret; return ret;
ret = devm_add_action_or_reset(&spi->dev, ad7124_reg_disable,
st->vref[i]);
if (ret)
return ret;
} }
st->mclk = devm_clk_get(&spi->dev, "mclk"); st->mclk = devm_clk_get(&spi->dev, "mclk");
if (IS_ERR(st->mclk)) { if (IS_ERR(st->mclk))
ret = PTR_ERR(st->mclk); return PTR_ERR(st->mclk);
goto error_regulator_disable;
}
ret = clk_prepare_enable(st->mclk); ret = clk_prepare_enable(st->mclk);
if (ret < 0) if (ret < 0)
goto error_regulator_disable; return ret;
ret = ad7124_soft_reset(st); ret = ad7124_soft_reset(st);
if (ret < 0) if (ret < 0)
@ -935,11 +943,6 @@ error_remove_trigger:
ad_sd_cleanup_buffer_and_trigger(indio_dev); ad_sd_cleanup_buffer_and_trigger(indio_dev);
error_clk_disable_unprepare: error_clk_disable_unprepare:
clk_disable_unprepare(st->mclk); clk_disable_unprepare(st->mclk);
error_regulator_disable:
for (i = ARRAY_SIZE(st->vref) - 1; i >= 0; i--) {
if (!IS_ERR_OR_NULL(st->vref[i]))
regulator_disable(st->vref[i]);
}
return ret; return ret;
} }
@ -948,17 +951,11 @@ static int ad7124_remove(struct spi_device *spi)
{ {
struct iio_dev *indio_dev = spi_get_drvdata(spi); struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct ad7124_state *st = iio_priv(indio_dev); struct ad7124_state *st = iio_priv(indio_dev);
int i;
iio_device_unregister(indio_dev); iio_device_unregister(indio_dev);
ad_sd_cleanup_buffer_and_trigger(indio_dev); ad_sd_cleanup_buffer_and_trigger(indio_dev);
clk_disable_unprepare(st->mclk); clk_disable_unprepare(st->mclk);
for (i = ARRAY_SIZE(st->vref) - 1; i >= 0; i--) {
if (!IS_ERR_OR_NULL(st->vref[i]))
regulator_disable(st->vref[i]);
}
return 0; return 0;
} }