The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH 1/1] usb: dwc3: gadget: fix IRQ storm on invalid event buffer count
@ 2026-07-27  9:40 Jiazi Liu
  2026-08-04 23:04 ` Thinh Nguyen
  2026-08-06  9:03 ` kernel test robot
  0 siblings, 2 replies; 5+ messages in thread
From: Jiazi Liu @ 2026-07-27  9:40 UTC (permalink / raw)
  To: Thinh.Nguyen; +Cc: gregkh, linux-usb, linux-kernel, stable, Jiazi Liu

When dwc3_check_event_buf() reads a GEVNTCOUNT value exceeding the
event buffer length, commit 63ccd26cd1f6 ("usb: dwc3: gadget: check
that event count does not exceed event buffer length") returns IRQ_NONE
without writing back GEVNTCOUNT. Since the DWC3 interrupt is
level-triggered, the uncleared IRQ source keeps the line asserted,
causing a tight IRQ storm that accumulates 99,900 unhandled interrupts
and triggers spurious.c:184 BUG -> kernel panic.

The resulting call stack:
  __report_bad_irq+0xac/0xc8
  note_interrupt+0x340/0x468
  handle_irq_event+0xac/0xc0
  handle_fasteoi_irq+0x120/0x228
  gic_handle_irq+0x68/0x108
  ...
  kernel BUG at kernel/irq/spurious.c:184

To reproduce, write a bogus value exceeding the event buffer length
directly to the GEVNTCOUNT register:

  devmem <DWC3_BASE + 0xc40c> 4 0x1004

Write the bogus count back to GEVNTCOUNT to clear the IRQ source,
consistent with the stale event clearing pattern in
dwc3_event_buffers_setup(), and schedule a soft disconnect via
softcon_work to recover the controller state.

Fixes: 63ccd26cd1f6 ("usb: dwc3: gadget: check that event count does not exceed event buffer length")
Cc: stable@vger.kernel.org
Signed-off-by: Jiazi Liu <liujiazi@amazon.com>
---
 drivers/usb/dwc3/core.h   |  2 ++
 drivers/usb/dwc3/gadget.c | 23 ++++++++++++++++++++++-
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 608daeb7ef10..0881ed7e956e 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -1004,6 +1004,7 @@ struct dwc3_glue_ops {
 /**
  * struct dwc3 - representation of our controller
  * @drd_work: workqueue used for role swapping
+ * @softcon_work: workqueue used for soft connect/disconnect recovery
  * @ep0_trb: trb which is used for the ctrl_req
  * @bounce: address of bounce buffer
  * @setup_buf: used while precessing STD USB requests
@@ -1189,6 +1190,7 @@ struct dwc3_glue_ops {
  */
 struct dwc3 {
 	struct work_struct	drd_work;
+	struct work_struct	softcon_work;
 	struct dwc3_trb		*ep0_trb;
 	void			*bounce;
 	u8			*setup_buf;
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index fa0f16ffafef..9b24259272a4 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -4669,7 +4669,18 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt)
 	if (count > evt->length) {
 		dev_err_ratelimited(dwc->dev, "invalid count(%u) > evt->length(%u)\n",
 			count, evt->length);
-		return IRQ_NONE;
+		/*
+		 * The DWC3 interrupt is level-triggered. Returning IRQ_NONE
+		 * without clearing the IRQ source leaves the line asserted,
+		 * causing a tight IRQ storm that triggers spurious.c:184 BUG.
+		 * Write the bogus count back to GEVNTCOUNT to clear the source,
+		 * consistent with the stale event clearing in
+		 * dwc3_event_buffers_setup(), then schedule a soft disconnect
+		 * to recover the controller state.
+		 */
+		dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), count);
+		schedule_work(&dwc->softcon_work);
+		return IRQ_HANDLED;
 	}
 
 	evt->count = count;
@@ -4729,6 +4740,14 @@ static void dwc_gadget_release(struct device *dev)
 	kfree(gadget);
 }
 
