* [PATCH v2] usb: dwc3: core: Fix RAM interface getting stuck during enumeration
@ 2026-08-06 5:49 Krishna Kurapati
2026-08-07 23:12 ` Thinh Nguyen
0 siblings, 1 reply; 2+ messages in thread
From: Krishna Kurapati @ 2026-08-06 5:49 UTC (permalink / raw)
To: Thinh Nguyen, Greg Kroah-Hartman
Cc: linux-usb, linux-kernel, Krishna Kurapati
During plug-in/plug-out test cases, it is sometimes seen that no events
are generated by the controller and all CSR register reads give "0" and
CSR_Timeout bit gets set indicating that CSR reads/writes are timing out
or timed out.
The issue comes up on different instnaces of enumeration on different
platforms. On SM8550, the debug log is as follows:
Prepared a TRB on ep0out and did start transfer to get set
address request from host:
<...>-7191 [000] D..1. 66.421006: dwc3_gadget_ep_cmd: ep0out:
cmd 'Start Transfer' [406] params 00000000 efffa000 00000000 -->
status: Successful
<...>-7191 [000] D..1. 66.421196: dwc3_event: event (0000c040):
ep0out: Transfer Complete (sIL) [Setup Phase]
<...>-7191 [000] D..1. 66.421197: dwc3_ctrl_req: Set
Address(Addr = 01)
An XFER NRDY is received on ep0in for zero length status phase and
a Start Transfer was done on ep0in with 0-length packet in 2 Stage
status phase:
<...>-7191 [000] D..1. 66.421249: dwc3_event: event (000020c2):
ep0in: Transfer Not Ready [00000000] (Not Active) [Status Phase]
<...>-7191 [000] D..1. 66.421266: dwc3_prepare_trb: ep0in: trb
ffffffc00fcfd000 (E0:D0) buf 00000000efffa000 size 0 ctrl 00000c33
sofn 00000000 (HLcs:SC:status2)
<...>-7191 [000] D..1. 66.421387: dwc3_gadget_ep_cmd: ep0in: cmd
'Start Transfer' [406] params 00000000 efffa000 00000000 -->status:
Successful
A bus reset was then received directly after 500 msec. Software never
got the cmd complete for the start transfer done in status phase. Here
the RAM interface is stuck. So host issues a bus reset as link is
idle for 500 msec:
<...>-7191 [000] D..1. 66.935603: dwc3_event: event (00000101):
Reset [U0]
Then software sees that it is in status phase and we issue an ENDXFER
on ep0in and it gets timedout waiting for the CMDACT to go '0':
<...>-7191 [000] D..1. 66.958249: dwc3_gadget_ep_cmd: ep0in: cmd
'End Transfer' [10508] params 00000000 00000000 00000000 --> status:
Timed Out
Upon debug with Synopsys, the root cause is as follows:
During any transfer, if the data is not successfully transmitted,
then a Done (with failure) handshake is returned, so that the BMU
can re-attempt the same data again by rewinding its data pointers.
But, if the USB IN is a 0-length payload (which is what is happening
in this case - 2 stage status phase of set_address), then there is no
need to rewind the pointers and the Done (with failure) handshake is
not returned for failure case. This keeps the Request-Done interface
busy till the next Done handshake. The MAC sends the 0-length payload
again when the host requests. If the transmission is successful this
time, the Done (with success) handshake is provided back. Otherwise,
it repeats the same steps again.
If the cable is disconnected or if the Host aborts the transfer on 3
consecutive failed attempts, the Request-Done handshake is not
complete. This keeps the interface busy.
The subsequent RAM access cannot proceed until the above pending
transfer is complete. This results in failure of any access to RAM
address locations. Many of the EndPoint commands need to access the
RAM and they would fail to complete successfully.
Furthermore when cable removal happens, this would not generate a
disconnect event and the "connected" flag remains true always blockin
suspend.
Synopsys confirmed that the issue is present on all USB3 devices and
as a workaround, suggested to re-initialize device mode.
Signed-off-by: Krishna Kurapati <krishna.kurapati@oss.qualcomm.com>
---
This series has only been compile tested. The issue was reproduced
easily with a certain kind of cable and CDP port of AMD based Lenovo
laptop. I don't have access to the cable currently and hence only
compile testing the fix for now. But the issue has popped up on OEM
testing as well.
Changes in v2:
- Implemented gadget recovery mechanism during gadget_ep_cmd instead of
handling this issue only during disconnect.
Link to RFC:
https://lore.kernel.org/all/20231011100214.25720-1-quic_kriskura@quicinc.com/
---
drivers/usb/dwc3/gadget.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index fa0f16ffafef..7aa290a804cc 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -283,6 +283,17 @@ int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned int cmd,
return ret;
}
+static int dwc3_gadget_soft_disconnect(struct dwc3 *dwc);
+static int dwc3_gadget_soft_connect(struct dwc3 *dwc);
+
+static void dwc3_gadget_recover(struct dwc3 *dwc)
+{
+ dev_warn(dwc->dev, "controller dead... triggering soft reconnect\n");
+ dwc3_gadget_soft_disconnect(dwc);
+ udelay(100);
+ dwc3_gadget_soft_connect(dwc);
+}
+
/**
* dwc3_send_gadget_ep_cmd - issue an endpoint command
* @dep: the endpoint to which the command is going to be issued
@@ -432,6 +443,23 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd,
cmd_status = -ETIMEDOUT;
}
+ /*
+ * STAR 5001544 - In some situations, like the cable is
+ * disconnected or if the Host aborts the transfer on 3
+ * consecutive failed attempts, the Request-Done handshake is not
+ * complete. This keeps the RAM interface busy.
+ *
+ * The subsequent RAM access cannot proceed until the pending
+ * transfer is complete. This results in failure of any access
+ * to RAM address locations. Many of the EndPoint commands need to
+ * access the RAM and they would fail to complete successfully.
+ *
+ * If the depcmd doesn't match the actual command, trigger controller
+ * recovery.
+ */
+ if (DWC3_DEPCMD_CMD(reg) != DWC3_DEPCMD_CMD(cmd))
+ dwc3_gadget_recover(dwc);
+
skip_status:
trace_dwc3_gadget_ep_cmd(dep, cmd, params, cmd_status);
---
base-commit: 5d5fd841c34649f1b09220fe58e59dffd61c447d
change-id: 20260803-ram-interface-code-12c624709732
Best regards,
--
Krishna Kurapati <krishna.kurapati@oss.qualcomm.com>
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH v2] usb: dwc3: core: Fix RAM interface getting stuck during enumeration
2026-08-06 5:49 [PATCH v2] usb: dwc3: core: Fix RAM interface getting stuck during enumeration Krishna Kurapati
@ 2026-08-07 23:12 ` Thinh Nguyen
0 siblings, 0 replies; 2+ messages in thread
From: Thinh Nguyen @ 2026-08-07 23:12 UTC (permalink / raw)
To: Krishna Kurapati
Cc: Thinh Nguyen, Greg Kroah-Hartman, linux-usb@vger.kernel.org,
linux-kernel@vger.kernel.org
On Thu, Aug 06, 2026, Krishna Kurapati wrote:
> During plug-in/plug-out test cases, it is sometimes seen that no events
> are generated by the controller and all CSR register reads give "0" and
> CSR_Timeout bit gets set indicating that CSR reads/writes are timing out
> or timed out.
>
> The issue comes up on different instnaces of enumeration on different
> platforms. On SM8550, the debug log is as follows:
>
> Prepared a TRB on ep0out and did start transfer to get set
> address request from host:
>
> <...>-7191 [000] D..1. 66.421006: dwc3_gadget_ep_cmd: ep0out:
> cmd 'Start Transfer' [406] params 00000000 efffa000 00000000 -->
> status: Successful
>
> <...>-7191 [000] D..1. 66.421196: dwc3_event: event (0000c040):
> ep0out: Transfer Complete (sIL) [Setup Phase]
>
> <...>-7191 [000] D..1. 66.421197: dwc3_ctrl_req: Set
> Address(Addr = 01)
>
> An XFER NRDY is received on ep0in for zero length status phase and
> a Start Transfer was done on ep0in with 0-length packet in 2 Stage
> status phase:
>
> <...>-7191 [000] D..1. 66.421249: dwc3_event: event (000020c2):
> ep0in: Transfer Not Ready [00000000] (Not Active) [Status Phase]
>
> <...>-7191 [000] D..1. 66.421266: dwc3_prepare_trb: ep0in: trb
> ffffffc00fcfd000 (E0:D0) buf 00000000efffa000 size 0 ctrl 00000c33
> sofn 00000000 (HLcs:SC:status2)
>
> <...>-7191 [000] D..1. 66.421387: dwc3_gadget_ep_cmd: ep0in: cmd
> 'Start Transfer' [406] params 00000000 efffa000 00000000 -->status:
> Successful
>
> A bus reset was then received directly after 500 msec. Software never
> got the cmd complete for the start transfer done in status phase. Here
> the RAM interface is stuck. So host issues a bus reset as link is
> idle for 500 msec:
>
> <...>-7191 [000] D..1. 66.935603: dwc3_event: event (00000101):
> Reset [U0]
>
> Then software sees that it is in status phase and we issue an ENDXFER
> on ep0in and it gets timedout waiting for the CMDACT to go '0':
>
> <...>-7191 [000] D..1. 66.958249: dwc3_gadget_ep_cmd: ep0in: cmd
> 'End Transfer' [10508] params 00000000 00000000 00000000 --> status:
> Timed Out
>
> Upon debug with Synopsys, the root cause is as follows:
>
> During any transfer, if the data is not successfully transmitted,
> then a Done (with failure) handshake is returned, so that the BMU
> can re-attempt the same data again by rewinding its data pointers.
>
> But, if the USB IN is a 0-length payload (which is what is happening
> in this case - 2 stage status phase of set_address), then there is no
> need to rewind the pointers and the Done (with failure) handshake is
> not returned for failure case. This keeps the Request-Done interface
> busy till the next Done handshake. The MAC sends the 0-length payload
> again when the host requests. If the transmission is successful this
> time, the Done (with success) handshake is provided back. Otherwise,
> it repeats the same steps again.
>
> If the cable is disconnected or if the Host aborts the transfer on 3
> consecutive failed attempts, the Request-Done handshake is not
> complete. This keeps the interface busy.
>
> The subsequent RAM access cannot proceed until the above pending
> transfer is complete. This results in failure of any access to RAM
> address locations. Many of the EndPoint commands need to access the
> RAM and they would fail to complete successfully.
>
> Furthermore when cable removal happens, this would not generate a
> disconnect event and the "connected" flag remains true always blockin
> suspend.
>
> Synopsys confirmed that the issue is present on all USB3 devices and
> as a workaround, suggested to re-initialize device mode.
>
> Signed-off-by: Krishna Kurapati <krishna.kurapati@oss.qualcomm.com>
> ---
> This series has only been compile tested. The issue was reproduced
> easily with a certain kind of cable and CDP port of AMD based Lenovo
> laptop. I don't have access to the cable currently and hence only
> compile testing the fix for now. But the issue has popped up on OEM
> testing as well.
>
> Changes in v2:
> - Implemented gadget recovery mechanism during gadget_ep_cmd instead of
> handling this issue only during disconnect.
>
> Link to RFC:
> https://urldefense.com/v3/__https://lore.kernel.org/all/20231011100214.25720-1-quic_kriskura@quicinc.com/__;!!A4F2R9G_pg!eBUzMlnEP2TK2HfbFZJaL1FQ2kLpCTkQgpKJf1nK616krwl1F5bq2LDIEAHwGpFj1ooH8y6Qzo1zikdXo0CszO5YCBQUTRhswkwqXA$
> ---
> drivers/usb/dwc3/gadget.c | 28 ++++++++++++++++++++++++++++
> 1 file changed, 28 insertions(+)
>
> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
> index fa0f16ffafef..7aa290a804cc 100644
> --- a/drivers/usb/dwc3/gadget.c
> +++ b/drivers/usb/dwc3/gadget.c
> @@ -283,6 +283,17 @@ int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned int cmd,
> return ret;
> }
>
> +static int dwc3_gadget_soft_disconnect(struct dwc3 *dwc);
> +static int dwc3_gadget_soft_connect(struct dwc3 *dwc);
> +
> +static void dwc3_gadget_recover(struct dwc3 *dwc)
> +{
> + dev_warn(dwc->dev, "controller dead... triggering soft reconnect\n");
> + dwc3_gadget_soft_disconnect(dwc);
> + udelay(100);
> + dwc3_gadget_soft_connect(dwc);
> +}
> +
> /**
> * dwc3_send_gadget_ep_cmd - issue an endpoint command
> * @dep: the endpoint to which the command is going to be issued
> @@ -432,6 +443,23 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd,
> cmd_status = -ETIMEDOUT;
> }
>
> + /*
> + * STAR 5001544 - In some situations, like the cable is
> + * disconnected or if the Host aborts the transfer on 3
> + * consecutive failed attempts, the Request-Done handshake is not
> + * complete. This keeps the RAM interface busy.
> + *
> + * The subsequent RAM access cannot proceed until the pending
> + * transfer is complete. This results in failure of any access
> + * to RAM address locations. Many of the EndPoint commands need to
> + * access the RAM and they would fail to complete successfully.
> + *
> + * If the depcmd doesn't match the actual command, trigger controller
> + * recovery.
> + */
> + if (DWC3_DEPCMD_CMD(reg) != DWC3_DEPCMD_CMD(cmd))
> + dwc3_gadget_recover(dwc);
> +
> skip_status:
> trace_dwc3_gadget_ep_cmd(dep, cmd, params, cmd_status);
>
>
> ---
> base-commit: 5d5fd841c34649f1b09220fe58e59dffd61c447d
> change-id: 20260803-ram-interface-code-12c624709732
>
> Best regards,
> --
> Krishna Kurapati <krishna.kurapati@oss.qualcomm.com>
>
Liu is also working on a controller recovery flow here:
https://lore.kernel.org/linux-usb/anZYnWfDlNPRQBq3@vbox/T/#t
Maybe you can review my feedback there also.
Thanks,
Thinh
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-08-07 23:13 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-06 5:49 [PATCH v2] usb: dwc3: core: Fix RAM interface getting stuck during enumeration Krishna Kurapati
2026-08-07 23:12 ` Thinh Nguyen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox