Skip to content

Commit

Permalink
regulator: core: Avoid deadlock when regulator_register fails
Browse files Browse the repository at this point in the history
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 <ckeepax@opensource.wolfsonmicro.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
  • Loading branch information
Charles Keepax authored and Mark Brown committed Nov 14, 2012
1 parent 77b6706 commit 23ff2f0
Showing 1 changed file with 17 additions and 11 deletions.
28 changes: 17 additions & 11 deletions drivers/regulator/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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(&regulator_list_mutex);
rdev = regulator->rdev;

debugfs_remove_recursive(regulator->debugfs);
Expand All @@ -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(&regulator_list_mutex);
_regulator_put(regulator);
mutex_unlock(&regulator_list_mutex);
}
EXPORT_SYMBOL_GPL(regulator_put);
Expand Down Expand Up @@ -3445,7 +3451,7 @@ regulator_register(const struct regulator_desc *regulator_desc,

scrub:
if (rdev->supply)
regulator_put(rdev->supply);
_regulator_put(rdev->supply);
if (rdev->ena_gpio)
gpio_free(rdev->ena_gpio);
kfree(rdev->constraints);
Expand Down

0 comments on commit 23ff2f0

Please sign in to comment.