Commit 9f01cd4a authored by Sascha Hauer's avatar Sascha Hauer Committed by Mark Brown

regulator: core: introduce function to lock regulators and its supplies

Each regulator_dev is locked with its own mutex. This is fine as long
as only one regulator_dev is locked, but makes lockdep unhappy when we
have to walk up the supply chain like it can happen in
regulator_get_voltage:

regulator_get_voltage ->
 mutex_lock(&regulator->rdev->mutex) ->
_regulator_get_voltage(regulator->rdev) ->
regulator_get_voltage(rdev->supply) ->
mutex_lock(&regulator->rdev->mutex);

This causes lockdep to issue a possible deadlock warning.

There are at least two ways to work around this:

- We can always lock the whole supply chain using the functions
  introduced with this patch.
- We could store the current voltage in struct regulator_rdev so
  that we do not have to walk up the supply chain for the
  _regulator_get_voltage case.

Anyway, regulator_lock_supply/regulator_unlock_supply will be needed
once we allow regulator_set_voltage to optimize the supply voltages.
Signed-off-by: default avatarSascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 6ff33f39
...@@ -131,6 +131,45 @@ static bool have_full_constraints(void) ...@@ -131,6 +131,45 @@ static bool have_full_constraints(void)
return has_full_constraints || of_have_populated_dt(); return has_full_constraints || of_have_populated_dt();
} }
/**
* regulator_lock_supply - lock a regulator and its supplies
* @rdev: regulator source
*/
static void regulator_lock_supply(struct regulator_dev *rdev)
{
struct regulator *supply;
int i = 0;
while (1) {
mutex_lock_nested(&rdev->mutex, i++);
supply = rdev->supply;
if (!rdev->supply)
return;
rdev = supply->rdev;
}
}
/**
* regulator_unlock_supply - unlock a regulator and its supplies
* @rdev: regulator source
*/
static void regulator_unlock_supply(struct regulator_dev *rdev)
{
struct regulator *supply;
while (1) {
mutex_unlock(&rdev->mutex);
supply = rdev->supply;
if (!rdev->supply)
return;
rdev = supply->rdev;
}
}
/** /**
* of_get_regulator - get a regulator device node based on supply name * of_get_regulator - get a regulator device node based on supply name
* @dev: Device pointer for the consumer (of regulator) device * @dev: Device pointer for the consumer (of regulator) device
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment