Skip to content

Commit

Permalink
regulator: core: Clean up on enable failure
Browse files Browse the repository at this point in the history
[ Upstream commit c32f1eb ]

If regulator_enable() fails, enable_count is incremented still.
A consumer, assuming no matching regulator_disable() is necessary on
failure, will then get this error message upon regulator_put()
since enable_count is non-zero:

    [    1.277418] WARNING: CPU: 3 PID: 1 at drivers/regulator/core.c:2304 _regulator_put.part.0+0x168/0x170

The consumer could try to fix this in their driver by cleaning up on
error from regulator_enable() (i.e. call regulator_disable()), but that
results in the following since regulator_enable() failed and didn't
increment user_count:

    [    1.258112] unbalanced disables for vreg_l17c
    [    1.262606] WARNING: CPU: 4 PID: 1 at drivers/regulator/core.c:2899 _regulator_disable+0xd4/0x190

Fix this by decrementing enable_count upon failure to enable.

With this in place, just the reason for failure to enable is printed
as expected and developers can focus on the root cause of their issue
instead of thinking their usage of the regulator consumer api is
incorrect. For example, in my case:

    [    1.240426] vreg_l17c: invalid input voltage found

Fixes: 5451781 ("regulator: core: Only count load for enabled consumers")
Signed-off-by: Andrew Halaney <ahalaney@redhat.com>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
Reviewed-by: Brian Masney <bmasney@redhat.com>
Link: https://lore.kernel.org/r/20220819194336.382740-1-ahalaney@redhat.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
ahalaney authored and gregkh committed Sep 15, 2022
1 parent 99fc0f4 commit 8fb6a79
Showing 1 changed file with 7 additions and 2 deletions.
9 changes: 7 additions & 2 deletions drivers/regulator/core.c
Expand Up @@ -2732,13 +2732,18 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
*/
static int _regulator_handle_consumer_enable(struct regulator *regulator)
{
int ret;
struct regulator_dev *rdev = regulator->rdev;

lockdep_assert_held_once(&rdev->mutex.base);

regulator->enable_count++;
if (regulator->uA_load && regulator->enable_count == 1)
return drms_uA_update(rdev);
if (regulator->uA_load && regulator->enable_count == 1) {
ret = drms_uA_update(rdev);
if (ret)
regulator->enable_count--;
return ret;
}

return 0;
}
Expand Down

0 comments on commit 8fb6a79

Please sign in to comment.