From 1cb5c91b996eb08f686d5c01b0fb69cadfeb22bc Mon Sep 17 00:00:00 2001 From: Hemant Kumar Date: Tue, 9 Aug 2016 12:28:55 -0700 Subject: [PATCH] usb: dwc3: Remove tasklet bottom half handler There is a possibility of tasklet bottom half handler racing with dwc3_msm_suspend(). As a result before disabling the dwc3 irq, dwc3 interrupts are fired and once the suspend routine disables the clocks bottom half handler gets a chance to run and tries to access dwc3 register resulting into un-clocked register access. Since dwc3 interrupt is already running in threaded irq context, interrupt can be directly handled in same context and avoid this race. Change-Id: Ife9e165f6aa2112c1440819d659b97b5502a3f07 Signed-off-by: Hemant Kumar --- drivers/usb/dwc3/core.h | 1 - drivers/usb/dwc3/gadget.c | 21 ++------------------- 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 95191221bc3c..2c26ae1e3eb7 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -1005,7 +1005,6 @@ struct dwc3 { /* IRQ timing statistics */ int irq; - struct tasklet_struct bh; unsigned long irq_cnt; unsigned bh_completion_time[MAX_INTR_STATS]; unsigned bh_handled_evt_cnt[MAX_INTR_STATS]; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 7d97aeb21340..acaa99615d33 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2141,8 +2141,6 @@ static int dwc3_gadget_stop(struct usb_gadget *g) atomic_read(&dwc->dev->power.usage_count)); dwc3_gadget_disable_irq(dwc); - tasklet_kill(&dwc->bh); - spin_lock_irqsave(&dwc->lock, flags); __dwc3_gadget_ep_disable(dwc->eps[0]); @@ -3380,15 +3378,6 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf) return ret; } -static void dwc3_interrupt_bh(unsigned long param) -{ - struct dwc3 *dwc = (struct dwc3 *) param; - - pm_runtime_get(dwc->dev); - dwc3_thread_interrupt(dwc->irq, dwc); - enable_irq(dwc->irq); -} - static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc) { struct dwc3 *dwc = _dwc; @@ -3412,7 +3401,6 @@ static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc) dwc->bh_completion_time[dwc->bh_dbg_index] = temp_time; dwc->bh_dbg_index = (dwc->bh_dbg_index + 1) % 10; - pm_runtime_put(dwc->dev); return ret; } @@ -3478,10 +3466,8 @@ irqreturn_t dwc3_interrupt(int irq, void *_dwc) dwc->irq_event_count[dwc->irq_dbg_index] = temp_cnt / 4; dwc->irq_dbg_index = (dwc->irq_dbg_index + 1) % MAX_INTR_STATS; - if (ret == IRQ_WAKE_THREAD) { - disable_irq_nosync(irq); - tasklet_schedule(&dwc->bh); - } + if (ret == IRQ_WAKE_THREAD) + dwc3_thread_interrupt(dwc->irq, dwc); return IRQ_HANDLED; } @@ -3529,9 +3515,6 @@ int dwc3_gadget_init(struct dwc3 *dwc) goto err3; } - dwc->bh.func = dwc3_interrupt_bh; - dwc->bh.data = (unsigned long)dwc; - dwc->gadget.ops = &dwc3_gadget_ops; dwc->gadget.speed = USB_SPEED_UNKNOWN; dwc->gadget.sg_supported = true;