aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Hunter <jonathanh@nvidia.com>2016-03-30 12:09:13 -0400
committerMark Brown <broonie@kernel.org>2016-03-30 14:03:54 -0400
commita2151374230820a3a6e654f2998b2a44dbfae4e1 (patch)
tree666f47abfa742a71fde56c3b5267db66410c896e
parent5e3ca2b349b1e2c80b060b51bbf2af37448fad85 (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.c10
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(&regulator_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(&regulator_class, NULL, NULL, 3997 class_for_each_device(&regulator_class, NULL, NULL,
3997 regulator_register_resolve_supply); 3998 regulator_register_resolve_supply);
3998out:
3999 mutex_unlock(&regulator_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
4013wash: 4011wash:
4014 regulator_ena_gpio_free(rdev); 4012 regulator_ena_gpio_free(rdev);
4015clean: 4013clean:
4016 kfree(rdev); 4014 kfree(rdev);
4017 rdev = ERR_PTR(ret); 4015out:
4018 goto out; 4016 mutex_unlock(&regulator_list_mutex);
4017 kfree(config);
4018 return ERR_PTR(ret);
4019} 4019}
4020EXPORT_SYMBOL_GPL(regulator_register); 4020EXPORT_SYMBOL_GPL(regulator_register);
4021 4021