summaryrefslogtreecommitdiff
path: root/drivers/regulator
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2015-09-30 16:05:42 +0200
committerMark Brown <broonie@kernel.org>2015-10-01 12:28:42 +0100
commit9f01cd4a915e13dda6a61b989229015687ffd58f (patch)
tree4dda333498397cf701528f22802f43001c1d416c /drivers/regulator
parent6ff33f3902c3b1c5d0db6b1e2c70b6d76fba357f (diff)
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: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/regulator')
-rw-r--r--drivers/regulator/core.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 7a85ac9e32c5..1f9ff55b3620 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -132,6 +132,45 @@ static bool have_full_constraints(void)
}
/**
+ * 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
* @dev: Device pointer for the consumer (of regulator) device
* @supply: regulator supply name