usb: ehci-msm-hsic: abort suspend when interrupts are pending
Since the wakelock was removed, an interrupt coming during the
transition to system suspend relies on pm_stay_awake() to indicate
that the controller's wakeup source is now active. However, this
depends on pm_save_wakeup_count() to be called by the process
that initiated the suspend. The forthcoming autosleep feature will
be doing this.
But until autosleep is implemented, for robustness additionally
introduce a .suspend_noirq callback which checks for pending
interrupts and returns -EBUSY if there are any, which will force
the PM core to unwind its suspend actions.
Change-Id: If286d654b667d00a0130accb7a783258901ff760
Signed-off-by: Jack Pham <jackp@codeaurora.org>
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 465e512..eebda9e 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -1465,12 +1465,26 @@
return ret;
}
+static int msm_hsic_pm_suspend_noirq(struct device *dev)
+{
+ struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
+
+ if (mehci->async_int) {
+ dev_dbg(dev, "suspend_noirq: Aborting due to pending interrupt\n");
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
static int msm_hsic_pm_resume(struct device *dev)
{
int ret;
struct usb_hcd *hcd = dev_get_drvdata(dev);
struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
+ dev_dbg(dev, "ehci-msm-hsic PM resume\n");
dbg_log_event(NULL, "PM Resume", 0);
if (device_may_wakeup(dev))
@@ -1524,6 +1538,7 @@
#ifdef CONFIG_PM
static const struct dev_pm_ops msm_hsic_dev_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(msm_hsic_pm_suspend, msm_hsic_pm_resume)
+ .suspend_noirq = msm_hsic_pm_suspend_noirq,
SET_RUNTIME_PM_OPS(msm_hsic_runtime_suspend, msm_hsic_runtime_resume,
msm_hsic_runtime_idle)
};