summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUmang Agrawal <uagrawal@codeaurora.org>2018-06-20 14:48:05 +0530
committerGeorg Veichtlbauer <georg@vware.at>2023-07-16 12:47:42 +0200
commit07f7c9961c7cd0090dd1771f61245746af7fe1ea (patch)
treea33df9d62772c1b6d57392ec51ec75071fb9419d
parent094b738f46c80c56d03d923c3e780e071abe34b0 (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.c24
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: