diff options
author | Robert Rosengren <robert.rosengren@stericsson.com> | 2011-03-17 10:07:59 +0100 |
---|---|---|
committer | Jonas ABERG <jonas.aberg@stericsson.com> | 2011-05-05 07:54:52 +0200 |
commit | 4971a224f854f4d976497baedac90385582b165a (patch) | |
tree | c5cd2cc730e57978998347bd8284161a902c794c /drivers/regulator | |
parent | d2aa06c10251ad48c69aceffcc30ba695d611fe4 (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.c | 20 |
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; } |