Re: [PATCH] usb: dwc3: Clear DWC3_EVENT_PENDING when count is 0

From: Linyu Yuan
Date: Wed Jan 04 2023 - 22:35:54 EST



On 1/5/2023 11:29 AM, Linyu Yuan wrote:
On 1/2/2023 1:08 PM, JaeHun Jung wrote:
Sometimes very rarely, The count is 0 and the DWC3 flag is set has status.
It must not have these status. Because, It can make happen interrupt storming
status.

could you help explain without clear the flag, how interrupt storming happen ?

as your change didn't touch any hardware register, i don't know how it fix storming.

storming from software layer ?

So, It have to clean up DWC3_EVENT_PENDING flags set when count is 0.
It means "There are no interrupts to handle.".

(struct dwc3_event_buffer *) ev_buf = 0xFFFFFF883DBF1180 (
    (void *) buf = 0xFFFFFFC00DBDD000 = end+0x337D000,
    (void *) cache = 0xFFFFFF8839F54080,
    (unsigned int) length = 0x1000,
    (unsigned int) lpos = 0x0,
    (unsigned int) count = 0x0,
    (unsigned int) flags = 0x00000001,
    (dma_addr_t) dma = 0x00000008BD7D7000,
    (struct dwc3 *) dwc = 0xFFFFFF8839CBC880,
    (u64) android_kabi_reserved1 = 0x0),

(time = 47557628930999, irq = 165, fn = dwc3_interrupt, latency = 0, en = 1),
(time = 47557628931268, irq = 165, fn = dwc3_interrupt, latency = 0, en = 3),
(time = 47557628932383, irq = 165, fn = dwc3_interrupt, latency = 0, en = 1),
(time = 47557628932652, irq = 165, fn = dwc3_interrupt, latency = 0, en = 3),
(time = 47557628933768, irq = 165, fn = dwc3_interrupt, latency = 0, en = 1),
(time = 47557628934037, irq = 165, fn = dwc3_interrupt, latency = 0, en = 3),
(time = 47557628935152, irq = 165, fn = dwc3_interrupt, latency = 0, en = 1),
(time = 47557628935460, irq = 165, fn = dwc3_interrupt, latency = 0, en = 3),
(time = 47557628936575, irq = 165, fn = dwc3_interrupt, latency = 0, en = 1),
(time = 47557628936845, irq = 165, fn = dwc3_interrupt, latency = 0, en = 3),
(time = 47557628937960, irq = 165, fn = dwc3_interrupt, latency = 0, en = 1),
(time = 47557628938229, irq = 165, fn = dwc3_interrupt, latency = 0, en = 3),
(time = 47557628939345, irq = 165, fn = dwc3_interrupt, latency = 0, en = 1),
(time = 47557628939652, irq = 165, fn = dwc3_interrupt, latency = 0, en = 3),
(time = 47557628940768, irq = 165, fn = dwc3_interrupt, latency = 0, en = 1),
(time = 47557628941037, irq = 165, fn = dwc3_interrupt, latency = 0, en = 3),
(time = 47557628942152, irq = 165, fn = dwc3_interrupt, latency = 0, en = 1),
(time = 47557628942422, irq = 165, fn = dwc3_interrupt, latency = 0, en = 3),
(time = 47557628943537, irq = 165, fn = dwc3_interrupt, latency = 0, en = 1),
(time = 47557628943806, irq = 165, fn = dwc3_interrupt, latency = 0, en = 3),
(time = 47557628944922, irq = 165, fn = dwc3_interrupt, latency = 0, en = 1),
(time = 47557628945229, irq = 165, fn = dwc3_interrupt, latency = 0, en = 3),
(time = 47557628946345, irq = 165, fn = dwc3_interrupt, latency = 0, en = 1),
(time = 47557628946614, irq = 165, fn = dwc3_interrupt, latency = 0, en = 3),
(time = 47557628947729, irq = 165, fn = dwc3_interrupt, latency = 0, en = 1),
(time = 47557628947999, irq = 165, fn = dwc3_interrupt, latency = 0, en = 3),

Signed-off-by: JaeHun Jung <jh0801.jung@xxxxxxxxxxx>
---
  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 789976567f9f..5d2d5a9b9915 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -4355,8 +4355,11 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt)
       * irq event handler completes before caching new event to prevent
       * losing events.
       */
-    if (evt->flags & DWC3_EVENT_PENDING)
+    if (evt->flags & DWC3_EVENT_PENDING) {
+        if (!evt->count)
+            evt->flags &= ~DWC3_EVENT_PENDING;
          return IRQ_HANDLED;
+    }
        count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0));
      count &= DWC3_GEVNTCOUNT_MASK;

how about below change ?

        count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0));
        count &= DWC3_GEVNTCOUNT_MASK;
-       if (!count)
+       if (!count) {
+               evt->flags &= ~DWC3_EVENT_PENDING;
                return IRQ_NONE;
+       }
ignore my suggestion, add Thinh to comment.

        evt->count = count;
        evt->flags |= DWC3_EVENT_PENDING;