Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1bc40bca authored by Saket Saurabh's avatar Saket Saurabh
Browse files

USB: msm_otg: Fix race between PM resume and charger detection



When device is in system suspend and USB charger is disconnected,
then due to VBUS clear IRQ from PMIC, the device will be PM resumed.
Now shortly if PMIC driver detects valid VBUS it will handle VBUS
set condition,notifies to msm_otg and msm_otg will kick in charger
detection mechanism. During PM resume, in dmp_complete() it will
call a pm_runtime_put_sync(), which will immediately kick off the
PM runtime idle and suspend routines.
dpm_complete()
  ->device_complete()
    ->pm_runtime_put_sync()
      ->rpm_idle()
        ->rpm_suspend()

The PM resume also runs in a separate worker queue, so it is not
guaranteed that it will finish executing before we finish the charger
detection stage. During this case there is a race if dpm_complete()
returns before charger detection starts. Return of dmp_cpmplete()
before charger detection will make USB to enter LPM. As USB will be
in LPM now and if charger detection starts then it will lead to
unclocked access.

Fixing the issue by handling the pm usage count using the variable
pm_done in msm_otg. When USB charger is disconnected and msm_otg
processes the disconnect event it marks the pm_done to true. Later
when USB charger is connected , mark the pm_done to false in
msm_otg_runtime_resume(). If pm_done is true increment the pm counter
using pm_runtime_get_sync. This handles the race case when PM resume
thread returns before the charger detection starts.

CRs-Fixed: 599143
Change-Id: I6de19fe850e24efa03ea71c7d14e388c15cf2f97
Signed-off-by: default avatarSaket Saurabh <ssaurabh@codeaurora.org>
parent 02983880
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
/* Copyright (c) 2009-2013, Linux Foundation. All rights reserved.
/* Copyright (c) 2009-2014, Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -2659,6 +2659,8 @@ static void msm_otg_sm_work(struct work_struct *w)
	bool work = 0, srp_reqd, dcp;

	pm_runtime_resume(otg->phy->dev);
	if (motg->pm_done)
		pm_runtime_get_sync(otg->phy->dev);
	pr_debug("%s work\n", usb_otg_state_string(otg->phy->state));
	switch (otg->phy->state) {
	case OTG_STATE_UNDEFINED:
@@ -2804,6 +2806,7 @@ 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;
		}
		break;
	case OTG_STATE_B_SRP_INIT:
@@ -5031,6 +5034,7 @@ static int msm_otg_runtime_resume(struct device *dev)

	dev_dbg(dev, "OTG runtime resume\n");
	pm_runtime_get_noresume(dev);
	motg->pm_done = 0;
	return msm_otg_resume(motg);
}
#endif
@@ -5058,6 +5062,7 @@ static int msm_otg_pm_resume(struct device *dev)

	dev_dbg(dev, "OTG PM resume\n");

	motg->pm_done = 0;
	atomic_set(&motg->pm_suspended, 0);
	if (motg->async_int || motg->sm_work_pending ||
			!pm_runtime_suspended(dev)) {
+3 −1
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@
 *
 * Copyright (C) 2008 Google, Inc.
 * Author: Brian Swetland <swetland@google.com>
 * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
 * Copyright (c) 2009-2014, The Linux Foundation. All rights reserved.
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
@@ -359,6 +359,7 @@ 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
 */
struct msm_otg {
	struct usb_phy phy;
@@ -478,6 +479,7 @@ struct msm_otg {
	bool ext_chg_active;
	struct completion ext_chg_wait;
	int ui_enabled;
	bool pm_done;
};

struct ci13xxx_platform_data {