diff options
| author | Hemant Kumar <hemantk@codeaurora.org> | 2016-08-09 12:28:55 -0700 |
|---|---|---|
| committer | Hemant Kumar <hemantk@codeaurora.org> | 2016-08-10 10:56:43 -0700 |
| commit | 1cb5c91b996eb08f686d5c01b0fb69cadfeb22bc (patch) | |
| tree | efa9e2bfa3558befc84e38804694456cdb6eef6a | |
| parent | e94b446eac88a43e42ecde105275d48b677ea5b3 (diff) | |
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 <hemantk@codeaurora.org>
| -rw-r--r-- | drivers/usb/dwc3/core.h | 1 | ||||
| -rw-r--r-- | 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; |
