diff options
author | Vijayavardhan Vennapusa <vvreddy@codeaurora.org> | 2017-09-08 12:51:25 +0530 |
---|---|---|
committer | Vijayavardhan Vennapusa <vvreddy@codeaurora.org> | 2017-09-14 16:41:17 +0530 |
commit | 3caa870dee84ddd69de752661df9b877110a12ca (patch) | |
tree | f151695413e666383db87b2193a9934234b40800 /drivers/usb/dwc3 | |
parent | 8aedd7084222d4cce3acdfe3c71820c674503bee (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.c | 15 |
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)) |