diff options
| author | Umang Agrawal <uagrawal@codeaurora.org> | 2018-06-20 14:48:05 +0530 |
|---|---|---|
| committer | Georg Veichtlbauer <georg@vware.at> | 2023-07-16 12:47:42 +0200 |
| commit | 07f7c9961c7cd0090dd1771f61245746af7fe1ea (patch) | |
| tree | a33df9d62772c1b6d57392ec51ec75071fb9419d | |
| parent | 094b738f46c80c56d03d923c3e780e071abe34b0 (diff) | |
power: smb-lib: Fix mutex acquisition deadlock on PD hard reset
Mutex acquisition deadlock can happen while cancelling cc_dettach
work during pd_hard_reset from the function usbin_plugin_hard_reset
_locked on vbus rise which is called in the same lock context that
we try to acquire in the cc_dettach work routine.
Check if cc_dettach work is running during pd_hard_reset and use
trylock instead of mutex_lock to prevent any deadlock if mutext is
already held.
Change-Id: I5530deb9e654d3d12ba1b4bc6876f36127a0d5a5
Signed-off-by: Umang Agrawal <uagrawal@codeaurora.org>
| -rw-r--r-- | drivers/power/supply/qcom/smb-lib.c | 24 |
1 files changed, 22 insertions, 2 deletions
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c index 81623c65ea8e..1782f23fafa7 100644 --- a/drivers/power/supply/qcom/smb-lib.c +++ b/drivers/power/supply/qcom/smb-lib.c @@ -4457,6 +4457,7 @@ static void rdstd_cc2_detach_work(struct work_struct *work) { int rc; u8 stat4, stat5; + bool lock = false; struct smb_charger *chg = container_of(work, struct smb_charger, rdstd_cc2_detach_work); @@ -4519,9 +4520,28 @@ static void rdstd_cc2_detach_work(struct work_struct *work) rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, EXIT_SNK_BASED_ON_CC_BIT, 0); smblib_reg_block_restore(chg, cc2_detach_settings); - mutex_lock(&chg->lock); + + /* + * Mutex acquisition deadlock can happen while cancelling this work + * during pd_hard_reset from the function smblib_cc2_sink_removal_exit + * which is called in the same lock context that we try to acquire in + * this work routine. + * Check if this work is running during pd_hard_reset and use trylock + * instead of mutex_lock to prevent any deadlock if mutext is already + * held. + */ + if (chg->pd_hard_reset) { + if (mutex_trylock(&chg->lock)) + lock = true; + } else { + mutex_lock(&chg->lock); + lock = true; + } + smblib_usb_typec_change(chg); - mutex_unlock(&chg->lock); + + if (lock) + mutex_unlock(&chg->lock); return; rerun: |
