| From 84918a89d6efaff075de570b55642b6f4ceeac6d Mon Sep 17 00:00:00 2001 |
| From: Sebastian Andrzej Siewior <bigeasy@linutronix.de> |
| Date: Fri, 18 Feb 2022 18:32:45 +0100 |
| Subject: usb: dwc3: gadget: Let the interrupt handler disable bottom halves. |
| |
| From: Sebastian Andrzej Siewior <bigeasy@linutronix.de> |
| |
| commit 84918a89d6efaff075de570b55642b6f4ceeac6d upstream. |
| |
| The interrupt service routine registered for the gadget is a primary |
| handler which mask the interrupt source and a threaded handler which |
| handles the source of the interrupt. Since the threaded handler is |
| voluntary threaded, the IRQ-core does not disable bottom halves before |
| invoke the handler like it does for the forced-threaded handler. |
| |
| Due to changes in networking it became visible that a network gadget's |
| completions handler may schedule a softirq which remains unprocessed. |
| The gadget's completion handler is usually invoked either in hard-IRQ or |
| soft-IRQ context. In this context it is enough to just raise the softirq |
| because the softirq itself will be handled once that context is left. |
| In the case of the voluntary threaded handler, there is nothing that |
| will process pending softirqs. Which means it remain queued until |
| another random interrupt (on this CPU) fires and handles it on its exit |
| path or another thread locks and unlocks a lock with the bh suffix. |
| Worst case is that the CPU goes idle and the NOHZ complains about |
| unhandled softirqs. |
| |
| Disable bottom halves before acquiring the lock (and disabling |
| interrupts) and enable them after dropping the lock. This ensures that |
| any pending softirqs will handled right away. |
| |
| Link: https://lkml.kernel.org/r/c2a64979-73d1-2c22-e048-c275c9f81558@samsung.com |
| Fixes: e5f68b4a3e7b0 ("Revert "usb: dwc3: gadget: remove unnecessary _irqsave()"") |
| Cc: stable <stable@kernel.org> |
| Reported-by: Marek Szyprowski <m.szyprowski@samsung.com> |
| Tested-by: Marek Szyprowski <m.szyprowski@samsung.com> |
| Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> |
| Link: https://lore.kernel.org/r/Yg/YPejVQH3KkRVd@linutronix.de |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/usb/dwc3/gadget.c | 2 ++ |
| 1 file changed, 2 insertions(+) |
| |
| --- a/drivers/usb/dwc3/gadget.c |
| +++ b/drivers/usb/dwc3/gadget.c |
| @@ -3181,9 +3181,11 @@ static irqreturn_t dwc3_thread_interrupt |
| unsigned long flags; |
| irqreturn_t ret = IRQ_NONE; |
| |
| + local_bh_disable(); |
| spin_lock_irqsave(&dwc->lock, flags); |
| ret = dwc3_process_event_buf(evt); |
| spin_unlock_irqrestore(&dwc->lock, flags); |
| + local_bh_enable(); |
| |
| return ret; |
| } |