aboutsummaryrefslogtreecommitdiff
path: root/drivers/regulator
diff options
context:
space:
mode:
authorRobert Rosengren <robert.rosengren@stericsson.com>2011-03-17 10:07:59 +0100
committerJonas ABERG <jonas.aberg@stericsson.com>2011-05-05 07:54:52 +0200
commit4971a224f854f4d976497baedac90385582b165a (patch)
treec5cd2cc730e57978998347bd8284161a902c794c /drivers/regulator
parentd2aa06c10251ad48c69aceffcc30ba695d611fe4 (diff)
regulator: recursive locking detected when notifying supply regulators
A "possible recursive locking detected"-warning is issued when a regulator has supply regulators and it shall notify the call chain. This is due to locking mutexes of the same lock class, i.e. the locks reside in the regulator_dev struct. Since this is valid behavior for the regulators, this patch changes the mutex lock into nested, as suggested in lockdep-design.txt. ST-Ericsson ID: 283165 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I8e9eae92783414dc49a99c44b7970a246aa9c273 Signed-off-by: Robert Rosengren <robert.rosengren@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/18538 Reviewed-by: Daniel WILLERUD <daniel.willerud@stericsson.com> Reviewed-by: Jonas ABERG <jonas.aberg@stericsson.com>
Diffstat (limited to 'drivers/regulator')
-rw-r--r--drivers/regulator/core.c20
1 files changed, 12 insertions, 8 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 16ee76f9930..0d78dfa7476 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -70,7 +70,7 @@ static int _regulator_get_voltage(struct regulator_dev *rdev);
static int _regulator_get_current_limit(struct regulator_dev *rdev);
static unsigned int _regulator_get_mode(struct regulator_dev *rdev);
static void _notifier_call_chain(struct regulator_dev *rdev,
- unsigned long event, void *data);
+ unsigned long event, void *data, int lock_sublevel);
static const char *rdev_get_name(struct regulator_dev *rdev)
{
@@ -1408,7 +1408,7 @@ static int _regulator_disable(struct regulator_dev *rdev,
}
_notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE,
- NULL);
+ NULL, 0);
}
/* decrease our supplies ref count and disable if required */
@@ -1482,7 +1482,7 @@ static int _regulator_force_disable(struct regulator_dev *rdev,
}
/* notify other consumers that power has been forced off */
_notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE |
- REGULATOR_EVENT_DISABLE, NULL);
+ REGULATOR_EVENT_DISABLE, NULL, 0);
}
/* decrease our supplies ref count and disable if required */
@@ -1670,7 +1670,7 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV);
out:
- _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, NULL);
+ _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, NULL, 0);
mutex_unlock(&rdev->mutex);
return ret;
}
@@ -1983,19 +1983,23 @@ EXPORT_SYMBOL_GPL(regulator_unregister_notifier);
/* notify regulator consumers and downstream regulator consumers.
* Note mutex must be held by caller.
+ * lock_sublevel should always be 0, only used for recursive calls.
*/
static void _notifier_call_chain(struct regulator_dev *rdev,
- unsigned long event, void *data)
+ unsigned long event, void *data, int lock_sublevel)
{
struct regulator_dev *_rdev;
/* call rdev chain first */
blocking_notifier_call_chain(&rdev->notifier, event, NULL);
+ /* increase sublevel before stepping into nested regulators */
+ lock_sublevel++;
+
/* now notify regulator we supply */
list_for_each_entry(_rdev, &rdev->supply_list, slist) {
- mutex_lock(&_rdev->mutex);
- _notifier_call_chain(_rdev, event, data);
+ mutex_lock_nested(&_rdev->mutex, lock_sublevel);
+ _notifier_call_chain(_rdev, event, data, lock_sublevel);
mutex_unlock(&_rdev->mutex);
}
}
@@ -2150,7 +2154,7 @@ EXPORT_SYMBOL_GPL(regulator_bulk_free);
int regulator_notifier_call_chain(struct regulator_dev *rdev,
unsigned long event, void *data)
{
- _notifier_call_chain(rdev, event, data);
+ _notifier_call_chain(rdev, event, data, 0);
return NOTIFY_DONE;
}