public inbox for stable@vger.kernel.org
 help / color / mirror / Atom feed
From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
To: Selvarasu Ganesan <selvarasu.g@samsung.com>
Cc: Thinh Nguyen <Thinh.Nguyen@synopsys.com>,
	Alan Stern <stern@rowland.harvard.edu>,
	"gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>,
	"linux-usb@vger.kernel.org" <linux-usb@vger.kernel.org>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	"jh0801.jung@samsung.com" <jh0801.jung@samsung.com>,
	"dh10.jung@samsung.com" <dh10.jung@samsung.com>,
	"naushad@samsung.com" <naushad@samsung.com>,
	"akash.m5@samsung.com" <akash.m5@samsung.com>,
	"h10.kim@samsung.com" <h10.kim@samsung.com>,
	"eomji.oh@samsung.com" <eomji.oh@samsung.com>,
	"alim.akhtar@samsung.com" <alim.akhtar@samsung.com>,
	"thiagu.r@samsung.com" <thiagu.r@samsung.com>,
	"stable@vger.kernel.org" <stable@vger.kernel.org>
Subject: Re: [PATCH v2] usb: dwc3: gadget: Prevent EPs resource conflict during StartTransfer
Date: Thu, 26 Feb 2026 18:41:09 +0000	[thread overview]
Message-ID: <20260226184104.sixspftuagwbtukt@synopsys.com> (raw)
In-Reply-To: <264c4448-8e67-4918-8d5d-60b6bba1162f@samsung.com>

