diff options
author | Philippe Langlais <philippe.langlais@linaro.org> | 2011-05-11 10:02:36 +0200 |
---|---|---|
committer | Robert Marklund <robert.marklund@stericsson.com> | 2011-10-05 12:11:37 +0200 |
commit | 4624a6b3b51a15d1852cddfc67674b83ad145a67 (patch) | |
tree | 300a8e4b3222e0c76cb722e503acac803bbde538 /drivers/regulator | |
parent | 99a1ba313bb5aa550978e5d78d7a60a3cbada376 (diff) |
cg2900: Fix crash when transport is closed
This patch fixes crashes caused by transport being removed
while users of the CG2900 driver still exist.
ST-Ericsson Linux next: Not tested, ER 336652
ST-Ericsson ID: 336652
ST-Ericsson FOSS-OUT ID: Trivial
Change-Id: I6318ce1086097a4fa63a1793b6795b01ea939715
Signed-off-by: Par-Gunnar Hjalmdahl <par-gunnar.p.hjalmdahl@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/21781
Reviewed-by: QATEST
Reviewed-by: Lukasz RYMANOWSKI <lukasz.rymanowski@stericsson.com>
Conflicts:
drivers/bluetooth/btcg2900.c
drivers/bluetooth/cg2900_uart.c
drivers/mfd/cg2900/cg2900_audio.c
drivers/mfd/cg2900/cg2900_char_devices.c
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 cfe19f1aacf..5cdcb615a68 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -88,7 +88,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 int _regulator_do_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV); @@ -1456,7 +1456,7 @@ static int _regulator_disable(struct regulator_dev *rdev, trace_regulator_disable_complete(rdev_get_name(rdev)); _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, - NULL); + NULL, 0); } /* decrease our supplies ref count and disable if required */ @@ -1529,7 +1529,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 */ @@ -1755,7 +1755,7 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, if (ret == 0) _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, - NULL); + NULL, 0); trace_regulator_set_voltage_complete(rdev_get_name(rdev), selector); @@ -2237,19 +2237,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); } } @@ -2403,7 +2407,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; } |