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.w...@linaro.org>
---
 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

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to