aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAzhar Shaikh <azhars@codeaurora.org>2014-11-11 18:59:20 -0800
committerGerrit - the friendly Code Review server <code-review@localhost>2014-12-04 10:55:28 -0800
commit556d4d1d22c084d2663970531ccf72739af279ae (patch)
treef3bc9a99bd6eeae5b2c438d43158d41150da1d1d
parent9cc0afb4cfddbf1211027951ae62adba37813574 (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.h2
-rw-r--r--drivers/usb/dwc3/dwc3-msm.c23
-rw-r--r--drivers/usb/dwc3/gadget.c2
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);