Re: [PATCH v3] usb: dwc3: gadget: Prevent EP resource conflicts during StartTransfer
From: Selvarasu Ganesan
Date: Thu Oct 08 2026 - 00:38:09 EST
On 10/8/2026 5:29 AM, Thinh Nguyen wrote:
> On Wed, Oct 07, 2026, Selvarasu Ganesan wrote:
>> Sorry for the format issue. The updated answers as below,
>>
>> No, the endpoint completion event is not seen after the -ETIMEDOUT error.
>>
>> The proposed fix works well for the __dwc3_gadget_ep_set_halt sequence,
>> where DWC3_EP_END_TRANSFER_PENDING must be set to prevent dwc3_ep_queue
>> from starting a new transfer during a EP transfer timeout.
>>
>> But, this is unnecessary for __dwc3_gadget_ep_disable. Since there's no
>> way to clear the pending flag if the interrupt is missed and no
>> dwc3_ep_queue calls occur until the EP is re-enabled, preserving
>> DWC3_EP_END_TRANSFER_PENDING here provides no benefit.
>>
>> So, the below changes is not necessary in ep disable,
>>
> We still need to keep DWC3_EP_END_TRANSFER_PENDING in ep_disable. That's
> for the normal case where the End Transfer completes after ep_disable
> returns, which is the original issue. If the command never completes,
> the endpoint resource is stuck regardless. Clearing the flag only lead
> to a NO_RESOURCE error later.
Agreed.
>
> As for the dwc3_gadget_ep_queue() race during giveback, keeping
> DWC3_EP_TRANSFER_STARTED isn't right. We should reject the queue when
> the endpoint is disabled. This should be a separate patch:
Agreed.
>
> 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;
>
Thanks for suggestion. We will test this patch to confirm no resource
issue in race condition.
> The End Transfer command not completing is also a separate issue. I
> asked you to check whether the command would eventually complete with
> the additional code, and it appears it doesn't.
We have confirmed that the completion event is never seen, once the
timeout occurs for end transfer. It appears the command is indeed
hanging in the hardware, as you suspected.
>
> Can you provide some more info on your setup:
> * IP and version
> * connected speed
> * endpoint direction (is it always OUT?)
> * Is there any active transfer
> * tracepoints
* IP and version : 0xc120: 0x33313130
* connected speed : HS mode
* endpoint direction (is it always OUT?) : Yes its always OUT
* Is there any active transfer : No, There is evidences from the log to
say there is a active transfer.
* tracepoints: There is no dwc3 traces for this issue as of now due to
its low reproduction rate in the customer's setup.
Thanks,
Selva
> Thanks,
> Thinh