usb: dwc3: core: Stop processing of pending events if controller is halted

This commit addresses an issue where events were being processed when
the controller was in a halted state. To fix this issue by stop
processing the events as the event count was considered stale or
invalid when the controller was halted.

Fixes: fc8bb91bc83e ("usb: dwc3: implement runtime PM")
Cc: stable@kernel.org
Signed-off-by: Selvarasu Ganesan <selvarasu.g@samsung.com>
Suggested-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
Link: https://lore.kernel.org/r/20240916231813.206-1-selvarasu.g@samsung.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by Selvarasu Ganesan and committed by Greg Kroah-Hartman 0d410e89 897e13a8

+19 -18
+19 -3
drivers/usb/dwc3/core.c
··· 544 544 int dwc3_event_buffers_setup(struct dwc3 *dwc) 545 545 { 546 546 struct dwc3_event_buffer *evt; 547 + u32 reg; 547 548 548 549 if (!dwc->ev_buf) 549 550 return 0; ··· 557 556 upper_32_bits(evt->dma)); 558 557 dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), 559 558 DWC3_GEVNTSIZ_SIZE(evt->length)); 560 - dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0); 561 559 560 + /* Clear any stale event */ 561 + reg = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0)); 562 + dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), reg); 562 563 return 0; 563 564 } 564 565 ··· 587 584 dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0), 0); 588 585 dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), DWC3_GEVNTSIZ_INTMASK 589 586 | DWC3_GEVNTSIZ_SIZE(0)); 590 - dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0); 587 + 588 + /* Clear any stale event */ 589 + reg = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0)); 590 + dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), reg); 591 591 } 592 592 593 593 static void dwc3_core_num_eps(struct dwc3 *dwc) ··· 2505 2499 2506 2500 switch (dwc->current_dr_role) { 2507 2501 case DWC3_GCTL_PRTCAP_DEVICE: 2508 - dwc3_gadget_process_pending_events(dwc); 2502 + if (dwc->pending_events) { 2503 + pm_runtime_put(dwc->dev); 2504 + dwc->pending_events = false; 2505 + enable_irq(dwc->irq_gadget); 2506 + } 2509 2507 break; 2510 2508 case DWC3_GCTL_PRTCAP_HOST: 2511 2509 default: ··· 2597 2587 static const struct dev_pm_ops dwc3_dev_pm_ops = { 2598 2588 SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume) 2599 2589 .complete = dwc3_complete, 2590 + 2591 + /* 2592 + * Runtime suspend halts the controller on disconnection. It relies on 2593 + * platforms with custom connection notification to start the controller 2594 + * again. 2595 + */ 2600 2596 SET_RUNTIME_PM_OPS(dwc3_runtime_suspend, dwc3_runtime_resume, 2601 2597 dwc3_runtime_idle) 2602 2598 };
-4
drivers/usb/dwc3/core.h
··· 1675 1675 #if !IS_ENABLED(CONFIG_USB_DWC3_HOST) 1676 1676 int dwc3_gadget_suspend(struct dwc3 *dwc); 1677 1677 int dwc3_gadget_resume(struct dwc3 *dwc); 1678 - void dwc3_gadget_process_pending_events(struct dwc3 *dwc); 1679 1678 #else 1680 1679 static inline int dwc3_gadget_suspend(struct dwc3 *dwc) 1681 1680 { ··· 1686 1687 return 0; 1687 1688 } 1688 1689 1689 - static inline void dwc3_gadget_process_pending_events(struct dwc3 *dwc) 1690 - { 1691 - } 1692 1690 #endif /* !IS_ENABLED(CONFIG_USB_DWC3_HOST) */ 1693 1691 1694 1692 #if IS_ENABLED(CONFIG_USB_DWC3_ULPI)
-11
drivers/usb/dwc3/gadget.c
··· 4728 4728 4729 4729 return dwc3_gadget_soft_connect(dwc); 4730 4730 } 4731 - 4732 - void dwc3_gadget_process_pending_events(struct dwc3 *dwc) 4733 - { 4734 - if (dwc->pending_events) { 4735 - dwc3_interrupt(dwc->irq_gadget, dwc->ev_buf); 4736 - dwc3_thread_interrupt(dwc->irq_gadget, dwc->ev_buf); 4737 - pm_runtime_put(dwc->dev); 4738 - dwc->pending_events = false; 4739 - enable_irq(dwc->irq_gadget); 4740 - } 4741 - }