[PATCH 1/1] usb: dwc3: gadget: add version check for setting ForceRM
From: Elson Serrao
Date: Thu Aug 06 2026 - 19:49:20 EST
The ForceRM bit of the DEPCMD register controls the behavior of the
EndTransfer command used to stop an active transfer. For DWC_usb31
controllers prior to version 2.00a, the programming guide specified
ForceRM=1. Starting with version 2.00a, the programming guide
(section 3.2.2.7) specifies ForceRM=0 when issuing an EndTransfer
command.
With ForceRM=1 on DWC_usb31 v2.00a and v2.10a controllers, an aborted
transfer through the ep_dequeue path was observed to remain active after
EndTransfer completion. A subsequent StartTransfer issued on the same
endpoint triggered writes associated with the aborted transfer. This
resulted in an SMMU fault because the transfer buffer had already been
unmapped during EndTransfer command-completion cleanup.
Using ForceRM=0 eliminates the issue and aligns driver behavior with
the programming guide requirements for DWC_usb31 2.00a and newer
revisions. Add version-based checks to select the appropriate ForceRM
setting based on the controller revision.
Fixes: 1e43c86d84fb ("usb: dwc3: core: Add DWC31 version 2.00a controller")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Elson Serrao <elson.serrao@xxxxxxxxxxxxxxxx>
---
drivers/usb/dwc3/gadget.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index fa0f16ffafef..4b7bcad75d90 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1760,10 +1760,17 @@ static int __dwc3_gadget_get_frame(struct dwc3 *dwc)
*/
static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool interrupt)
{
+ struct dwc3 *dwc = dep->dwc;
struct dwc3_gadget_ep_cmd_params params;
u32 cmd;
int ret;
+ /*
+ * Per the DWC_usb31 programming guide (section 3.2.2.7), EndTransfer
+ * must be issued with ForceRM cleared starting from version 2.00a.
+ */
+ force = force && (!DWC3_IP_IS(DWC31) || DWC3_VER_IS_PRIOR(DWC31, 200A));
+
cmd = DWC3_DEPCMD_ENDTRANSFER;
cmd |= force ? DWC3_DEPCMD_HIPRI_FORCERM : 0;
cmd |= interrupt ? DWC3_DEPCMD_CMDIOC : 0;
--
2.34.1