Skip to content

Commit

Permalink
iio: adc: ad7124: Fix missbalanced regulator enable / disable on error.
Browse files Browse the repository at this point in the history
commit 4573472 upstream.

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: b3af341 ("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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
jic23 authored and gregkh committed Jun 3, 2021
1 parent dceb4ec commit fbb02b5
Showing 1 changed file with 13 additions and 16 deletions.
29 changes: 13 additions & 16 deletions drivers/iio/adc/ad7124.c
Expand Up @@ -707,6 +707,11 @@ static int ad7124_setup(struct ad7124_state *st)
return ret;
}

static void ad7124_reg_disable(void *r)
{
regulator_disable(r);
}

static int ad7124_probe(struct spi_device *spi)
{
const struct ad7124_chip_info *info;
Expand Down Expand Up @@ -752,17 +757,20 @@ static int ad7124_probe(struct spi_device *spi)
ret = regulator_enable(st->vref[i]);
if (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");
if (IS_ERR(st->mclk)) {
ret = PTR_ERR(st->mclk);
goto error_regulator_disable;
}
if (IS_ERR(st->mclk))
return PTR_ERR(st->mclk);

ret = clk_prepare_enable(st->mclk);
if (ret < 0)
goto error_regulator_disable;
return ret;

ret = ad7124_soft_reset(st);
if (ret < 0)
Expand Down Expand Up @@ -792,11 +800,6 @@ static int ad7124_probe(struct spi_device *spi)
ad_sd_cleanup_buffer_and_trigger(indio_dev);
error_clk_disable_unprepare:
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;
}
Expand All @@ -805,17 +808,11 @@ static int ad7124_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct ad7124_state *st = iio_priv(indio_dev);
int i;

iio_device_unregister(indio_dev);
ad_sd_cleanup_buffer_and_trigger(indio_dev);
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;
}

Expand Down

0 comments on commit fbb02b5

Please sign in to comment.