From b8558e41a27ac168c519976ed2d9d5ec88b2fbe7 Mon Sep 17 00:00:00 2001
From: Saket Saurabh <ssaurabh@codeaurora.org>
Date: Fri, 11 Apr 2014 16:59:57 +0530
Subject: [PATCH] phy-msm-usb: Set pm_done to true only when usb is in lpm

As part of USB disconnect event, msm_otg_suspend() executes and USB
enters into low power mode and pm_done flag is set to true. In the
scenario in which before the msm_otg_suspend() finished executing,
then USB connect event came in, in this case msm_otg_suspend() returns
-EBUSY. And later USB connect event is processed. As device is already
in resumed state, hence pm_done flag is never set to false. So on
next USB connect pm usage counter gets incremented in msm_otg_sm_work()
and device cannot enter into sleep state.

Fix the issue by setting pm_done flag to true as part of USB disconnect
event only when USB finished executing msm_otg_suspend() and is able to
enter low power mode.

CRs-fixed: 649434
Change-Id: Icd8d612ce6280300d0d97656f3dcf1921b45126f
Signed-off-by: Saket Saurabh <ssaurabh@codeaurora.org>
---
 drivers/usb/phy/phy-msm-usb.c | 7 ++++++-
 include/linux/usb/msm_hsusb.h | 5 ++++-
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c
index e1c92c4e1fdc..9c6ab0c541b2 100644
--- a/drivers/usb/phy/phy-msm-usb.c
+++ b/drivers/usb/phy/phy-msm-usb.c
@@ -2803,7 +2803,12 @@ static void msm_otg_sm_work(struct work_struct *w)
 			 */
 			pm_runtime_mark_last_busy(otg->phy->dev);
 			pm_runtime_autosuspend(otg->phy->dev);
-			motg->pm_done = 1;
+			/*
+			 * Set pm_done to true as part of USB disconnect
+			 * only when USB is in low power mode.
+			 */
+			if (atomic_read(&motg->in_lpm))
+				motg->pm_done = 1;
 		}
 		break;
 	case OTG_STATE_B_SRP_INIT:
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 17f28aeea795..78a2ed4c05e9 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -369,7 +369,10 @@ struct msm_otg_platform_data {
  * @chg_check_timer: The timer used to implement the workaround to detect
  *               very slow plug in of wall charger.
  * @ui_enabled: USB Intterupt is enabled or disabled.
- * @pm_done: Indicates whether USB is PM resumed
+ * @pm_done: It is used to increment the pm counter using pm_runtime_get_sync.
+	     This handles the race case when PM resume thread returns before
+	     the charger detection starts. When USB is disconnected and in lpm
+	     pm_done is set to true.
  */
 struct msm_otg {
 	struct usb_phy phy;
-- 
GitLab