On Thu, Feb 26, 2026, Selvarasu Ganesan wrote:
> 
> On 12/12/2025 6:51 AM, Thinh Nguyen wrote:
> > On Thu, Dec 11, 2025, Selvarasu Ganesan wrote:
> >> On 12/5/2025 6:48 AM, Thinh Nguyen wrote:
> >>>> I was hoping that the dwc3_gadget_ep_queue() won't come early to run
> >>>> into this scenario. What I've provided will only mitigate and will not
> >>>> resolve for all cases. It seems adding more checks in dwc3 will be
> >>>> more messy.
> >>
> >> Hi Thinh,
> >>
> >>
> >> Thank you for the insightful comments. I agree that adding more checks
> >> directly in the dwc3 driver would be messy, and a comprehensive rework
> >> of the dwc3 ep disable would ultimately be the cleaner solution.
> >>
> >> In the meantime, Introducing additional checks for
> >> DWC3_EP_TRANSFER_STARTED in dwc3 driver is the most practical way to
> >> unblock the current issue while we work toward that longer‑term fix.
> >> We have applied the patches and performed additional testing, no
> >> regressions or new issues were observed.
> >>
> >> Could you please confirm whether below interim fix is acceptable along
> >> with your proposed earlier patch for unblocking the current development
> >> flow?
> >>
> >>
> >> Patch 2: usb: dwc3: protect dep->flags from concurrent modify in
> >> dwc3_gadget_ep_disable
> >> =======================================================================================
> >>
> >> Subject: [PATCH] usb: dwc3: protect dep->flags from concurrent modify in
> >> dwc3_gadget_ep_disable
> >> The below warnings in `dwc3_gadget_ep_queue` observed during the RNDIS
> >> enable/disable test is caused by a race between `dwc3_gadget_ep_disable`
> >> and `dwc3_gadget_ep_queue`. Both functions manipulate `dep->flags`, and
> >> the lock released temporarily by `dwc3_gadget_giveback` (called from
> >> `dwc3_gadget_ep_disable`) can be acquired by `dwc3_gadget_ep_queue`
> >> before `dwc3_gadget_ep_disable` has finished. This leads to an
> >> inconsistent state of the `DWC3_EP_TRANSFER_STARTED` dep->flag.
> >>
> >> To fix this issue by add a condition check when masking `dep->flags`
> >> in `dwc3_gadget_ep_disable` to ensure the `DWC3_EP_TRANSFER_STARTED`
> >> flag is not cleared when it is actually set. This prevents the spurious
> >> warning and eliminates the race.
> >>
> >> Thread#1:
> >> dwc3_gadget_ep_disable
> >>     ->__dwc3_gadget_ep_disable
> >>      ->dwc3_remove_requests
> >>       ->dwc3_stop_active_transfer
> >>        ->__dwc3_stop_active_transfer
> >>         -> dwc3_send_gadget_ep_cmd (cmd =DWC3_DEPCMD_ENDTRANSFER)
> >>          ->if(!interrupt)dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
> >>           ->dwc3_gadget_giveback
> >>            ->spin_unlock(&dwc->lock)
> >>              ...
> >>              While Thread#1 is still running, Thread#2 starts:
> >>
> >> Thread#2:
> >> usb_ep_queue
> >>     ->dwc3_gadget_ep_queue
> >>      ->__dwc3_gadget_kick_transfer
> >>       -> starting = !(dep->flags & DWC3_EP_TRANSFER_STARTED);
> >>        ->if(starting)
> >>          ->dwc3_send_gadget_ep_cmd (cmd = DWC3_DEPCMD_STARTTRANSFER)
> >>           ->dep->flags |= DWC3_EP_TRANSFER_STARTED;
> >>             ...
> >>              ->__dwc3_gadget_ep_disable
> >>               ->mask = DWC3_EP_TXFIFO_RESIZED |DWC3_EP_RESOURCE_ALLOCATED;
> >>                ->dep->flags &= mask; --> // Possible of clears
> >>                    DWC3_EP_TRANSFER_STARTED flag as well without
> >>                    sending DWC3_DEPCMD_ENDTRANSFER
> >>
> >>    ------------[ cut here ]------------
> >>     dwc3 13200000.dwc3: No resource for ep1in
> >>     WARNING: CPU: 7 PID: 1748 at drivers/usb/dwc3/gadget.c:398
> >> dwc3_send_gadget_ep_cmd+0x2f8/0x76c
> >>     pc : dwc3_send_gadget_ep_cmd+0x2f8/0x76c
> >>     lr : dwc3_send_gadget_ep_cmd+0x2f8/0x76c
> >>     Call trace:
> >>       dwc3_send_gadget_ep_cmd+0x2f8/0x76c
> >>       __dwc3_gadget_kick_transfer+0x2ec/0x3f4
> >>       dwc3_gadget_ep_queue+0x140/0x1f0
> >>       usb_ep_queue+0x60/0xec
> >>       mp_tx_task+0x100/0x134
> >>       mp_tx_timeout+0xd0/0x1e0
> >>       __hrtimer_run_queues+0x130/0x318
> >>       hrtimer_interrupt+0xe8/0x340
> >>       exynos_mct_comp_isr+0x58/0x80
> >>       __handle_irq_event_percpu+0xcc/0x25c
> >>       handle_irq_event+0x40/0x9c
> >>       handle_fasteoi_irq+0x154/0x2c8
> >>       generic_handle_domain_irq+0x58/0x80
> >>       gic_handle_irq+0x48/0x104
> >>       call_on_irq_stack+0x3c/0x50
> >>       do_interrupt_handler+0x4c/0x84
> >>       el1_interrupt+0x34/0x58
> >>       el1h_64_irq_handler+0x18/0x24
> >>       el1h_64_irq+0x68/0x6c
> >>
> >> Change-Id: Ib6a77ce5130e25d0162f72d0e52c845dbb1d18f5
> >> Signed-off-by: Selvarasu Ganesan <selvarasu.g@samsung.com>
> >> ---
> >>    drivers/usb/dwc3/gadget.c | 16 ++++++++++++++++
> >>    1 file changed, 16 insertions(+)
> >>
> >> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
> >> index b42d225b67408..1dc5798072120 100644
> >> --- a/drivers/usb/dwc3/gadget.c
> >> +++ b/drivers/usb/dwc3/gadget.c
> >> @@ -1051,6 +1051,22 @@ 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);
> >> +
> >> +    /*
> >> +     * When dwc3_gadget_ep_disable() calls dwc3_gadget_giveback(),
> >> +     * the  dwc->lock is temporarily released.  If dwc3_gadget_ep_queue()
> >> +     * runs in that window it may set the DWC3_EP_TRANSFER_STARTED flag as
> >> +     * part of dwc3_send_gadget_ep_cmd. The original code cleared the flag
> >> +     * unconditionally, which could overwrite the concurrent modification.
> >> +     *
> >> +     * The added check ensures the DWC3_EP_TRANSFER_STARTED flag is only
> >> +     * cleared if it is not set already, preserving the state updated
> >> by the
> >> +     * concurrent ep_queue path and eliminating the EP resource conflict
> >> +     * warning.
> >> +     */
> > We need to explain the underlining problem here and in the commit
> > message. The function usb_ep_disable() is expected be used interrupt
> > context, and it's being used in interrupt context in the composite
> > framework. There's no wait for flushing of endpoint is handled before
> > usb_ep_disable completes.
> >
> > We are adding a temporary workaround to handle the endpoint
> > reconfiguration and restart before the flushing completed.
> >
> >> +    if (dep->flags & DWC3_EP_TRANSFER_STARTED)
> >> +        mask |= DWC3_EP_TRANSFER_STARTED;
> >> +
> >>        dep->flags &= mask;
> >>
> >>        /* Clear out the ep descriptors for non-ep0 */
> >> -- 
> >>
> >> 2.31.1
> >>
> >>
> > For your case, it may work because the endpoint is probably reconfigured
> > to be the same in usb_ep_enable(). If we reconfigure the endpoint before
> > the endpoint is stopped, the behavior is underfined.
> >
> > You can create the patches and Cc stable. However, I would not add the
> > "Fixes" tag since they (IMHO) are not really fixes. May also need to
> > note that under the "---" in the commit explain why there's no Fixes tag
> > also.
> >
> > Thanks,
> > Thinh
> 
> 
> Hi Thinh,
> 
> This is a followup regarding the temporary workaround patches.
> 
> In v3, I will incorporate the actual underlying issue into the commit 
> message proper, and include a note under the '---' separator explaining 
> why the Fixes tag was not added.
> 
> Please review the updated patches in below and let me know if you have 
> any concerns.
> 
> 
> 
> Subject: [PATCH v3 1/2] usb: dwc3: gadget: Prevent EPs resource conflict
> during StartTransfer
> MIME-Version: 1.0
> Content-Type: text/plain; charset=UTF-8
> Content-Transfer-Encoding: 8bit
> 
> The below “No resource for ep” warning appears when a StartTransfer
> command is issued for bulk or interrupt endpoints in
> `dwc3_gadget_ep_enable` while a previous StartTransfer on the same
> endpoint is still in progress. The gadget functions drivers can invoke
> `usb_ep_enable` (which triggers a new StartTransfer command) before the
> earlier transfer has completed. Because the previous StartTransfer is
> still active, `dwc3_gadget_ep_disable` can skip the required
> `EndTransfer` due to `DWC3_EP_DELAY_STOP`, leading to the endpoint
> resources are busy for previous StartTransfer and warning ("No resource
> for ep") from dwc3 driver.
> 
> The underlying framework issue is that `usb_ep_disable()` is expected to
> complete pending requests before returning, but is allowed to be called
> from interrupt context where sleeping to wait for completion is not
> possible.
> 
> Add a temporary workaround to handle the endpoint reconfiguration and
> restart before the flushing completed. Specifically, a check is added to
> `dwc3_gadget_ep_enable` that checks the `DWC3_EP_TRANSFER_STARTED`
> flag before issuing a new StartTransfer. By preventing a second
> StartTransfer on an already busy endpoint, the resource conflict is
> eliminated, the warning disappears, and potential kernel panics caused
> by `panic_on_warn` are avoided.
> 
> ------------[ cut here ]------------
> dwc3 13200000.dwc3: No resource for ep1out
> WARNING: CPU: 0 PID: 700 at drivers/usb/dwc3/gadget.c:398 
> dwc3_send_gadget_ep_cmd+0x2f8/0x76c
> Call trace:
> dwc3_send_gadget_ep_cmd+0x2f8/0x76c
> __dwc3_gadget_ep_enable+0x490/0x7c0
> dwc3_gadget_ep_enable+0x6c/0xe4
> usb_ep_enable+0x5c/0x15c
> mp_eth_stop+0xd4/0x11c
> __dev_close_many+0x160/0x1c8
> __dev_change_flags+0xfc/0x220
> dev_change_flags+0x24/0x70
> devinet_ioctl+0x434/0x524
> inet_ioctl+0xa8/0x224
> sock_do_ioctl+0x74/0x128
> sock_ioctl+0x3bc/0x468
> __arm64_sys_ioctl+0xa8/0xe4
> invoke_syscall+0x58/0x10c
> el0_svc_common+0xa8/0xdc
> do_el0_svc+0x1c/0x28
> el0_svc+0x38/0x88
> el0t_64_sync_handler+0x70/0xbc
> el0t_64_sync+0x1a8/0x1ac
> 
> Cc: stable@vger.kernel.org
> Signed-off-by: Selvarasu Ganesan <selvarasu.g@samsung.com>
> ---
> 
> Note: No Fixes tag is added because this is a workaround for the
> gadget framework issue where the gadget framework calls usb_ep_disable()
> in interrupt context without ensuring endpoint flushing completes.
> A proper fix requires refactoring the framework to make sure
> usb_ep_disable is invoked in process context.
> ---
> drivers/usb/dwc3/gadget.c | 5 +++--
> 1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
> index 502d54ce13bc..949a9e6b176a 100644
> --- a/drivers/usb/dwc3/gadget.c
> +++ b/drivers/usb/dwc3/gadget.c
> @@ -951,8 +951,9 @@ 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)) {
> + if ((usb_endpoint_xfer_bulk(desc) ||
> + usb_endpoint_xfer_int(desc)) &&
> + !(dep->flags & DWC3_EP_TRANSFER_STARTED)) {
> struct dwc3_gadget_ep_cmd_params params;
> struct dwc3_trb *trb;
> dma_addr_t trb_dma;
> --
> 2.34.1
> 
> 
> 
> Subject: [PATCH v3 2/2] usb: dwc3: gadget: Protect endpoint flags during
>   concurrent ep disable and queue
> 
> A race condition exists between dwc3_gadget_ep_disable() and
> dwc3_gadget_ep_queue() when manipulating dep->flags. The underlying
> framework issue is that usb_ep_disable() is expected be used interrupt
> context, and it's being used in interrupt context in the composite
> framework. There's no wait for flushing of endpoint is handled before
> usb_ep_disable completes.
> 
> In the race scenario: when dwc3_gadget_ep_disable() calls
> dwc3_gadget_giveback(), the dwc->lock is temporarily released. If
> dwc3_gadget_ep_queue() runs in that window, it set the
> DWC3_EP_TRANSFER_STARTED flag via dwc3_send_gadget_ep_cmd(). When
> ep_disable resumes, it unconditionally clears all flags except those
> explicitly masked, potentially clearing DWC3_EP_TRANSFER_STARTED even
> though a new transfer has started. This leads to "No resource ep"
> warnings on subsequent StartTransfer attempts.
> 
> As a temporary workaround for the framework limitation, add a condition
> check when masking `dep->flags` in `dwc3_gadget_ep_disable` to ensure
> the `DWC3_EP_TRANSFER_STARTED` flag is not cleared when it is actually
> set. This prevents the spurious warning and eliminates the race.
> 
> Cc: stable@vger.kernel.org
> Signed-off-by: Selvarasu Ganesan <selvarasu.g@samsung.com>
> ---
> 
> Note: No Fixes tag is added because this is a workaround for the
> gadget framework issue where the gadget framework calls usb_ep_disable()
> in interrupt context without ensuring endpoint flushing completes.
> A proper fix requires refactoring the framework to make sure
> usb_ep_disable is invoked in process context.
> ---
>   drivers/usb/dwc3/gadget.c | 17 +++++++++++++++++
>   1 file changed, 17 insertions(+)
> 
> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
> index 949a9e6b176a..1b16d103d94e 100644
> --- a/drivers/usb/dwc3/gadget.c
> +++ b/drivers/usb/dwc3/gadget.c
> @@ -1078,6 +1078,23 @@ 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);
> +
> +       /*
> +        * When dwc3_gadget_ep_disable() calls dwc3_gadget_giveback(),
> +        * the dwc->lock is temporarily released. If dwc3_gadget_ep_queue()
> +        * runs in that window it may set the DWC3_EP_TRANSFER_STARTED 
> flag as
> +        * part of dwc3_send_gadget_ep_cmd. The original code cleared 
> the flag
> +        * unconditionally in the mask operation, which could overwrite the
> +        * concurrent modification.
> +        *
> +        * As a workaround for the interrupt context constraint where we 
> cannot
> +        * wait for endpoint flushing, preserve the DWC3_EP_TRANSFER_STARTED
> +        * flag if it is set, avoiding resource conflicts until the 
> framework
> +        * is fixed to properly synchronize endpoint lifecycle management.
> +        */
> +       if (dep->flags & DWC3_EP_TRANSFER_STARTED)
> +               mask |= DWC3_EP_TRANSFER_STARTED;
> +
>          dep->flags &= mask;
> 
>          /* Clear out the ep descriptors for non-ep0 */
> --
> 2.34.1
> 
> 

I think these 2 patches should be combined together into a single patch,
and it looks good to me.

Thanks,
Thinh

  reply	other threads:[~2026-02-26 18:41 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <CGME20251117160057epcas5p324eddf1866146216495186a50bcd3c01@epcas5p3.samsung.com>
2025-11-17 15:59 ` [PATCH v2] usb: dwc3: gadget: Prevent EPs resource conflict during StartTransfer Selvarasu Ganesan
2025-11-18  2:21   ` Thinh Nguyen
2025-11-18  3:58     ` Selvarasu Ganesan
2025-11-19  1:56       ` Thinh Nguyen
2025-11-18  4:20     ` Alan Stern
2025-11-19  1:49       ` Thinh Nguyen
2025-11-19  4:09         ` Alan Stern
2025-11-20  2:07           ` Thinh Nguyen
2025-11-20  3:33             ` Alan Stern
2025-11-21  2:22               ` Thinh Nguyen
2025-11-21  3:08                 ` Alan Stern
2025-12-03  5:25                   ` Selvarasu Ganesan
2025-12-04  1:51                     ` Thinh Nguyen
2025-12-04 13:15                       ` Selvarasu Ganesan
2025-12-05  0:37                         ` Thinh Nguyen
2025-12-05  1:18                           ` Thinh Nguyen
2025-12-05  1:19                             ` Thinh Nguyen
2025-12-11 10:38                             ` Selvarasu Ganesan
2025-12-12  1:21                               ` Thinh Nguyen
2026-02-26 10:59                                 ` Selvarasu Ganesan
2026-02-26 18:41                                   ` Thinh Nguyen [this message]
2026-03-02  5:56                                     ` Selvarasu Ganesan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260226184104.sixspftuagwbtukt@synopsys.com \
    --to=thinh.nguyen@synopsys.com \
    --cc=akash.m5@samsung.com \
    --cc=alim.akhtar@samsung.com \
    --cc=dh10.jung@samsung.com \
    --cc=eomji.oh@samsung.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=h10.kim@samsung.com \
    --cc=jh0801.jung@samsung.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=naushad@samsung.com \
    --cc=selvarasu.g@samsung.com \
    --cc=stable@vger.kernel.org \
    --cc=stern@rowland.harvard.edu \
    --cc=thiagu.r@samsung.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox