summaryrefslogtreecommitdiff
path: root/drivers/usb/dwc3
diff options
context:
space:
mode:
authorVijayavardhan Vennapusa <vvreddy@codeaurora.org>2017-09-08 12:51:25 +0530
committerVijayavardhan Vennapusa <vvreddy@codeaurora.org>2017-09-14 16:41:17 +0530
commit3caa870dee84ddd69de752661df9b877110a12ca (patch)
treef151695413e666383db87b2193a9934234b40800 /drivers/usb/dwc3
parent8aedd7084222d4cce3acdfe3c71820c674503bee (diff)
USB: dwc3-msm: Protect enabling phy irqs with mutex
Currently driver is enabling hsphy_irq and ssphy_irq at the end of dwc3_msm_suspend() without any spinlock/mutex protection. But if it happens that hsphy_irq or ssphy_irq gets fired right after enablement of irqs, there is a chance that we might see warnings related to unbalanced irq enable. This could happen due to flag is not yet set to indicate phy irqs enabled in suspend(). This might cause phy irq left enabled after resume and could cause crash due to unclocked access in host mode. Fix the unbalance irq enable by having mutex protection and also extend mutex protection for dwc3_msm_suspend() and dwc3_msm_resume(). Change-Id: I8c2d26f82feb235add64305c1d0e5b686993e9e9 Signed-off-by: Vijayavardhan Vennapusa <vvreddy@codeaurora.org>
Diffstat (limited to 'drivers/usb/dwc3')
-rw-r--r--drivers/usb/dwc3/dwc3-msm.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 5ad68df298cd..3c0f68deee34 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -233,6 +233,7 @@ struct dwc3_msm {
struct pm_qos_request pm_qos_req_dma;
struct delayed_work perf_vote_work;
struct delayed_work sdp_check;
+ struct mutex suspend_resume_mutex;
};
#define USB_HSPHY_3P3_VOL_MIN 3050000 /* uV */
@@ -1997,8 +1998,10 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc)
dbg_event(0xFF, "Ctl Sus", atomic_read(&dwc->in_lpm));
+ mutex_lock(&mdwc->suspend_resume_mutex);
if (atomic_read(&dwc->in_lpm)) {
dev_dbg(mdwc->dev, "%s: Already suspended\n", __func__);
+ mutex_unlock(&mdwc->suspend_resume_mutex);
return 0;
}
@@ -2015,6 +2018,7 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc)
__func__, evt->count / 4);
dbg_print_reg("PENDING DEVICE EVENT",
*(u32 *)(evt->buf + evt->lpos));
+ mutex_unlock(&mdwc->suspend_resume_mutex);
return -EBUSY;
}
}
@@ -2034,6 +2038,7 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc)
dev_dbg(mdwc->dev,
"%s: cable disconnected while not in idle otg state\n",
__func__);
+ mutex_unlock(&mdwc->suspend_resume_mutex);
return -EBUSY;
}
@@ -2047,12 +2052,15 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc)
pr_err("%s(): Trying to go in LPM with state:%d\n",
__func__, dwc->gadget.state);
pr_err("%s(): LPM is not performed.\n", __func__);
+ mutex_unlock(&mdwc->suspend_resume_mutex);
return -EBUSY;
}
ret = dwc3_msm_prepare_suspend(mdwc);
- if (ret)
+ if (ret) {
+ mutex_unlock(&mdwc->suspend_resume_mutex);
return ret;
+ }
/* Initialize variables here */
can_suspend_ssphy = !(mdwc->in_host_mode &&
@@ -2153,6 +2161,7 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc)
}
dev_info(mdwc->dev, "DWC3 in low power mode\n");
+ mutex_unlock(&mdwc->suspend_resume_mutex);
return 0;
}
@@ -2164,8 +2173,10 @@ static int dwc3_msm_resume(struct dwc3_msm *mdwc)
dev_dbg(mdwc->dev, "%s: exiting lpm\n", __func__);
+ mutex_lock(&mdwc->suspend_resume_mutex);
if (!atomic_read(&dwc->in_lpm)) {
dev_dbg(mdwc->dev, "%s: Already resumed\n", __func__);
+ mutex_unlock(&mdwc->suspend_resume_mutex);
return 0;
}
@@ -2300,6 +2311,7 @@ static int dwc3_msm_resume(struct dwc3_msm *mdwc)
msecs_to_jiffies(1000 * PM_QOS_SAMPLE_SEC));
dbg_event(0xFF, "Ctl Res", atomic_read(&dwc->in_lpm));
+ mutex_unlock(&mdwc->suspend_resume_mutex);
return 0;
}
@@ -3179,6 +3191,7 @@ static int dwc3_msm_probe(struct platform_device *pdev)
POWER_SUPPLY_PROP_PRESENT, &pval);
}
+ mutex_init(&mdwc->suspend_resume_mutex);
/* Update initial VBUS/ID state from extcon */
if (mdwc->extcon_vbus && extcon_get_cable_state_(mdwc->extcon_vbus,
EXTCON_USB))