diff --git a/patches/28-dwc3-otg-no-live-reinit.patch b/patches/28-dwc3-otg-no-live-reinit.patch index c8c7871..386076d 100644 --- a/patches/28-dwc3-otg-no-live-reinit.patch +++ b/patches/28-dwc3-otg-no-live-reinit.patch @@ -1,40 +1,33 @@ diff --git a/drivers/usb/dwc3/drd.c b/drivers/usb/dwc3/drd.c --- a/drivers/usb/dwc3/drd.c +++ b/drivers/usb/dwc3/drd.c -@@ -55,7 +55,35 @@ +@@ -55,7 +55,17 @@ spin_lock(&dwc->lock); if (dwc->otg_restart_host) { - dwc3_otg_host_init(dwc); + /* -+ * dwc3_otg_host_init() is documented just above its definition as -+ * "should be called before Host controller driver is started": it -+ * rewrites OCTL/OCFG, touches GUSB2PHYCFG and re-asserts port power -+ * (OCTL.PrtPwrCtl). Doing that to a controller that is already -+ * running corrupts an in-flight command. -+ * -+ * But otg_restart_host is set in dwc3_otg_irq() ONLY when -+ * current_otg_role is already DWC3_OTG_ROLE_HOST, so this path -+ * always ran it against a live host -- the exact condition the -+ * comment forbids. Observed on the RV1106 86-panel as the xHCI -+ * controller failing to answer a Stop Endpoint command, after which -+ * xhci-hcd declares it dead and tears the bus down: an r8152 NIC -+ * would stall a transfer and the controller died 8 times out of 8 -+ * between 452s and 587s. (flare-edge#160) -+ * -+ * On this board the event is always spurious: the dwc3 node -+ * deliberately carries no extcon (wiring it pins the role to -+ * peripheral on D1-modded panels) and CONIDSTS reads 0, so the role -+ * cannot legitimately change while host is current. Skip the -+ * re-init in that case. dwc3_set_mode() below still re-evaluates -+ * the role, and if it has genuinely changed dwc3_otg_update() does -+ * a proper dwc3_host_exit() before re-initialising. ++ * flare-edge#160: dwc3_otg_host_init() is documented as "should be ++ * called before Host controller driver is started" but this path ++ * only ever runs while current_otg_role is already HOST. Skip it ++ * on a live host and record that we did. + */ + if (dwc->current_otg_role == DWC3_OTG_ROLE_HOST) -+ dev_dbg(dwc->dev, -+ "OTG event while host is live; skipping host re-init\n"); ++ dev_warn_ratelimited(dwc->dev, ++ "OTGDIAG skipped host re-init on live host\n"); + else + dwc3_otg_host_init(dwc); dwc->otg_restart_host = false; } +@@ -83,6 +93,10 @@ + if (dwc->current_otg_role == DWC3_OTG_ROLE_HOST && + !(reg & DWC3_OEVT_DEVICEMODE)) + dwc->otg_restart_host = true; ++ /* flare-edge#160 diagnostic: is the OTG event path active at all? */ ++ dev_warn_ratelimited(dwc->dev, ++ "OTGDIAG irq OEVT=0x%08x role=%u restart=%d\n", ++ reg, dwc->current_otg_role, dwc->otg_restart_host); + dwc3_writel(dwc, DWC3_OEVT, reg); + ret = IRQ_WAKE_THREAD; + }