From 3b892eeb3dcb5e4226d8b3ebfdf0c59f4a4178e6 Mon Sep 17 00:00:00 2001 From: Wu Liang feng Date: Fri, 28 Oct 2016 10:23:09 +0800 Subject: [PATCH] CHROMIUM: usb: dwc3: rockchip: fix hung task timeout when rm xhci-hcd We will remove the xhci controller from usb bus when Type-C USB is disconnected. This patch set xhci state to XHCI_STATE_REMOVING when remove xhci-hcd to indicate that the host is being removed and avoid queueing configure_endpoint commands for the dropped endpoints. This fix the following problem, observed with a USB-C HUB. [11760.112650] INFO: task kworker/0:2:1636 blocked for more than 120 seconds. [11760.119588] Tainted: G W 4.4.21 #2 [11760.124779] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. [11760.134551] kworker/0:2 D ffffffc000204fd8 0 1636 2 0x00000000 [11760.143947] Workqueue: usb_hub_wq hub_event [11760.148173] Call trace: [11760.152660] [] __switch_to+0x9c/0xa8 [11760.157820] [] __schedule+0x440/0x6d8 [11760.166718] [] schedule+0x94/0xb4 [11760.171643] [] schedule_timeout+0x44/0x27c [11760.181127] [] wait_for_common+0xf8/0x198 [11760.186746] [] wait_for_completion+0x28/0x34 [11760.195950] [] xhci_configure_endpoint+0x20c/0x4b0 [11760.202569] [] xhci_check_bandwidth+0x1a4/0x324 [11760.212137] [] usb_hcd_alloc_bandwidth+0xb4/0x2c8 [11760.218446] [] usb_disable_device+0x17c/0x1c8 [11760.227668] [] usb_disconnect+0x9c/0x1d0 [11760.233188] [] hub_event+0x58c/0xde0 [11760.238483] [] process_one_work+0x240/0x424 [11760.244659] [] worker_thread+0x2fc/0x424 [11760.250569] [] kthread+0x10c/0x114 [11760.255755] [] ret_from_fork+0x10/0x40 [11760.261513] task PC stack pid father [11760.268100] kworker/0:2 D ffffffc000204fd8 0 1636 2 0x00000000 [11760.275603] Workqueue: usb_hub_wq hub_event [11760.279915] Call trace: [11760.282437] [] __switch_to+0x9c/0xa8 [11760.287595] [] __schedule+0x440/0x6d8 [11760.292929] [] schedule+0x94/0xb4 [11760.297893] [] schedule_timeout+0x44/0x27c [11760.303598] [] wait_for_common+0xf8/0x198 [11760.309264] [] wait_for_completion+0x28/0x34 [11760.315171] [] xhci_configure_endpoint+0x20c/0x4b0 [11760.321573] [] xhci_check_bandwidth+0x1a4/0x324 [11760.327757] [] usb_hcd_alloc_bandwidth+0xb4/0x2c8 [11760.334094] [] usb_disable_device+0x17c/0x1c8 [11760.340119] [] usb_disconnect+0x9c/0x1d0 [11760.345663] [] hub_event+0x58c/0xde0 [11760.350809] [] process_one_work+0x240/0x424 [11760.356549] [] worker_thread+0x2fc/0x424 [11760.362090] [] kthread+0x10c/0x114 [11760.367055] [] ret_from_fork+0x10/0x40 [11760.372374] kworker/1:1 D ffffffc000204fd8 0 5743 2 0x00000000 [11760.379456] Workqueue: events dwc3_rockchip_otg_extcon_evt_work [11760.385443] Call trace: [11760.387893] [] __switch_to+0x9c/0xa8 [11760.393035] [] __schedule+0x440/0x6d8 [11760.398256] [] schedule+0x94/0xb4 [11760.403134] [] schedule_preempt_disabled+0x28/0x44 [11760.409487] [] __mutex_lock_slowpath+0x120/0x1ac [11760.415664] [] mutex_lock+0x4c/0x68 [11760.420714] [] usb_disconnect+0x5c/0x1d0 [11760.426200] [] usb_remove_hcd+0xc8/0x1e0 [11760.431691] [] dwc3_rockchip_otg_extcon_evt_work+0x134/0x178 [11760.438911] [] process_one_work+0x240/0x424 [11760.444739] [] worker_thread+0x2fc/0x424 [11760.450230] [] kthread+0x10c/0x114 [11760.455196] [] ret_from_fork+0x10/0x40 TEST=do plug/unplug USB-C HUB with a USB3 flash drive, check if kernel blocked for more than 120 seconds. Change-Id: Ib37009c185a2cad6f4671c6a858a737c2ccef1e8 Signed-off-by: Wu Liang feng --- drivers/usb/dwc3/dwc3-rockchip.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/dwc3/dwc3-rockchip.c b/drivers/usb/dwc3/dwc3-rockchip.c index 036f8742cad8..0488af0b29be 100644 --- a/drivers/usb/dwc3/dwc3-rockchip.c +++ b/drivers/usb/dwc3/dwc3-rockchip.c @@ -33,6 +33,7 @@ #include "core.h" #include "io.h" +#include "../host/xhci.h" #define DWC3_ROCKCHIP_AUTOSUSPEND_DELAY 500 /* ms */ @@ -82,6 +83,7 @@ static void dwc3_rockchip_otg_extcon_evt_work(struct work_struct *work) struct dwc3 *dwc = rockchip->dwc; struct extcon_dev *edev = rockchip->edev; struct usb_hcd *hcd; + struct xhci_hcd *xhci; unsigned long flags; int ret; u32 reg; @@ -219,8 +221,10 @@ static void dwc3_rockchip_otg_extcon_evt_work(struct work_struct *work) if (DWC3_GCTL_PRTCAP(reg) == DWC3_GCTL_PRTCAP_HOST || DWC3_GCTL_PRTCAP(reg) == DWC3_GCTL_PRTCAP_OTG) { hcd = dev_get_drvdata(&dwc->xhci->dev); + xhci = hcd_to_xhci(hcd); if (hcd->state != HC_STATE_HALT) { + xhci->xhc_state |= XHCI_STATE_REMOVING; usb_remove_hcd(hcd->shared_hcd); usb_remove_hcd(hcd); } -- 2.34.1