Re: [PATCH 1/1] usb: dwc3: gadget: fix IRQ storm on invalid event buffer count

Liu Jiazi <[email protected]> Fri, 7 Aug 2026 19:04:08 +0800
Newsgroups org.kernel.vger.linux-usb,dev.linux.lists.oe-kbuild-all,org.kernel.vger.linux-kernel,org.kernel.vger.stable
Message-ID <CAAcjFgibrFJYKYp1Q-ig6hHE_WCg5KSSZV2Fvv0zawswEdHZEQ@mail.gmail.com>
Hi @[email protected]

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 <[email protected]> 于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/[email protected]/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/[email protected]/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 <[email protected]>
> | Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
>
> 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