diff options
author | Ajay Agarwal <ajaya@codeaurora.org> | 2018-07-31 12:40:10 +0530 |
---|---|---|
committer | Ajay Agarwal <ajaya@codeaurora.org> | 2018-07-31 12:47:12 +0530 |
commit | 3674a33d5de3d453795941e2d3db9248298d6cfb (patch) | |
tree | e35385f0ec46cd6b3b11979e6df693f7140265c4 /drivers/usb/dwc3 | |
parent | 1deb9383f1a5c164dbc1dec03bbd48d6101f5d3c (diff) |
usb: dwc3-msm: Queue resume_work unconditionally on pm_resume
Currently on pm_resume, the driver queues resume_work only if
vbus_active is true or id_state is false. So when the system is
suspended with host mode cable connected and the cable is
disconnected, the port still remains in host mode. Fix this by
unconditionally queueing resume_work from pm_resume and adding
required pm_relax in B_IDLE branch of sm_work.
Also create a freezable workqueue for sm_work so that the work
items do not race with pm_resume of child devices.
Change-Id: I9b79ddcc44c87111fc85086038361d9140be2af5
Signed-off-by: Ajay Agarwal <ajaya@codeaurora.org>
Diffstat (limited to 'drivers/usb/dwc3')
-rw-r--r-- | drivers/usb/dwc3/dwc3-msm.c | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index de6bb295bf67..95e27e097b6b 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -188,6 +188,7 @@ struct dwc3_msm { struct work_struct restart_usb_work; bool in_restart; struct workqueue_struct *dwc3_wq; + struct workqueue_struct *sm_usb_wq; struct delayed_work sm_work; unsigned long inputs; unsigned max_power; @@ -1597,7 +1598,7 @@ static int msm_dwc3_usbdev_notify(struct notifier_block *self, } mdwc->hc_died = true; - schedule_delayed_work(&mdwc->sm_work, 0); + queue_delayed_work(mdwc->sm_usb_wq, &mdwc->sm_work, 0); return 0; } @@ -2358,7 +2359,7 @@ static void dwc3_ext_event_notify(struct dwc3_msm *mdwc) } pm_stay_awake(mdwc->dev); - schedule_delayed_work(&mdwc->sm_work, 0); + queue_delayed_work(mdwc->sm_usb_wq, &mdwc->sm_work, 0); } static void dwc3_resume_work(struct work_struct *w) @@ -2944,6 +2945,12 @@ static int dwc3_msm_probe(struct platform_device *pdev) INIT_DELAYED_WORK(&mdwc->perf_vote_work, msm_dwc3_perf_vote_work); INIT_DELAYED_WORK(&mdwc->sdp_check, check_for_sdp_connection); + mdwc->sm_usb_wq = create_freezable_workqueue("k_sm_usb"); + if (!mdwc->sm_usb_wq) { + pr_err("%s: Failed to create workqueue for sm_usb\n", __func__); + return -ENOMEM; + } + mdwc->dwc3_wq = alloc_ordered_workqueue("dwc3_wq", 0); if (!mdwc->dwc3_wq) { pr_err("%s: Unable to create workqueue dwc3_wq\n", __func__); @@ -3248,7 +3255,7 @@ static int dwc3_msm_probe(struct platform_device *pdev) dwc3_msm_id_notifier(&mdwc->id_nb, true, mdwc->extcon_id); else if (!pval.intval) { /* USB cable is not connected */ - schedule_delayed_work(&mdwc->sm_work, 0); + queue_delayed_work(mdwc->sm_usb_wq, &mdwc->sm_work, 0); } else { if (pval.intval > 0) dev_info(mdwc->dev, "charger detection in progress\n"); @@ -3868,6 +3875,7 @@ static void dwc3_otg_sm_work(struct work_struct *w) break; } else { dwc3_msm_gadget_vbus_draw(mdwc, 0); + pm_relax(mdwc->dev); dev_dbg(mdwc->dev, "Cable disconnected\n"); } break; @@ -3981,7 +3989,7 @@ static void dwc3_otg_sm_work(struct work_struct *w) } if (work) - schedule_delayed_work(&mdwc->sm_work, delay); + queue_delayed_work(mdwc->sm_usb_wq, &mdwc->sm_work, delay); ret: return; @@ -4086,9 +4094,7 @@ static int dwc3_msm_pm_resume(struct device *dev) if (mdwc->no_wakeup_src_in_hostmode && !test_bit(ID, &mdwc->inputs)) dwc3_msm_resume(mdwc); - /* kick in otg state machine */ - if (mdwc->vbus_active || !mdwc->id_state) - queue_work(mdwc->dwc3_wq, &mdwc->resume_work); + queue_work(mdwc->dwc3_wq, &mdwc->resume_work); return 0; } |