From b2da55d9441cbdaf73c12403ed801b644d5ae5e3 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sun, 28 Oct 2012 16:01:11 +0100 Subject: [PATCH 1/3] Regulator: core: Unregister when gpio request fails. If the gpio_request_one() fails, or returns EPROBE_DEFER, the regulator must be device_unregister()ed. When this is not done, there are WARNING: from sysfs: WARNING: at fs/sysfs/file.c:343 sysfs_open_file+0x238/0x268() Signed-off-by: Andrew Lunn Signed-off-by: Mark Brown --- drivers/regulator/core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 5c4829cba6a6..aa4d28b5984e 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3365,7 +3365,7 @@ regulator_register(const struct regulator_desc *regulator_desc, if (ret != 0) { rdev_err(rdev, "Failed to request enable GPIO%d: %d\n", config->ena_gpio, ret); - goto clean; + goto wash; } rdev->ena_gpio = config->ena_gpio; @@ -3449,6 +3449,7 @@ scrub: if (rdev->ena_gpio) gpio_free(rdev->ena_gpio); kfree(rdev->constraints); +wash: device_unregister(&rdev->dev); /* device core frees rdev */ rdev = ERR_PTR(ret); From 23ff2f0f6128b4c310fbb274dbb91cc2f9b6ab06 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 14 Nov 2012 09:39:31 +0000 Subject: [PATCH 2/3] regulator: core: Avoid deadlock when regulator_register fails When regulator_register fails and exits through the scrub path the regulator_put function was called whilst holding the regulator_list_mutex, causing deadlock. This patch adds a private version of the regulator_put function which can be safely called whilst holding the mutex, replacing the aforementioned call. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- drivers/regulator/core.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 5c4829cba6a6..3ebc06b280ab 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1381,22 +1381,14 @@ struct regulator *regulator_get_exclusive(struct device *dev, const char *id) } EXPORT_SYMBOL_GPL(regulator_get_exclusive); -/** - * regulator_put - "free" the regulator source - * @regulator: regulator source - * - * Note: drivers must ensure that all regulator_enable calls made on this - * regulator source are balanced by regulator_disable calls prior to calling - * this function. - */ -void regulator_put(struct regulator *regulator) +/* Locks held by regulator_put() */ +static void _regulator_put(struct regulator *regulator) { struct regulator_dev *rdev; if (regulator == NULL || IS_ERR(regulator)) return; - mutex_lock(®ulator_list_mutex); rdev = regulator->rdev; debugfs_remove_recursive(regulator->debugfs); @@ -1412,6 +1404,20 @@ void regulator_put(struct regulator *regulator) rdev->exclusive = 0; module_put(rdev->owner); +} + +/** + * regulator_put - "free" the regulator source + * @regulator: regulator source + * + * Note: drivers must ensure that all regulator_enable calls made on this + * regulator source are balanced by regulator_disable calls prior to calling + * this function. + */ +void regulator_put(struct regulator *regulator) +{ + mutex_lock(®ulator_list_mutex); + _regulator_put(regulator); mutex_unlock(®ulator_list_mutex); } EXPORT_SYMBOL_GPL(regulator_put); @@ -3445,7 +3451,7 @@ unset_supplies: scrub: if (rdev->supply) - regulator_put(rdev->supply); + _regulator_put(rdev->supply); if (rdev->ena_gpio) gpio_free(rdev->ena_gpio); kfree(rdev->constraints); From f0f98b19e23d4426ca185e3d4ca80e6aff5ef51b Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 13 Nov 2012 09:48:51 +0100 Subject: [PATCH 3/3] regulator: fix voltage check in regulator_is_supported_voltage() regulator_is_supported_voltage() should return true only if the voltage of fixed/constant regulator is between min_uV and max_uV. Signed-off-by: Marek Szyprowski Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- drivers/regulator/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 5c4829cba6a6..27eb9d66f06a 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1974,7 +1974,7 @@ int regulator_is_supported_voltage(struct regulator *regulator, if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { ret = regulator_get_voltage(regulator); if (ret >= 0) - return (min_uV >= ret && ret <= max_uV); + return (min_uV <= ret && ret <= max_uV); else return ret; }