diff options
author | Dmitry Osipenko <digetx@gmail.com> | 2018-11-19 00:56:18 +0300 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2018-11-19 12:33:18 +0000 |
commit | 089e2cc2e1861ad13a56811aa538419989346089 (patch) | |
tree | ff28312962a161517803bc7431d435288abb5fca | |
parent | f8702f9e4aa7b45131af3df5531d6e3835269141 (diff) | |
download | linux-089e2cc2e1861ad13a56811aa538419989346089.tar.bz2 |
regulator: core: Properly handle case where supply is the couple
Check whether supply regulator is the couple to avoid infinite recursion
during of locking.
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | drivers/regulator/core.c | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 47ccd35c7965..e46e53aa43db 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -233,6 +233,21 @@ void regulator_unlock(struct regulator_dev *rdev) mutex_unlock(®ulator_nesting_mutex); } +static bool regulator_supply_is_couple(struct regulator_dev *rdev) +{ + struct regulator_dev *c_rdev; + int i; + + for (i = 1; i < rdev->coupling_desc.n_coupled; i++) { + c_rdev = rdev->coupling_desc.coupled_rdevs[i]; + + if (rdev->supply->rdev == c_rdev) + return true; + } + + return false; +} + static void regulator_unlock_recursive(struct regulator_dev *rdev, unsigned int n_coupled) { @@ -245,7 +260,7 @@ static void regulator_unlock_recursive(struct regulator_dev *rdev, if (!c_rdev) continue; - if (c_rdev->supply) + if (c_rdev->supply && !regulator_supply_is_couple(c_rdev)) regulator_unlock_recursive( c_rdev->supply->rdev, c_rdev->coupling_desc.n_coupled); @@ -283,7 +298,7 @@ static int regulator_lock_recursive(struct regulator_dev *rdev, *old_contended_rdev = NULL; } - if (c_rdev->supply) { + if (c_rdev->supply && !regulator_supply_is_couple(c_rdev)) { err = regulator_lock_recursive(c_rdev->supply->rdev, new_contended_rdev, old_contended_rdev, |