From 4852b6f3dc45c06fe6601d25d05433db629df791 Mon Sep 17 00:00:00 2001 From: Sriharsha Allenki Date: Mon, 12 Oct 2020 14:14:57 +0530 Subject: [PATCH] usb: dwc3: Fix re-enumeration of connected peripherals When the device exits suspend/deep sleep in host mode with peripherals connected, the peripherals and root hub failed to resume because the xhci stack has not resumed yet, leading to the re-enumeration of the connected peripherals. Fix this by resuming the glue driver, core and xhci plat driver un-conditionally as part of suspend/deep sleep exit. Change-Id: Ie1cbe174aec04ddde5779ad4fabdf075cffa955d Signed-off-by: Sriharsha Allenki --- drivers/usb/dwc3/core.c | 3 +-- drivers/usb/dwc3/dwc3-msm.c | 2 +- drivers/usb/host/xhci-plat.c | 25 ++++++++++++++++++++++++- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index ea06853aaaca..97477c3dc244 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -2001,8 +2001,7 @@ static int dwc3_resume(struct device *dev) * runtime PM state as active to reflect actual state of device * which is now out of LPM. This allows runtime_suspend later. */ - if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST && - dwc->host_poweroff_in_pm_suspend) + if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST) goto runtime_set_active; return 0; diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 10b1ad1f0823..aadb217d03b8 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -5303,7 +5303,7 @@ static int dwc3_msm_pm_resume(struct device *dev) atomic_set(&mdwc->pm_suspended, 0); - if (!dwc->host_poweroff_in_pm_suspend || !mdwc->in_host_mode) { + if (!mdwc->in_host_mode) { /* kick in otg state machine */ queue_work(mdwc->dwc3_wq, &mdwc->resume_work); diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 997bc1e57ff3..575a31ec9600 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -421,6 +421,29 @@ static int __maybe_unused xhci_plat_runtime_suspend(struct device *dev) return xhci_suspend(xhci, true); } +static int xhci_plat_resume(struct device *dev) +{ + struct usb_hcd *hcd = dev_get_drvdata(dev); + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + int ret; + + if (!xhci) + return 0; + + dev_dbg(dev, "xhci-plat resume\n"); + + ret = xhci_priv_resume_quirk(hcd); + if (ret) + return ret; + + ret = xhci_resume(xhci, false); + pm_runtime_disable(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + + return ret; +} + static int __maybe_unused xhci_plat_runtime_resume(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); @@ -443,7 +466,7 @@ static int __maybe_unused xhci_plat_runtime_resume(struct device *dev) } static const struct dev_pm_ops xhci_plat_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(NULL, NULL) + SET_SYSTEM_SLEEP_PM_OPS(NULL, xhci_plat_resume) SET_RUNTIME_PM_OPS(xhci_plat_runtime_suspend, xhci_plat_runtime_resume,