[PATCH] usb: dwc3: gadget: Avoid race between dwc3 interrupt handler and irq thread handler

From: Baolin Wang
Date: Mon Dec 26 2016 - 03:01:44 EST


On some platfroms(like x86 platform), when one core is running the USB gadget
irq thread handler by dwc3_thread_interrupt(), meanwhile another core also can
respond other interrupts from dwc3 controller and modify the event buffer by
dwc3_interrupt() function, that will cause getting the wrong event count in
irq thread handler to make the USB function abnormal.

We should add spin_lock/unlock() in dwc3_check_event_buf() to avoid this race.

Signed-off-by: Baolin Wang <baolin.wang@xxxxxxxxxx>
---
drivers/usb/dwc3/gadget.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 6785595..1a1e1f4 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2894,10 +2894,13 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt)
return IRQ_HANDLED;
}

+ spin_lock(&dwc->lock);
count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0));
count &= DWC3_GEVNTCOUNT_MASK;
- if (!count)
+ if (!count) {
+ spin_unlock(&dwc->lock);
return IRQ_NONE;
+ }

evt->count = count;
evt->flags |= DWC3_EVENT_PENDING;
@@ -2914,6 +2917,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(&dwc->lock);

return IRQ_WAKE_THREAD;
}
--
1.7.9.5