summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRui Zhang <zr.zhang@vivo.com>2022-12-01 11:38:06 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2023-01-18 11:30:37 +0100
commitdc3391d49479bc2bf8a2b88dbf86fdd800882fee (patch)
tree6d8939d32feef7ed8e743f58f4aa358b3c048fdf
parent02bc8bc6eab03c84373281b85cb6e98747172ff7 (diff)
downloadlinux-stable-dc3391d49479bc2bf8a2b88dbf86fdd800882fee.tar.gz
linux-stable-dc3391d49479bc2bf8a2b88dbf86fdd800882fee.tar.bz2
linux-stable-dc3391d49479bc2bf8a2b88dbf86fdd800882fee.zip
regulator: core: fix use_count leakage when handling boot-on
[ Upstream commit 0591b14ce0398125439c759f889647369aa616a0 ] I found a use_count leakage towards supply regulator of rdev with boot-on option. ┌───────────────────┐ ┌───────────────────┐ │ regulator_dev A │ │ regulator_dev B │ │ (boot-on) │ │ (boot-on) │ │ use_count=0 │◀──supply──│ use_count=1 │ │ │ │ │ └───────────────────┘ └───────────────────┘ In case of rdev(A) configured with `regulator-boot-on', the use_count of supplying regulator(B) will increment inside regulator_enable(rdev->supply). Thus, B will acts like always-on, and further balanced regulator_enable/disable cannot actually disable it anymore. However, B was also configured with `regulator-boot-on', we wish it could be disabled afterwards. Signed-off-by: Rui Zhang <zr.zhang@vivo.com> Link: https://lore.kernel.org/r/20221201033806.2567812-1-zr.zhang@vivo.com Signed-off-by: Mark Brown <broonie@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--drivers/regulator/core.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 9cf438a37eeb..11656b383674 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -1197,7 +1197,13 @@ static int set_machine_constraints(struct regulator_dev *rdev)
if (rdev->supply_name && !rdev->supply)
return -EPROBE_DEFER;
- if (rdev->supply) {
+ /* If supplying regulator has already been enabled,
+ * it's not intended to have use_count increment
+ * when rdev is only boot-on.
+ */
+ if (rdev->supply &&
+ (rdev->constraints->always_on ||
+ !regulator_is_enabled(rdev->supply))) {
ret = regulator_enable(rdev->supply);
if (ret < 0) {
_regulator_put(rdev->supply);