+static void dwc3_softcon_work(struct work_struct *work)
+{
+	struct dwc3 *dwc = container_of(work, struct dwc3, softcon_work);
+
+	dev_err(dwc->dev, "event buffer error: performing soft disconnect\n");
+	dwc3_gadget_soft_disconnect(dwc);
+}
+
 /**
  * dwc3_gadget_init - initializes gadget related registers
  * @dwc: pointer to our controller context structure
@@ -4772,6 +4791,7 @@ int dwc3_gadget_init(struct dwc3 *dwc)
 	}
 
 	init_completion(&dwc->ep0_in_setup);
+	INIT_WORK(&dwc->softcon_work, dwc3_softcon_work);
 	dwc->gadget = kzalloc_obj(struct usb_gadget);
 	if (!dwc->gadget) {
 		ret = -ENOMEM;
@@ -4868,6 +4888,7 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
 	if (!dwc->gadget)
 		return;
 
+	cancel_work_sync(&dwc->softcon_work);
 	dwc3_enable_susphy(dwc, true);
 	usb_del_gadget(dwc->gadget);
 	dwc3_gadget_free_endpoints(dwc);
-- 
2.50.1 (Apple Git-155)


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/1] usb: dwc3: gadget: fix IRQ storm on invalid event buffer count
  2026-07-27  9:40 [PATCH 1/1] usb: dwc3: gadget: fix IRQ storm on invalid event buffer count Jiazi Liu
@ 2026-08-04 23:04 ` Thinh Nguyen
  2026-08-06  9:03 ` kernel test robot
  1 sibling, 0 replies; 5+ messages in thread
From: Thinh Nguyen @ 2026-08-04 23:04 UTC (permalink / raw)
  To: Jiazi Liu
  Cc: Thinh Nguyen, gregkh@linuxfoundation.org,
	linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org,
	stable@vger.kernel.org, Jiazi Liu

On Mon, Jul 27, 2026, Jiazi Liu wrote:
> When dwc3_check_event_buf() reads a GEVNTCOUNT value exceeding the
> event buffer length, commit 63ccd26cd1f6 ("usb: dwc3: gadget: check
> that event count does not exceed event buffer length") returns IRQ_NONE
> without writing back GEVNTCOUNT. Since the DWC3 interrupt is
> level-triggered, the uncleared IRQ source keeps the line asserted,
> causing a tight IRQ storm that accumulates 99,900 unhandled interrupts
> and triggers spurious.c:184 BUG -> kernel panic.
> 
> The resulting call stack:
>   __report_bad_irq+0xac/0xc8
>   note_interrupt+0x340/0x468
>   handle_irq_event+0xac/0xc0
>   handle_fasteoi_irq+0x120/0x228
>   gic_handle_irq+0x68/0x108
>   ...
>   kernel BUG at kernel/irq/spurious.c:184
> 
> To reproduce, write a bogus value exceeding the event buffer length
> directly to the GEVNTCOUNT register:
> 
>   devmem <DWC3_BASE + 0xc40c> 4 0x1004
> 
> Write the bogus count back to GEVNTCOUNT to clear the IRQ source,
> consistent with the stale event clearing pattern in
> dwc3_event_buffers_setup(), and schedule a soft disconnect via
> softcon_work to recover the controller state.
> 
> Fixes: 63ccd26cd1f6 ("usb: dwc3: gadget: check that event count does not exceed event buffer length")
> Cc: stable@vger.kernel.org
> Signed-off-by: Jiazi Liu <liujiazi@amazon.com>
> ---
>  drivers/usb/dwc3/core.h   |  2 ++
>  drivers/usb/dwc3/gadget.c | 23 ++++++++++++++++++++++-
>  2 files changed, 24 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> index 608daeb7ef10..0881ed7e956e 100644
> --- a/drivers/usb/dwc3/core.h
> +++ b/drivers/usb/dwc3/core.h
> @@ -1004,6 +1004,7 @@ struct dwc3_glue_ops {
>  /**
>   * struct dwc3 - representation of our controller
>   * @drd_work: workqueue used for role swapping
> + * @softcon_work: workqueue used for soft connect/disconnect recovery

Rename this to err_recovery_work and update the description.

>   * @ep0_trb: trb which is used for the ctrl_req
>   * @bounce: address of bounce buffer
>   * @setup_buf: used while precessing STD USB requests
> @@ -1189,6 +1190,7 @@ struct dwc3_glue_ops {
>   */
>  struct dwc3 {
>  	struct work_struct	drd_work;
> +	struct work_struct	softcon_work;
>  	struct dwc3_trb		*ep0_trb;
>  	void			*bounce;
>  	u8			*setup_buf;
> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
> index fa0f16ffafef..9b24259272a4 100644
> --- a/drivers/usb/dwc3/gadget.c
> +++ b/drivers/usb/dwc3/gadget.c
> @@ -4669,7 +4669,18 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt)
>  	if (count > evt->length) {
>  		dev_err_ratelimited(dwc->dev, "invalid count(%u) > evt->length(%u)\n",
>  			count, evt->length);

We probably no longer need the dev_err to be ratelimited.

> -		return IRQ_NONE;
> +		/*
> +		 * The DWC3 interrupt is level-triggered. Returning IRQ_NONE

This comment is out of context now that it's no longer IRQ_NONE. Most of
the details here are only relevant if we return IRQ_NONE. What we need
to document here why this is a fatal error and require reinitializing
the controller. Document that the driver and the controller are out of
sync to which event is consumed.

> +		 * without clearing the IRQ source leaves the line asserted,
> +		 * causing a tight IRQ storm that triggers spurious.c:184 BUG.
> +		 * Write the bogus count back to GEVNTCOUNT to clear the source,
> +		 * consistent with the stale event clearing in
> +		 * dwc3_event_buffers_setup(), then schedule a soft disconnect
> +		 * to recover the controller state.
> +		 */
> +		dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), count);
> +		schedule_work(&dwc->softcon_work);
> +		return IRQ_HANDLED;
>  	}
>  
>  	evt->count = count;
> @@ -4729,6 +4740,14 @@ static void dwc_gadget_release(struct device *dev)
>  	kfree(gadget);
>  }
>  
> +static void dwc3_softcon_work(struct work_struct *work)
> +{
> +	struct dwc3 *dwc = container_of(work, struct dwc3, softcon_work);
> +
> +	dev_err(dwc->dev, "event buffer error: performing soft disconnect\n");

Remove this dev_err(). The error message should be at the caller where
the specific failure condition is known, not the generic work handler.

> +	dwc3_gadget_soft_disconnect(dwc);

Check and follow the dwc3_gadget_suspend() and dwc3_gadget_resume()
logic for soft-disconnect and soft-connect to make sure the internal
states are updated and notify the gadget drivers correctly.

Perhaps you can also recover with soft-connect after soft-disconnect.

> +}
> +
>  /**
>   * dwc3_gadget_init - initializes gadget related registers
>   * @dwc: pointer to our controller context structure
> @@ -4772,6 +4791,7 @@ int dwc3_gadget_init(struct dwc3 *dwc)
>  	}
>  
>  	init_completion(&dwc->ep0_in_setup);
> +	INIT_WORK(&dwc->softcon_work, dwc3_softcon_work);
>  	dwc->gadget = kzalloc_obj(struct usb_gadget);
>  	if (!dwc->gadget) {
>  		ret = -ENOMEM;
> @@ -4868,6 +4888,7 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
>  	if (!dwc->gadget)
>  		return;
>  
> +	cancel_work_sync(&dwc->softcon_work);
>  	dwc3_enable_susphy(dwc, true);
>  	usb_del_gadget(dwc->gadget);
>  	dwc3_gadget_free_endpoints(dwc);
> -- 
> 2.50.1 (Apple Git-155)
> 

Thanks,
Thinh

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/1] usb: dwc3: gadget: fix IRQ storm on invalid event buffer count
  2026-07-27  9:40 [PATCH 1/1] usb: dwc3: gadget: fix IRQ storm on invalid event buffer count Jiazi Liu
  2026-08-04 23:04 ` Thinh Nguyen
@ 2026-08-06  9:03 ` kernel test robot
  2026-08-07 11:04   ` Liu Jiazi
  1 sibling, 1 reply; 5+ messages in thread
From: kernel test robot @ 2026-08-06  9:03 UTC (permalink / raw)
  To: Jiazi Liu, Thinh.Nguyen
  Cc: oe-kbuild-all, gregkh, linux-usb, linux-kernel, stable, Jiazi Liu

Hi Jiazi,

kernel test robot noticed the following build warnings:

[auto build test WARNING on usb/usb-testing]
[also build test WARNING on usb/usb-next usb/usb-linus linus/master v7.2-rc6 next-20260805]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Jiazi-Liu/usb-dwc3-gadget-fix-IRQ-storm-on-invalid-event-buffer-count/20260806-005046
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git usb-testing
patch link:    https://lore.kernel.org/r/20260727094015.5101-1-liujiazi%40amazon.com
patch subject: [PATCH 1/1] usb: dwc3: gadget: fix IRQ storm on invalid event buffer count
config: i386-randconfig-r132-20260806 (https://download.01.org/0day-ci/archive/20260806/202608061759.sIcC6h4C-lkp@intel.com/config)
compiler: gcc-13 (Debian 13.3.0-16) 13.3.0
sparse: v0.6.5-rc1
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260806/202608061759.sIcC6h4C-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202608061759.sIcC6h4C-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> drivers/usb/dwc3/gadget.c:4681:32: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct dwc3 *dwc @@     got void [noderef] __iomem *regs @@
   drivers/usb/dwc3/gadget.c:4681:32: sparse:     expected struct dwc3 *dwc
   drivers/usb/dwc3/gadget.c:4681:32: sparse:     got void [noderef] __iomem *regs

vim +4681 drivers/usb/dwc3/gadget.c

  4636	
  4637	static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt)
  4638	{
  4639		struct dwc3 *dwc = evt->dwc;
  4640		u32 amount;
  4641		u32 count;
  4642	
  4643		if (pm_runtime_suspended(dwc->dev)) {
  4644			dwc->pending_events = true;
  4645			/*
  4646			 * Trigger runtime resume. The get() function will be balanced
  4647			 * after processing the pending events in dwc3_process_pending
  4648			 * events().
  4649			 */
  4650			pm_runtime_get(dwc->dev);
  4651			disable_irq_nosync(dwc->irq_gadget);
  4652			return IRQ_HANDLED;
  4653		}
  4654	
  4655		/*
  4656		 * With PCIe legacy interrupt, test shows that top-half irq handler can
  4657		 * be called again after HW interrupt deassertion. Check if bottom-half
  4658		 * irq event handler completes before caching new event to prevent
  4659		 * losing events.
  4660		 */
  4661		if (evt->flags & DWC3_EVENT_PENDING)
  4662			return IRQ_HANDLED;
  4663	
  4664		count = dwc3_readl(dwc, DWC3_GEVNTCOUNT(0));
  4665		count &= DWC3_GEVNTCOUNT_MASK;
  4666		if (!count)
  4667			return IRQ_NONE;
  4668	
  4669		if (count > evt->length) {
  4670			dev_err_ratelimited(dwc->dev, "invalid count(%u) > evt->length(%u)\n",
  4671				count, evt->length);
  4672			/*
  4673			 * The DWC3 interrupt is level-triggered. Returning IRQ_NONE
  4674			 * without clearing the IRQ source leaves the line asserted,
  4675			 * causing a tight IRQ storm that triggers spurious.c:184 BUG.
  4676			 * Write the bogus count back to GEVNTCOUNT to clear the source,
  4677			 * consistent with the stale event clearing in
  4678			 * dwc3_event_buffers_setup(), then schedule a soft disconnect
  4679			 * to recover the controller state.
  4680			 */
> 4681			dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), count);
  4682			schedule_work(&dwc->softcon_work);
  4683			return IRQ_HANDLED;
  4684		}
  4685	
  4686		evt->count = count;
  4687		evt->flags |= DWC3_EVENT_PENDING;
  4688	
  4689		/* Mask interrupt */
  4690		dwc3_writel(dwc, DWC3_GEVNTSIZ(0),
  4691			    DWC3_GEVNTSIZ_INTMASK | DWC3_GEVNTSIZ_SIZE(evt->length));
  4692	
  4693		amount = min(count, evt->length - evt->lpos);
  4694		memcpy(evt->cache + evt->lpos, evt->buf + evt->lpos, amount);
  4695	
  4696		if (amount < count)
  4697			memcpy(evt->cache, evt->buf, count - amount);
  4698	
  4699		dwc3_writel(dwc, DWC3_GEVNTCOUNT(0), count);
  4700	
  4701		return IRQ_WAKE_THREAD;
  4702	}
  4703	

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/1] usb: dwc3: gadget: fix IRQ storm on invalid event buffer count
  2026-08-06  9:03 ` kernel test robot
@ 2026-08-07 11:04   ` Liu Jiazi
  2026-08-07 23:09     ` Thinh Nguyen
  0 siblings, 1 reply; 5+ messages in thread
From: Liu Jiazi @ 2026-08-07 11:04 UTC (permalink / raw)
  To: kernel test robot
  Cc: Thinh.Nguyen, oe-kbuild-all, gregkh, linux-usb, linux-kernel,
	stable, Jiazi Liu

Hi @Thinh.Nguyen@synopsys.com

Thanks for the review suggestions. I've updated the patch accordingly.
On thing I'd like to discuss: in dwc3_err_recovery_work(), after
soft_disconnect succeeds, should we attempt soft_connect to
recover the controller, or just leave it disconnected and let the
upper layer (e.g. function driver like ADB) handle reconnection
on its own?

In my testing, calling soft_connect after soft_disconnect triggers an
RCU stall. Simply doing soft_disconnect and notifying the
gadget driver via dwc3_disconnect_gadget_sleepable() is sufficient —
ADB recovers on its own after that.
What's your recommendation here?

Brs
Jiazi

kernel test robot <lkp@intel.com> 于2026年8月6日周四 17:03写道:
>
> Hi Jiazi,
>
> kernel test robot noticed the following build warnings:
>
> [auto build test WARNING on usb/usb-testing]
> [also build test WARNING on usb/usb-next usb/usb-linus linus/master v7.2-rc6 next-20260805]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use '--base' as documented in
> https://git-scm.com/docs/git-format-patch#_base_tree_information]
>
> url:    https://github.com/intel-lab-lkp/linux/commits/Jiazi-Liu/usb-dwc3-gadget-fix-IRQ-storm-on-invalid-event-buffer-count/20260806-005046
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git usb-testing
> patch link:    https://lore.kernel.org/r/20260727094015.5101-1-liujiazi%40amazon.com
> patch subject: [PATCH 1/1] usb: dwc3: gadget: fix IRQ storm on invalid event buffer count
> config: i386-randconfig-r132-20260806 (https://download.01.org/0day-ci/archive/20260806/202608061759.sIcC6h4C-lkp@intel.com/config)
> compiler: gcc-13 (Debian 13.3.0-16) 13.3.0
> sparse: v0.6.5-rc1
> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260806/202608061759.sIcC6h4C-lkp@intel.com/reproduce)
>
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <lkp@intel.com>
> | Closes: https://lore.kernel.org/oe-kbuild-all/202608061759.sIcC6h4C-lkp@intel.com/
>
> sparse warnings: (new ones prefixed by >>)
> >> drivers/usb/dwc3/gadget.c:4681:32: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct dwc3 *dwc @@     got void [noderef] __iomem *regs @@
>    drivers/usb/dwc3/gadget.c:4681:32: sparse:     expected struct dwc3 *dwc
>    drivers/usb/dwc3/gadget.c:4681:32: sparse:     got void [noderef] __iomem *regs
>
> vim +4681 drivers/usb/dwc3/gadget.c
>
>   4636
>   4637  static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt)
>   4638  {
>   4639          struct dwc3 *dwc = evt->dwc;
>   4640          u32 amount;
>   4641          u32 count;
>   4642
>   4643          if (pm_runtime_suspended(dwc->dev)) {
>   4644                  dwc->pending_events = true;
>   4645                  /*
>   4646                   * Trigger runtime resume. The get() function will be balanced
>   4647                   * after processing the pending events in dwc3_process_pending
>   4648                   * events().
>   4649                   */
>   4650                  pm_runtime_get(dwc->dev);
>   4651                  disable_irq_nosync(dwc->irq_gadget);
>   4652                  return IRQ_HANDLED;
>   4653          }
>   4654
>   4655          /*
>   4656           * With PCIe legacy interrupt, test shows that top-half irq handler can
>   4657           * be called again after HW interrupt deassertion. Check if bottom-half
>   4658           * irq event handler completes before caching new event to prevent
>   4659           * losing events.
>   4660           */
>   4661          if (evt->flags & DWC3_EVENT_PENDING)
>   4662                  return IRQ_HANDLED;
>   4663
>   4664          count = dwc3_readl(dwc, DWC3_GEVNTCOUNT(0));
>   4665          count &= DWC3_GEVNTCOUNT_MASK;
>   4666          if (!count)
>   4667                  return IRQ_NONE;
>   4668
>   4669          if (count > evt->length) {
>   4670                  dev_err_ratelimited(dwc->dev, "invalid count(%u) > evt->length(%u)\n",
>   4671                          count, evt->length);
>   4672                  /*
>   4673                   * The DWC3 interrupt is level-triggered. Returning IRQ_NONE
>   4674                   * without clearing the IRQ source leaves the line asserted,
>   4675                   * causing a tight IRQ storm that triggers spurious.c:184 BUG.
>   4676                   * Write the bogus count back to GEVNTCOUNT to clear the source,
>   4677                   * consistent with the stale event clearing in
>   4678                   * dwc3_event_buffers_setup(), then schedule a soft disconnect
>   4679                   * to recover the controller state.
>   4680                   */
> > 4681                  dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), count);
>   4682                  schedule_work(&dwc->softcon_work);
>   4683                  return IRQ_HANDLED;
>   4684          }
>   4685
>   4686          evt->count = count;
>   4687          evt->flags |= DWC3_EVENT_PENDING;
>   4688
>   4689          /* Mask interrupt */
>   4690          dwc3_writel(dwc, DWC3_GEVNTSIZ(0),
>   4691                      DWC3_GEVNTSIZ_INTMASK | DWC3_GEVNTSIZ_SIZE(evt->length));
>   4692
>   4693          amount = min(count, evt->length - evt->lpos);
>   4694          memcpy(evt->cache + evt->lpos, evt->buf + evt->lpos, amount);
>   4695
>   4696          if (amount < count)
>   4697                  memcpy(evt->cache, evt->buf, count - amount);
>   4698
>   4699          dwc3_writel(dwc, DWC3_GEVNTCOUNT(0), count);
>   4700
>   4701          return IRQ_WAKE_THREAD;
>   4702  }
>   4703
>
> --
> 0-DAY CI Kernel Test Service
> https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/1] usb: dwc3: gadget: fix IRQ storm on invalid event buffer count
  2026-08-07 11:04   ` Liu Jiazi
