phy: rockchip: inno-usb2: fix deadlock when using extcon_set_state_sync

The tcpm tx timeout cause a deadlock among these mutex locks.
 - rport->mutex in drivers/phy/rockchip/phy-rockchip-inno-usb2.c
 - phy->mutex in drivers/phy/phy-core.c
 - port->lock in drivers/usb/typec/tcpm/tcpm.c

The kernel report the following hung_task messages:

[ 4393.667144][   T69] Workqueue: events_freezable __dwc3_set_mode
[ 4393.667175][   T69] Call trace:
[ 4393.667187][   T69]  __switch_to+0xf8/0x134
[ 4393.667209][   T69]  __schedule+0x5e8/0x96c
[ 4393.667226][   T69]  schedule+0x7c/0xe4
[ 4393.667244][   T69]  schedule_preempt_disabled+0x24/0x40
[ 4393.667263][   T69]  __mutex_lock+0x3a4/0x950
[ 4393.667282][   T69]  __mutex_lock_slowpath+0x14/0x20
[ 4393.667300][   T69]  mutex_lock+0x38/0x70
[ 4393.667317][   T69]  rockchip_usb2phy_power_on+0x60/0x1e0
[ 4393.667339][   T69]  phy_power_on+0x8c/0x108
[ 4393.667357][   T69]  dwc3_core_init+0xbbc/0x17ac
[ 4393.667377][   T69]  dwc3_resume_common+0x5c/0x4b8
[ 4393.667396][   T69]  dwc3_runtime_resume+0x28/0x64
[ 4393.667416][   T69]  pm_generic_runtime_resume+0x28/0x3c
[ 4393.667437][   T69]  genpd_runtime_resume+0x1fc/0x384
[ 4393.667456][   T69]  __rpm_callback+0x7c/0x3c4
[ 4393.667477][   T69]  rpm_resume+0x43c/0x678
[ 4393.667496][   T69]  __pm_runtime_resume+0x4c/0x90
[ 4393.667515][   T69]  __dwc3_set_mode+0x5c/0x910
[ 4393.667534][   T69]  process_one_work+0x1a8/0x3b8
[ 4393.667557][   T69]  worker_thread+0x25c/0x430
[ 4393.667577][   T69]  kthread+0xec/0x1b8
[ 4393.667597][   T69]  ret_from_fork+0x10/0x20

[ 4393.667713][   T69] Call trace:
[ 4393.667725][   T69]  __switch_to+0xf8/0x134
[ 4393.667744][   T69]  __schedule+0x5e8/0x96c
[ 4393.667761][   T69]  schedule+0x7c/0xe4
[ 4393.667778][   T69]  schedule_preempt_disabled+0x24/0x40
[ 4393.667796][   T69]  __mutex_lock+0x3a4/0x950
[ 4393.667814][   T69]  __mutex_lock_slowpath+0x14/0x20
[ 4393.667833][   T69]  mutex_lock+0x38/0x70
[ 4393.667850][   T69]  phy_set_mode_ext+0x3c/0x88
[ 4393.667868][   T69]  dwc3_usb_role_switch_set+0x30/0x70
[ 4393.667887][   T69]  usb_role_switch_set_role+0x48/0x80
[ 4393.667907][   T69]  tcpm_set_roles+0xc0/0x128
[ 4393.667925][   T69]  run_state_machine+0x8d8/0x1964
[ 4393.667942][   T69]  tcpm_state_machine_work+0x84/0xcc
[ 4393.667963][   T69]  kthread_worker_fn+0xf4/0x228
[ 4393.667982][   T69]  kthread+0xec/0x1b8
[ 4393.668001][   T69]  ret_from_fork+0x10/0x20

[ 4393.668641][   T69] Workqueue: events rockchip_chg_detect_work
[ 4393.668664][   T69] Call trace:
[ 4393.668675][   T69]  __switch_to+0xf8/0x134
[ 4393.668694][   T69]  __schedule+0x5e8/0x96c
[ 4393.668711][   T69]  schedule+0x7c/0xe4
[ 4393.668729][   T69]  schedule_preempt_disabled+0x24/0x40
[ 4393.668747][   T69]  __mutex_lock+0x3a4/0x950
[ 4393.668765][   T69]  __mutex_lock_slowpath+0x14/0x20
[ 4393.668784][   T69]  mutex_lock+0x38/0x70
[ 4393.668801][   T69]  tcpm_psy_set_prop+0x1ec/0x334
[ 4393.668819][   T69]  power_supply_set_property+0x28/0x3c
[ 4393.668840][   T69]  charger_extcon_notifier+0x46c/0x6e4
[ 4393.668858][   T69]  raw_notifier_call_chain+0x44/0x70
[ 4393.668876][   T69]  extcon_sync+0x124/0x2e4
[ 4393.668895][   T69]  extcon_set_state_sync+0x2c/0x3c
[ 4393.668913][   T69]  rockchip_usb2phy_otg_sm_work+0x2b8/0x48c
[ 4393.668934][   T69]  rockchip_chg_detect_work+0x460/0x68c
[ 4393.668954][   T69]  process_one_work+0x1a8/0x3b8
[ 4393.668975][   T69]  worker_thread+0x25c/0x430
[ 4393.668995][   T69]  kthread+0xec/0x1b8
[ 4393.669014][   T69]  ret_from_fork+0x10/0x20

Signed-off-by: Frank Wang <frank.wang@rock-chips.com>
Change-Id: I002878b1e2ac23b6c4e9e2daf6d1bd7cd8f86d0a
This commit is contained in:
Frank Wang
2024-04-09 09:37:47 +08:00
parent 8d5b857b29
commit cda3d64772

View File

@@ -1341,6 +1341,8 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work)
return;
}
mutex_unlock(&rport->mutex);
if (extcon_get_state(rphy->edev, cable) != rport->vbus_attached) {
extcon_set_state_sync(rphy->edev,
cable, rport->vbus_attached);
@@ -1369,8 +1371,6 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work)
}
if (sch_work)
schedule_delayed_work(&rport->otg_sm_work, delay);
mutex_unlock(&rport->mutex);
}
static const char *chg_to_string(enum power_supply_type chg_type)