diff options
author | Jon Hunter <jonathanh@nvidia.com> | 2016-03-30 12:09:13 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2016-03-30 14:03:54 -0400 |
commit | a2151374230820a3a6e654f2998b2a44dbfae4e1 (patch) | |
tree | 666f47abfa742a71fde56c3b5267db66410c896e | |
parent | 5e3ca2b349b1e2c80b060b51bbf2af37448fad85 (diff) |
regulator: Fix deadlock during regulator registration
Commit 5e3ca2b349b1 ("regulator: Try to resolve regulators supplies on
registration") added a call to regulator_resolve_supply() within
regulator_register() where the regulator_list_mutex is held. This causes
a deadlock to occur on the Tegra114 Dalmore board when the palmas PMIC
is registered because regulator_register_resolve_supply() calls
regulator_dev_lookup() which may try to acquire the regulator_list_mutex
again.
Fix this by releasing the mutex before calling
regulator_register_resolve_supply() and update the error exit path to
ensure the mutex is released on an error.
[Made commit message more legible -- broonie]
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | drivers/regulator/core.c | 10 |
1 files changed, 5 insertions, 5 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index ab1838138877..fd0e4e37f4e1 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c | |||
@@ -3991,12 +3991,11 @@ regulator_register(const struct regulator_desc *regulator_desc, | |||
3991 | } | 3991 | } |
3992 | 3992 | ||
3993 | rdev_init_debugfs(rdev); | 3993 | rdev_init_debugfs(rdev); |
3994 | mutex_unlock(®ulator_list_mutex); | ||
3994 | 3995 | ||
3995 | /* try to resolve regulators supply since a new one was registered */ | 3996 | /* try to resolve regulators supply since a new one was registered */ |
3996 | class_for_each_device(®ulator_class, NULL, NULL, | 3997 | class_for_each_device(®ulator_class, NULL, NULL, |
3997 | regulator_register_resolve_supply); | 3998 | regulator_register_resolve_supply); |
3998 | out: | ||
3999 | mutex_unlock(®ulator_list_mutex); | ||
4000 | kfree(config); | 3999 | kfree(config); |
4001 | return rdev; | 4000 | return rdev; |
4002 | 4001 | ||
@@ -4007,15 +4006,16 @@ scrub: | |||
4007 | regulator_ena_gpio_free(rdev); | 4006 | regulator_ena_gpio_free(rdev); |
4008 | device_unregister(&rdev->dev); | 4007 | device_unregister(&rdev->dev); |
4009 | /* device core frees rdev */ | 4008 | /* device core frees rdev */ |
4010 | rdev = ERR_PTR(ret); | ||
4011 | goto out; | 4009 | goto out; |
4012 | 4010 | ||
4013 | wash: | 4011 | wash: |
4014 | regulator_ena_gpio_free(rdev); | 4012 | regulator_ena_gpio_free(rdev); |
4015 | clean: | 4013 | clean: |
4016 | kfree(rdev); | 4014 | kfree(rdev); |
4017 | rdev = ERR_PTR(ret); | 4015 | out: |
4018 | goto out; | 4016 | mutex_unlock(®ulator_list_mutex); |
4017 | kfree(config); | ||
4018 | return ERR_PTR(ret); | ||
4019 | } | 4019 | } |
4020 | EXPORT_SYMBOL_GPL(regulator_register); | 4020 | EXPORT_SYMBOL_GPL(regulator_register); |
4021 | 4021 | ||