@ 2026-08-07 23:09     ` Thinh Nguyen
  0 siblings, 0 replies; 5+ messages in thread
From: Thinh Nguyen @ 2026-08-07 23:09 UTC (permalink / raw)
  To: Liu Jiazi
  Cc: kernel test robot, Thinh Nguyen, oe-kbuild-all@lists.linux.dev,
	gregkh@linuxfoundation.org, linux-usb@vger.kernel.org,
	linux-kernel@vger.kernel.org, stable@vger.kernel.org, Jiazi Liu

Hi Liu Jiazi,

On Fri, Aug 07, 2026, Liu Jiazi wrote:
> Hi @Thinh.Nguyen@synopsys.com
> 
> Thanks for the review suggestions. I've updated the patch accordingly.
> On thing I'd like to discuss: in dwc3_err_recovery_work(), after
> soft_disconnect succeeds, should we attempt soft_connect to
> recover the controller, or just leave it disconnected and let the
> upper layer (e.g. function driver like ADB) handle reconnection
> on its own?

But what would trigger the usb core to reconnect?

> 
> In my testing, calling soft_connect after soft_disconnect triggers an

Can you confirm where exactly the RCU stall happens? Did you add
synchronize_irq() before the soft_connect?

> RCU stall. Simply doing soft_disconnect and notifying the
> gadget driver via dwc3_disconnect_gadget_sleepable() is sufficient —
> ADB recovers on its own after that.
> What's your recommendation here?
> 
> Brs
> Jiazi
> 

Also, we may need to add a resuscitate counter and a "dying" state.
Before scheduling the dwc3_err_recovery_work(), increment the counter
and set the dying state. While in this state, the controller should
reject all gadget driver's requests.

If we fail to recover more than 3 times, stop doing soft_connect.

BR,
Thinh

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-08-07 23:09 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-27  9:40 [PATCH 1/1] usb: dwc3: gadget: fix IRQ storm on invalid event buffer count Jiazi Liu
2026-08-04 23:04 ` Thinh Nguyen
2026-08-06  9:03 ` kernel test robot
2026-08-07 11:04   ` Liu Jiazi
2026-08-07 23:09     ` Thinh Nguyen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox