summaryrefslogtreecommitdiff
path: root/drivers/usb/dwc3
diff options
context:
space:
mode:
authorAjay Agarwal <ajaya@codeaurora.org>2018-07-31 12:40:10 +0530
committerAjay Agarwal <ajaya@codeaurora.org>2018-07-31 12:47:12 +0530
commit3674a33d5de3d453795941e2d3db9248298d6cfb (patch)
treee35385f0ec46cd6b3b11979e6df693f7140265c4 /drivers/usb/dwc3
parent1deb9383f1a5c164dbc1dec03bbd48d6101f5d3c (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.c20
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;
}