* [PATCH 0/7] usb: dwc3: gadget: Fix No Resource after End Transfer
@ 2026-10-21 0:37 ` Thinh Nguyen
2026-10-21 0:37 ` [PATCH 1/7] usb: dwc3: gadget: Reject requests to a disabled endpoint Thinh Nguyen
` (6 more replies)
0 siblings, 7 replies; 9+ messages in thread
From: Thinh Nguyen @ 2026-10-21 0:37 UTC (permalink / raw)
To: Greg Kroah-Hartman, Thinh Nguyen, Wesley Cheng, Michael Grzeschik
Cc: Tejas Narendra Joglekar, linux-usb@vger.kernel.org,
stable@vger.kernel.org, Michael Grzeschik, Selvarasu Ganesan
The dwc3 driver can issue a Start Transfer command while a previous End
Transfer command on the same endpoint has not completed. The controller then
rejects it with "No Resource", and the endpoint stays unusable.
This happens in two cases:
* On ep disable, the End Transfer command is issued without interrupt and its
completion isn't tracked. A quick re-enable or queue to the endpoint can
race with it.
* A timed out End Transfer is treated as done, and the endpoint resource index
is lost.
This series tracks the End Transfer completion on ep disable and on timeout. It
also avoids an unneeded no-op Start Transfer on non-stream endpoints, and
rejects requests queued to an endpoint that is being disabled. If the End
Transfer never completes, the driver recovers through the existing error
recovery, and stale endpoint flags are reset on controller start.
Thanks to Selvarasu for reporting and debugging the issue.
Link: https://lore.kernel.org/linux-usb/20260227121236.963-1-selvarasu.g@samsung.com/
Thinh Nguyen (7):
usb: dwc3: gadget: Reject requests to a disabled endpoint
usb: dwc3: gadget: Track a timed out End Transfer
usb: dwc3: gadget: Clear delayed stop on End Transfer completion
usb: dwc3: gadget: Issue no-op Start Transfer only for stream endpoints
usb: dwc3: gadget: Wait for End Transfer completion on ep disable
usb: dwc3: gadget: Reset endpoint flags on controller start
usb: dwc3: gadget: Recover from End Transfer timeout
drivers/usb/dwc3/core.h | 4 +-
drivers/usb/dwc3/ep0.c | 2 +-
drivers/usb/dwc3/gadget.c | 160 +++++++++++++++++++++++++-------------
3 files changed, 109 insertions(+), 57 deletions(-)
base-commit: bdf12cde30830d46a8ef1ba93986356f1164b4f1
--
2.53.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/7] usb: dwc3: gadget: Reject requests to a disabled endpoint
2026-10-21 0:37 ` [PATCH 0/7] usb: dwc3: gadget: Fix No Resource after End Transfer Thinh Nguyen
@ 2026-10-21 0:37 ` Thinh Nguyen
2026-10-21 0:37 ` [PATCH 2/7] usb: dwc3: gadget: Track a timed out End Transfer Thinh Nguyen
` (5 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Thinh Nguyen @ 2026-10-21 0:37 UTC (permalink / raw)
To: Greg Kroah-Hartman, Thinh Nguyen
Cc: Tejas Narendra Joglekar, linux-usb@vger.kernel.org,
stable@vger.kernel.org, Selvarasu Ganesan
__dwc3_gadget_ep_disable() releases the lock while giving back requests,
and DWC3_EP_ENABLED is only cleared afterward. A function driver can
queue a new request in this window, and the driver would start a
transfer on an endpoint that is already disabled in hardware.
Clear DWC3_EP_ENABLED before giving back the requests, and reject
requests queued to an endpoint that is not enabled.
Fixes: 72246da40f37 ("usb: Introduce DesignWare USB3 DRD Driver")
Cc: stable@vger.kernel.org
Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
---
drivers/usb/dwc3/gadget.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index ee837235630a..eb6666b7bb98 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1084,6 +1084,8 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
reg &= ~DWC3_DALEPENA_EP(dep->number);
dwc3_writel(dwc, DWC3_DALEPENA, reg);
+ dep->flags &= ~DWC3_EP_ENABLED;
+
dwc3_remove_requests(dwc, dep, -ESHUTDOWN);
dep->stream_capable = false;
@@ -1990,7 +1992,8 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
{
struct dwc3 *dwc = dep->dwc;
- if (!dep->endpoint.desc || !dwc->pullups_connected || !dwc->connected) {
+ if (!(dep->flags & DWC3_EP_ENABLED) || !dep->endpoint.desc ||
+ !dwc->pullups_connected || !dwc->connected) {
dev_dbg(dwc->dev, "%s: can't queue to disabled endpoint\n",
dep->name);
return -ESHUTDOWN;
--
2.53.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/7] usb: dwc3: gadget: Track a timed out End Transfer
2026-10-21 0:37 ` [PATCH 0/7] usb: dwc3: gadget: Fix No Resource after End Transfer Thinh Nguyen
2026-10-21 0:37 ` [PATCH 1/7] usb: dwc3: gadget: Reject requests to a disabled endpoint Thinh Nguyen
@ 2026-10-21 0:37 ` Thinh Nguyen
2026-10-21 0:38 ` [PATCH 3/7] usb: dwc3: gadget: Clear delayed stop on End Transfer completion Thinh Nguyen
` (4 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Thinh Nguyen @ 2026-10-21 0:37 UTC (permalink / raw)
To: Greg Kroah-Hartman, Thinh Nguyen, Michael Grzeschik
Cc: Tejas Narendra Joglekar, linux-usb@vger.kernel.org,
stable@vger.kernel.org, Michael Grzeschik, Selvarasu Ganesan
If an End Transfer command with CMDIOC times out, the driver clears the
resource index but keeps DWC3_EP_TRANSFER_STARTED without setting
DWC3_EP_END_TRANSFER_PENDING. The command is still outstanding, but a
later stop issues another End Transfer with resource index 0, and the
next Start Transfer fails with "No Resource".
Mark the timed out End Transfer as pending so that no other command is
issued to the endpoint until it completes. For any other failure, there
is no outstanding command, so clear DWC3_EP_TRANSFER_STARTED.
Fixes: e192cc7b5239 ("usb: dwc3: gadget: move cmd_endtransfer to extra function")
Cc: stable@vger.kernel.org
Reported-by: Selvarasu Ganesan <selvarasu.g@samsung.com>
Closes: https://lore.kernel.org/linux-usb/3fdda532-8181-48e9-b58d-cad7289408e7@samsung.com/
Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
---
drivers/usb/dwc3/gadget.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index eb6666b7bb98..df5407e75788 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1798,9 +1798,9 @@ static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool int
dep->resource_index = 0;
- if (!interrupt)
+ if (!interrupt || (ret && ret != -ETIMEDOUT))
dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
- else if (!ret)
+ else
dep->flags |= DWC3_EP_END_TRANSFER_PENDING;
dep->flags &= ~DWC3_EP_DELAY_STOP;
--
2.53.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 3/7] usb: dwc3: gadget: Clear delayed stop on End Transfer completion
2026-10-21 0:37 ` [PATCH 0/7] usb: dwc3: gadget: Fix No Resource after End Transfer Thinh Nguyen
2026-10-21 0:37 ` [PATCH 1/7] usb: dwc3: gadget: Reject requests to a disabled endpoint Thinh Nguyen
2026-10-21 0:37 ` [PATCH 2/7] usb: dwc3: gadget: Track a timed out End Transfer Thinh Nguyen
@ 2026-10-21 0:38 ` Thinh Nguyen
2026-10-21 0:38 ` [PATCH 4/7] usb: dwc3: gadget: Issue no-op Start Transfer only for stream endpoints Thinh Nguyen
` (3 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Thinh Nguyen @ 2026-10-21 0:38 UTC (permalink / raw)
To: Greg Kroah-Hartman, Thinh Nguyen
Cc: Tejas Narendra Joglekar, linux-usb@vger.kernel.org,
stable@vger.kernel.org, Wesley Cheng, Selvarasu Ganesan
When an End Transfer command times out outside of the SETUP phase, the
driver sets DWC3_EP_DELAY_STOP to retry it on the next SETUP phase. If
the command completes in the meantime, the flag is left set. Requests
queued to the endpoint are then deferred, and the retry may end a
transfer that is started later.
Clear DWC3_EP_DELAY_STOP when the End Transfer command completes.
Fixes: 4db0fbb60136 ("usb: dwc3: gadget: Don't delay End Transfer on delayed_status")
Cc: stable@vger.kernel.org
Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
---
drivers/usb/dwc3/gadget.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index df5407e75788..4de3b81cb678 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -3875,6 +3875,7 @@ static void dwc3_gadget_endpoint_command_complete(struct dwc3_ep *dep,
if (dep->stream_capable)
dep->flags |= DWC3_EP_IGNORE_NEXT_NOSTREAM;
+ dep->flags &= ~DWC3_EP_DELAY_STOP;
dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING;
dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
dwc3_gadget_ep_cleanup_cancelled_requests(dep);
--
2.53.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 4/7] usb: dwc3: gadget: Issue no-op Start Transfer only for stream endpoints
2026-10-21 0:37 ` [PATCH 0/7] usb: dwc3: gadget: Fix No Resource after End Transfer Thinh Nguyen
` (2 preceding siblings ...)
2026-10-21 0:38 ` [PATCH 3/7] usb: dwc3: gadget: Clear delayed stop on End Transfer completion Thinh Nguyen
@ 2026-10-21 0:38 ` Thinh Nguyen
2026-10-21 0:38 ` [PATCH 5/7] usb: dwc3: gadget: Wait for End Transfer completion on ep disable Thinh Nguyen
` (2 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Thinh Nguyen @ 2026-10-21 0:38 UTC (permalink / raw)
To: Greg Kroah-Hartman, Thinh Nguyen
Cc: Tejas Narendra Joglekar, linux-usb@vger.kernel.org,
stable@vger.kernel.org, Selvarasu Ganesan
The function driver may re-enable an endpoint before the End Transfer
command issued on ep disable completes. The no-op Start Transfer issued
on ep enable then fails with "No Resource".
Only stream endpoints need the no-op Start Transfer to initiate a
stream. Other bulk and interrupt endpoints start their transfer when a
request is queued. Skip it for those endpoints, and move it to a helper
to be reused.
Fixes: a97ea994605e ("usb: dwc3: gadget: offset Start Transfer latency for bulk EPs")
Cc: stable@vger.kernel.org
Reported-by: Selvarasu Ganesan <selvarasu.g@samsung.com>
Closes: https://lore.kernel.org/linux-usb/20260227121236.963-1-selvarasu.g@samsung.com/
Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
---
drivers/usb/dwc3/gadget.c | 97 ++++++++++++++++++++-------------------
1 file changed, 50 insertions(+), 47 deletions(-)
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 4de3b81cb678..e68584f20fbd 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -906,6 +906,54 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep)
return 0;
}
+static int dwc3_gadget_ep_start_noop_transfer(struct dwc3_ep *dep)
+{
+ struct dwc3_gadget_ep_cmd_params params;
+ struct dwc3 *dwc = dep->dwc;
+ struct dwc3_trb *trb;
+ dma_addr_t trb_dma;
+ u32 cmd;
+ int ret;
+
+ memset(¶ms, 0, sizeof(params));
+ trb = &dep->trb_pool[0];
+ trb_dma = dwc3_trb_dma_offset(dep, trb);
+
+ params.param0 = upper_32_bits(trb_dma);
+ params.param1 = lower_32_bits(trb_dma);
+
+ cmd = DWC3_DEPCMD_STARTTRANSFER;
+
+ ret = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * For streams, at start, there maybe a race where the host primes the
+ * endpoint before the function driver queues a request to initiate a
+ * stream. In that case, the controller will not see the prime to
+ * generate the ERDY and start stream. To workaround this, issue a
+ * no-op TRB as normal, but end it immediately. As a result, when the
+ * function driver queues the request, the next START_TRANSFER command
+ * will cause the controller to generate an ERDY to initiate the
+ * stream.
+ */
+ dwc3_stop_active_transfer(dep, false, true);
+
+ /*
+ * All stream eps will reinitiate stream on NoStream rejection.
+ *
+ * However, if the controller is capable of TXF_FLUSH_BYPASS, then IN
+ * direction endpoints will automatically restart the stream without
+ * the driver initiation.
+ */
+ if (!dep->direction ||
+ !(dwc->hwparams.hwparams9 & DWC3_GHWPARAMS9_DEV_TXF_FLUSH_BYPASS))
+ dep->flags |= DWC3_EP_FORCE_RESTART_STREAM;
+
+ return 0;
+}
+
/**
* __dwc3_gadget_ep_enable - initializes a hw endpoint
* @dep: endpoint to be initialized
@@ -971,55 +1019,10 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action)
* Issue StartTransfer here with no-op TRB so we can always rely on No
* Response Update Transfer command.
*/
- if (usb_endpoint_xfer_bulk(desc) ||
- usb_endpoint_xfer_int(desc)) {
- struct dwc3_gadget_ep_cmd_params params;
- struct dwc3_trb *trb;
- dma_addr_t trb_dma;
- u32 cmd;
-
- memset(¶ms, 0, sizeof(params));
- trb = &dep->trb_pool[0];
- trb_dma = dwc3_trb_dma_offset(dep, trb);
-
- params.param0 = upper_32_bits(trb_dma);
- params.param1 = lower_32_bits(trb_dma);
-
- cmd = DWC3_DEPCMD_STARTTRANSFER;
-
- ret = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms);
+ if (dep->stream_capable) {
+ ret = dwc3_gadget_ep_start_noop_transfer(dep);
if (ret < 0)
return ret;
-
- if (dep->stream_capable) {
- /*
- * For streams, at start, there maybe a race where the
- * host primes the endpoint before the function driver
- * queues a request to initiate a stream. In that case,
- * the controller will not see the prime to generate the
- * ERDY and start stream. To workaround this, issue a
- * no-op TRB as normal, but end it immediately. As a
- * result, when the function driver queues the request,
- * the next START_TRANSFER command will cause the
- * controller to generate an ERDY to initiate the
- * stream.
- */
- dwc3_stop_active_transfer(dep, false, true);
-
- /*
- * All stream eps will reinitiate stream on NoStream
- * rejection.
- *
- * However, if the controller is capable of
- * TXF_FLUSH_BYPASS, then IN direction endpoints will
- * automatically restart the stream without the driver
- * initiation.
- */
- if (!dep->direction ||
- !(dwc->hwparams.hwparams9 &
- DWC3_GHWPARAMS9_DEV_TXF_FLUSH_BYPASS))
- dep->flags |= DWC3_EP_FORCE_RESTART_STREAM;
- }
}
out:
--
2.53.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 5/7] usb: dwc3: gadget: Wait for End Transfer completion on ep disable
2026-10-21 0:37 ` [PATCH 0/7] usb: dwc3: gadget: Fix No Resource after End Transfer Thinh Nguyen
` (3 preceding siblings ...)
2026-10-21 0:38 ` [PATCH 4/7] usb: dwc3: gadget: Issue no-op Start Transfer only for stream endpoints Thinh Nguyen
@ 2026-10-21 0:38 ` Thinh Nguyen
2026-10-21 0:38 ` [PATCH 6/7] usb: dwc3: gadget: Reset endpoint flags on controller start Thinh Nguyen
2026-10-22 7:05 ` [PATCH 0/7] usb: dwc3: gadget: Fix No Resource after End Transfer Selvarasu Ganesan
6 siblings, 0 replies; 9+ messages in thread
From: Thinh Nguyen @ 2026-10-21 0:38 UTC (permalink / raw)
To: Greg Kroah-Hartman, Thinh Nguyen
Cc: Tejas Narendra Joglekar, linux-usb@vger.kernel.org,
stable@vger.kernel.org, Selvarasu Ganesan
The End Transfer command on ep disable is issued without interrupt, and
the endpoint flags are cleared right after a fixed delay. The command
may not have completed by then. If the function driver re-enables the
endpoint and queues a request, the next Start Transfer fails with "No
Resource".
Issue the End Transfer command with interrupt on ep disable, and keep
DWC3_EP_END_TRANSFER_PENDING and DWC3_EP_TRANSFER_STARTED until the
command completes. Defer the no-op Start Transfer of a stream endpoint
re-enabled in the meantime to the command completion.
Fixes: c5353b225df9 ("usb: dwc3: gadget: don't enable interrupt when disabling endpoint")
Cc: stable@vger.kernel.org
Reported-by: Selvarasu Ganesan <selvarasu.g@samsung.com>
Closes: https://lore.kernel.org/linux-usb/20260227121236.963-1-selvarasu.g@samsung.com/
Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
---
drivers/usb/dwc3/core.h | 4 +++-
drivers/usb/dwc3/ep0.c | 2 +-
drivers/usb/dwc3/gadget.c | 42 ++++++++++++++++++++++++++++++++-------
3 files changed, 39 insertions(+), 9 deletions(-)
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index f3dabb37f806..267c922ca11b 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -771,6 +771,7 @@ struct dwc3_ep {
#define DWC3_EP_TXFIFO_RESIZED BIT(12)
#define DWC3_EP_DELAY_STOP BIT(13)
#define DWC3_EP_RESOURCE_ALLOCATED BIT(14)
+#define DWC3_EP_PENDING_NOOP_START BIT(15)
/* This last one is specific to EP0 */
#define DWC3_EP0_DIR_IN BIT(31)
@@ -1695,7 +1696,8 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd,
int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned int cmd,
u32 param);
void dwc3_gadget_clear_tx_fifos(struct dwc3 *dwc);
-void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep, int status);
+void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep, int status,
+ bool interrupt);
#else
static inline int dwc3_gadget_init(struct dwc3 *dwc)
{ return 0; }
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 46a34c4a046b..cf5a47b71efc 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -315,7 +315,7 @@ void dwc3_ep0_out_start(struct dwc3 *dwc)
if (dwc->connected)
dwc3_stop_active_transfer(dwc3_ep, false, true);
else
- dwc3_remove_requests(dwc, dwc3_ep, -ESHUTDOWN);
+ dwc3_remove_requests(dwc, dwc3_ep, -ESHUTDOWN, false);
}
}
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index e68584f20fbd..e531adc02a40 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1020,9 +1020,14 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action)
* Response Update Transfer command.
*/
if (dep->stream_capable) {
- ret = dwc3_gadget_ep_start_noop_transfer(dep);
- if (ret < 0)
- return ret;
+ if (dep->flags & (DWC3_EP_END_TRANSFER_PENDING |
+ DWC3_EP_DELAY_STOP)) {
+ dep->flags |= DWC3_EP_PENDING_NOOP_START;
+ } else {
+ ret = dwc3_gadget_ep_start_noop_transfer(dep);
+ if (ret < 0)
+ return ret;
+ }
}
out:
@@ -1031,16 +1036,21 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action)
return 0;
}
-void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep, int status)
+void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep, int status,
+ bool interrupt)
{
struct dwc3_request *req;
- dwc3_stop_active_transfer(dep, false, false);
+ dwc3_stop_active_transfer(dep, false, interrupt);
/* If endxfer is delayed, avoid unmapping requests */
if (dep->flags & DWC3_EP_DELAY_STOP)
return;
+ /* Give the controller time to stop accessing the request buffers */
+ if (dep->flags & DWC3_EP_END_TRANSFER_PENDING)
+ mdelay(1);
+
/* - giveback all requests to gadget driver */
while (!list_empty(&dep->started_list)) {
req = next_request(&dep->started_list);
@@ -1089,7 +1099,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
dep->flags &= ~DWC3_EP_ENABLED;
- dwc3_remove_requests(dwc, dep, -ESHUTDOWN);
+ dwc3_remove_requests(dwc, dep, -ESHUTDOWN, true);
dep->stream_capable = false;
dep->type = 0;
@@ -1101,6 +1111,15 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
*/
if (dep->flags & DWC3_EP_DELAY_STOP)
mask |= (DWC3_EP_DELAY_STOP | DWC3_EP_TRANSFER_STARTED);
+
+ /*
+ * The End Transfer command is still in progress. Do not clear the
+ * flags, so that the ep is only rearmed once the command completes.
+ */
+ if (dep->flags & DWC3_EP_END_TRANSFER_PENDING)
+ mask |= (DWC3_EP_END_TRANSFER_PENDING |
+ DWC3_EP_TRANSFER_STARTED);
+
dep->flags &= mask;
/* Clear out the ep descriptors for non-ep0 */
@@ -2553,7 +2572,7 @@ static void dwc3_stop_active_transfers(struct dwc3 *dwc)
if (!dep)
continue;
- dwc3_remove_requests(dwc, dep, -ESHUTDOWN);
+ dwc3_remove_requests(dwc, dep, -ESHUTDOWN, false);
}
}
@@ -3901,7 +3920,16 @@ static void dwc3_gadget_endpoint_command_complete(struct dwc3_ep *dep,
dwc3_ep0_send_delayed_status(dwc);
}
+ if (dep->flags & DWC3_EP_PENDING_NOOP_START) {
+ dep->flags &= ~DWC3_EP_PENDING_NOOP_START;
+
+ if (!(dep->flags & DWC3_EP_DELAY_START) &&
+ (dep->flags & DWC3_EP_ENABLED))
+ dwc3_gadget_ep_start_noop_transfer(dep);
+ }
+
if ((dep->flags & DWC3_EP_DELAY_START) &&
+ (dep->flags & DWC3_EP_ENABLED) &&
!usb_endpoint_xfer_isoc(dep->endpoint.desc))
__dwc3_gadget_kick_transfer(dep);
--
2.53.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 6/7] usb: dwc3: gadget: Reset endpoint flags on controller start
2026-10-21 0:37 ` [PATCH 0/7] usb: dwc3: gadget: Fix No Resource after End Transfer Thinh Nguyen
` (4 preceding siblings ...)
2026-10-21 0:38 ` [PATCH 5/7] usb: dwc3: gadget: Wait for End Transfer completion on ep disable Thinh Nguyen
@ 2026-10-21 0:38 ` Thinh Nguyen
2026-10-22 7:05 ` [PATCH 0/7] usb: dwc3: gadget: Fix No Resource after End Transfer Selvarasu Ganesan
6 siblings, 0 replies; 9+ messages in thread
From: Thinh Nguyen @ 2026-10-21 0:38 UTC (permalink / raw)
To: Greg Kroah-Hartman, Thinh Nguyen, Wesley Cheng
Cc: Tejas Narendra Joglekar, linux-usb@vger.kernel.org,
stable@vger.kernel.org, Selvarasu Ganesan
The flags of a disabled endpoint may be preserved while its End
Transfer command is pending. If the command never completes, the stale
flags persist across a soft disconnect or an error recovery, and the
endpoint can't be used again.
Reset the flags of all non-control endpoints when starting the
controller.
Fixes: 76bff31c7fba ("usb: dwc3: gadget: Do not clear ep delayed stop flag during ep disable")
Cc: stable@vger.kernel.org
Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
---
drivers/usb/dwc3/gadget.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index e531adc02a40..a8f12e583a0f 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2972,6 +2972,7 @@ static int __dwc3_gadget_start(struct dwc3 *dwc)
{
struct dwc3_ep *dep;
int ret = 0;
+ u32 epnum;
u32 reg;
/*
@@ -3029,6 +3030,15 @@ static int __dwc3_gadget_start(struct dwc3 *dwc)
return ret;
}
+ for (epnum = 2; epnum < dwc->num_eps; epnum++) {
+ dep = dwc->eps[epnum];
+ if (!dep)
+ continue;
+
+ dep->flags &= (DWC3_EP_TXFIFO_RESIZED |
+ DWC3_EP_RESOURCE_ALLOCATED);
+ }
+
dep = dwc->eps[0];
dep->flags = 0;
ret = __dwc3_gadget_ep_enable(dep, DWC3_DEPCFG_ACTION_INIT);
--
2.53.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 0/7] usb: dwc3: gadget: Fix No Resource after End Transfer
2026-10-21 0:37 ` [PATCH 0/7] usb: dwc3: gadget: Fix No Resource after End Transfer Thinh Nguyen
` (5 preceding siblings ...)
2026-10-21 0:38 ` [PATCH 6/7] usb: dwc3: gadget: Reset endpoint flags on controller start Thinh Nguyen
@ 2026-10-22 7:05 ` Selvarasu Ganesan
2026-10-26 11:09 ` Akash M/Akash M
6 siblings, 1 reply; 9+ messages in thread
From: Selvarasu Ganesan @ 2026-10-22 7:05 UTC (permalink / raw)
To: Thinh Nguyen, Greg Kroah-Hartman, Wesley Cheng, Michael Grzeschik
Cc: Tejas Narendra Joglekar, linux-usb@vger.kernel.org,
stable@vger.kernel.org, Michael Grzeschik,
alim.akhtar@samsung.com, thiagu.r@samsung.com,
jh0801.jung@samsung.com
On 10/21/2026 6:07 AM, Thinh Nguyen wrote:
> The dwc3 driver can issue a Start Transfer command while a previous End
> Transfer command on the same endpoint has not completed. The controller then
> rejects it with "No Resource", and the endpoint stays unusable.
>
> This happens in two cases:
> * On ep disable, the End Transfer command is issued without interrupt and its
> completion isn't tracked. A quick re-enable or queue to the endpoint can
> race with it.
> * A timed out End Transfer is treated as done, and the endpoint resource index
> is lost.
>
> This series tracks the End Transfer completion on ep disable and on timeout. It
> also avoids an unneeded no-op Start Transfer on non-stream endpoints, and
> rejects requests queued to an endpoint that is being disabled. If the End
> Transfer never completes, the driver recovers through the existing error
> recovery, and stale endpoint flags are reset on controller start.
>
> Thanks to Selvarasu for reporting and debugging the issue.
>
> Link: https://lore.kernel.org/linux-usb/20260227121236.963-1-selvarasu.g@samsung.com/
>
>
>
> Thinh Nguyen (7):
> usb: dwc3: gadget: Reject requests to a disabled endpoint
> usb: dwc3: gadget: Track a timed out End Transfer
> usb: dwc3: gadget: Clear delayed stop on End Transfer completion
> usb: dwc3: gadget: Issue no-op Start Transfer only for stream endpoints
> usb: dwc3: gadget: Wait for End Transfer completion on ep disable
> usb: dwc3: gadget: Reset endpoint flags on controller start
> usb: dwc3: gadget: Recover from End Transfer timeout
>
> drivers/usb/dwc3/core.h | 4 +-
> drivers/usb/dwc3/ep0.c | 2 +-
> drivers/usb/dwc3/gadget.c | 160 +++++++++++++++++++++++++-------------
> 3 files changed, 109 insertions(+), 57 deletions(-)
>
>
> base-commit: bdf12cde30830d46a8ef1ba93986356f1164b4f1
Hi Thinh,
Thanks for sharing the patches. We will test and update.
Thanks,
Selva
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 0/7] usb: dwc3: gadget: Fix No Resource after End Transfer
2026-10-22 7:05 ` [PATCH 0/7] usb: dwc3: gadget: Fix No Resource after End Transfer Selvarasu Ganesan
@ 2026-10-26 11:09 ` Akash M/Akash M
0 siblings, 0 replies; 9+ messages in thread
From: Akash M/Akash M @ 2026-10-26 11:09 UTC (permalink / raw)
To: Selvarasu Ganesan, Thinh Nguyen, Greg Kroah-Hartman, Wesley Cheng,
Michael Grzeschik
Cc: Tejas Narendra Joglekar, linux-usb@vger.kernel.org,
stable@vger.kernel.org, Michael Grzeschik,
alim.akhtar@samsung.com, thiagu.r@samsung.com,
jh0801.jung@samsung.com
On 10/22/2026 12:35 PM, Selvarasu Ganesan wrote:
> On 10/21/2026 6:07 AM, Thinh Nguyen wrote:
>> The dwc3 driver can issue a Start Transfer command while a previous End
>> Transfer command on the same endpoint has not completed. The controller then
>> rejects it with "No Resource", and the endpoint stays unusable.
>>
>> This happens in two cases:
>> * On ep disable, the End Transfer command is issued without interrupt and its
>> completion isn't tracked. A quick re-enable or queue to the endpoint can
>> race with it.
>> * A timed out End Transfer is treated as done, and the endpoint resource index
>> is lost.
>>
>> This series tracks the End Transfer completion on ep disable and on timeout. It
>> also avoids an unneeded no-op Start Transfer on non-stream endpoints, and
>> rejects requests queued to an endpoint that is being disabled. If the End
>> Transfer never completes, the driver recovers through the existing error
>> recovery, and stale endpoint flags are reset on controller start.
>>
>> Thanks to Selvarasu for reporting and debugging the issue.
>>
>> Link: https://lore.kernel.org/linux-usb/20260227121236.963-1-selvarasu.g@samsung.com/
>>
>>
>>
>> Thinh Nguyen (7):
>> usb: dwc3: gadget: Reject requests to a disabled endpoint
>> usb: dwc3: gadget: Track a timed out End Transfer
>> usb: dwc3: gadget: Clear delayed stop on End Transfer completion
>> usb: dwc3: gadget: Issue no-op Start Transfer only for stream endpoints
>> usb: dwc3: gadget: Wait for End Transfer completion on ep disable
>> usb: dwc3: gadget: Reset endpoint flags on controller start
>> usb: dwc3: gadget: Recover from End Transfer timeout
>>
>> drivers/usb/dwc3/core.h | 4 +-
>> drivers/usb/dwc3/ep0.c | 2 +-
>> drivers/usb/dwc3/gadget.c | 160 +++++++++++++++++++++++++-------------
>> 3 files changed, 109 insertions(+), 57 deletions(-)
>>
>>
>> base-commit: bdf12cde30830d46a8ef1ba93986356f1164b4f1
> Hi Thinh,
> Thanks for sharing the patches. We will test and update.
>
> Thanks,
> Selva
Hi Thinh,
We tested the patches on Exynos platforms and observed no issues. Feel
free to add a "Tested-by: Akash M <akash.m5@samsung.com>"
Thanks,
Akash
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-10-27 6:36 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <CGME20261021003845epcas5p4eece85dfc80cdcd3e138c14d5d32ec6c@epcas5p4.samsung.com>
2026-10-21 0:37 ` [PATCH 0/7] usb: dwc3: gadget: Fix No Resource after End Transfer Thinh Nguyen
2026-10-21 0:37 ` [PATCH 1/7] usb: dwc3: gadget: Reject requests to a disabled endpoint Thinh Nguyen
2026-10-21 0:37 ` [PATCH 2/7] usb: dwc3: gadget: Track a timed out End Transfer Thinh Nguyen
2026-10-21 0:38 ` [PATCH 3/7] usb: dwc3: gadget: Clear delayed stop on End Transfer completion Thinh Nguyen
2026-10-21 0:38 ` [PATCH 4/7] usb: dwc3: gadget: Issue no-op Start Transfer only for stream endpoints Thinh Nguyen
2026-10-21 0:38 ` [PATCH 5/7] usb: dwc3: gadget: Wait for End Transfer completion on ep disable Thinh Nguyen
2026-10-21 0:38 ` [PATCH 6/7] usb: dwc3: gadget: Reset endpoint flags on controller start Thinh Nguyen
2026-10-22 7:05 ` [PATCH 0/7] usb: dwc3: gadget: Fix No Resource after End Transfer Selvarasu Ganesan
2026-10-26 11:09 ` Akash M/Akash M
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox