diff options
| author | Azhar Shaikh <azhars@codeaurora.org> | 2014-11-11 18:59:20 -0800 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2014-12-04 10:55:28 -0800 |
| commit | 556d4d1d22c084d2663970531ccf72739af279ae (patch) | |
| tree | f3bc9a99bd6eeae5b2c438d43158d41150da1d1d | |
| parent | 9cc0afb4cfddbf1211027951ae62adba37813574 (diff) | |
usb: dwc3-msm: Mask events on cable disconnect
If erratic event occurs upon cable disconnect, then controller is
generating erratic events even after block reset is done.
Hence prevent this situaton by masking all events on cable disconnect
and after handling first block reset.
Blocking the subsequent events would later prevent
the unclocked register access due to controller suspend turning
off core clock while block reset work is in progress.
CRs-fixed: 754183
Change-Id: Iab364f0f72bc467067471835101a4931f786e61e
Signed-off-by: Azhar Shaikh <azhars@codeaurora.org>
| -rw-r--r-- | drivers/usb/dwc3/core.h | 2 | ||||
| -rw-r--r-- | drivers/usb/dwc3/dwc3-msm.c | 23 | ||||
| -rw-r--r-- | drivers/usb/dwc3/gadget.c | 2 |
3 files changed, 19 insertions, 8 deletions
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index b2074dd107d..804fa9e2fda 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -761,6 +761,7 @@ struct dwc3_scratchpad_array { * @tx_fifo_size: Available RAM size for TX fifo allocation * @err_evt_seen: previous event in queue was erratic error * @irq: irq number + * @irq_cnt: total irq count * @bh: tasklet which handles the interrupt * @bh_completion_time: time taken for taklet completion * @bh_handled_evt_cnt: no. of events handled by tasklet per interrupt @@ -873,6 +874,7 @@ struct dwc3 { bool err_evt_seen; bool enable_suspend_event; struct dwc3_gadget_events dbg_gadget_events; + unsigned long irq_cnt; /* offload IRQ handling to tasklet */ int irq; diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 98a83f689f2..aa8bee1ac47 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -972,7 +972,9 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned event) switch (event) { case DWC3_CONTROLLER_ERROR_EVENT: - dev_info(mdwc->dev, "DWC3_CONTROLLER_ERROR_EVENT received\n"); + dev_info(mdwc->dev, + "DWC3_CONTROLLER_ERROR_EVENT received, irq cnt %lu\n", + dwc->irq_cnt); dwc3_msm_dump_phy_info(mdwc); dwc3_gadget_disable_irq(dwc); /* @@ -1053,9 +1055,11 @@ static void dwc3_block_reset_usb_work(struct work_struct *w) unsigned long flags; dev_dbg(mdwc->dev, "%s\n", __func__); - dwc3_msm_block_reset(&mdwc->ext_xceiv, true); - dwc3_gadget_enable_irq(dwc); + if (mdwc->ext_xceiv.bsv) { + dbg_event(0xFF, "Mask EVT", 0); + dwc3_gadget_enable_irq(dwc); + } spin_lock_irqsave(&dwc->lock, flags); dwc->err_evt_seen = 0; spin_unlock_irqrestore(&dwc->lock, flags); @@ -1743,12 +1747,15 @@ static int dwc3_msm_power_set_property_usb(struct power_supply *psy, if (mdwc->otg_xceiv && !mdwc->ext_inuse && (mdwc->ext_xceiv.otg_capability || !init)) { mdwc->ext_xceiv.bsv = val->intval; - /* - * Cancel any block reset in progress during disconnect - * and wait for it to finish. - */ + /* Disable all events on cable disconnect */ + if (!mdwc->ext_xceiv.bsv) { + dbg_event(0xFF, "Dis EVT", 0); + dwc3_gadget_disable_irq(dwc); + } + /* Flush block reset work during disconnect */ if (dwc && dwc->err_evt_seen && !mdwc->ext_xceiv.bsv) { - cancel_work_sync(&mdwc->usb_block_reset_work); + dbg_event(0xFF, "Flush BR", 0); + flush_work(&mdwc->usb_block_reset_work); dwc->err_evt_seen = 0; } /* diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index fcfab1f45b9..5fd82614e6b 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -3154,6 +3154,8 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc) spin_lock(&dwc->lock); + dwc->irq_cnt++; + if (dwc->err_evt_seen) { /* controller reset is still pending */ spin_unlock(&dwc->lock); |
