summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHemant Kumar <hemantk@codeaurora.org>2016-08-09 12:28:55 -0700
committerHemant Kumar <hemantk@codeaurora.org>2016-08-10 10:56:43 -0700
commit1cb5c91b996eb08f686d5c01b0fb69cadfeb22bc (patch)
treeefa9e2bfa3558befc84e38804694456cdb6eef6a
parente94b446eac88a43e42ecde105275d48b677ea5b3 (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.h1
-rw-r--r--drivers/usb/dwc3/gadget.c21
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;