Interrupt Storming occurred with a very low probability of occurrence. The occurrence of the problem is estimated to be caused by a race condition between the top half and bottom half of the interrupt service routine. It was confirmed that variables have values that cannot be held when ISR occurs through normal H / W irq. ===================================================================== (struct dwc3_event_buffer *) ev_buf = 0xFFFFFF88DE6A0380 ( (void *) buf = 0xFFFFFFC01594E000, (void *) cache = 0xFFFFFF88DDC14080, (unsigned int) length = 4096, (unsigned int) lpos = 0, (unsigned int) count = 0, << (unsigned int) flags = 1, << ===================================================================== "evt->count=0" and "evt->flags=DWC3_EVENT_PENDING" cannot be set at the same time. We estimate that a race condition occurred between dwc3_interrupt() and dwc3_process_event_buf() called by dwc3_gadget_process_pending_events(). So I try to block the race condition through spin_lock. Signed-off-by: JaeHun Jung <jh0801.jung@xxxxxxxxxxx> --- drivers/usb/dwc3/gadget.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index a0c883f19a41..88f9ecf8cbfe 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -4172,6 +4172,7 @@ static irqreturn_t dwc3_thread_interrupt(int irq, void *_evt) static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt) { struct dwc3 *dwc = evt->dwc; + unsigned long flags; u32 amount; u32 count; @@ -4188,13 +4189,18 @@ 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) + spin_lock_irqsave(&dwc->lock, flags); + if (evt->flags & DWC3_EVENT_PENDING) { + spin_unlock_irqrestore(&dwc->lock, flags); return IRQ_HANDLED; + } count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0)); count &= DWC3_GEVNTCOUNT_MASK; - if (!count) + if (!count) { + spin_unlock_irqrestore(&dwc->lock, flags); return IRQ_NONE; + } evt->count = count; evt->flags |= DWC3_EVENT_PENDING; @@ -4210,6 +4216,7 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt) memcpy(evt->cache, evt->buf, count - amount); dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), count); + spin_unlock_irqrestore(&dwc->lock, flags); return IRQ_WAKE_THREAD; } -- 2.31.1