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

Commit b4adc4f6 authored by Manu Gautam's avatar Manu Gautam
Browse files

USB: msm_otg: Fail suspend if !BSV is under processing



USB BAM driver is also responsible for putting USB OTG
in runtime suspend state during bus suspend or cable
disconnect. There is a handshake between usb_bam and
IPA for the same. msm_otg checks with usb_bam for the
same using msm_bam_lpm_ok() before entering suspend
to make sure that handshake between usb_bam and its
peer bam peripheral is finished.
In case that handshake takes more time and msm_bam_lpm_ok
returns FALSE then it is the responsibility of usb_bam
driver to put usb_otg in runtime_suspend later when
it is finished. But, there is chance that user disconnects
USB cable just when usb_bam is trying to put USB in
LPM and its processing is not finished by sm_work_fn.
This may result in stop_peripheral and msm_otg_suspend
racing with each other. Fix this by not allowing LPM if
cable is disconnected but OTG state is not B_IDLE. OTG
state is marked B_IDLE only after gadget driver is
disconnected or stopped.

CRs-fixed: 606558
Change-Id: I14b12ba52afd568bcb7fbc5a690ed135c3e90c55
Signed-off-by: default avatarManu Gautam <mgautam@codeaurora.org>
parent 077dfa98
Loading
Loading
Loading
Loading
+8 −3
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
@@ -891,7 +891,7 @@ static int msm_otg_suspend(struct msm_otg *motg)
	struct msm_otg_platform_data *pdata = motg->pdata;
	int cnt = 0;
	bool host_bus_suspend, device_bus_suspend, dcp, prop_charger;
	bool floated_charger;
	bool floated_charger, sm_work_busy;
	u32 phy_ctrl_val = 0, cmd_val;
	unsigned ret;
	u32 portsc, config2;
@@ -915,6 +915,10 @@ static int msm_otg_suspend(struct msm_otg *motg)
	prop_charger = motg->chg_type == USB_PROPRIETARY_CHARGER;
	floated_charger = motg->chg_type == USB_FLOATED_CHARGER;

	/* !BSV, but its handling is in progress by otg sm_work */
	sm_work_busy = !test_bit(B_SESS_VLD, &motg->inputs) &&
			phy->state == OTG_STATE_B_PERIPHERAL;

	/* Enable line state difference wakeup fix for only device and host
	 * bus suspend scenarios.  Otherwise PHY can not be suspended when
	 * a charger that pulls DP/DM high is connected.
@@ -930,11 +934,12 @@ static int msm_otg_suspend(struct msm_otg *motg)
	 * Abort suspend when,
	 * 1. charging detection in progress due to cable plug-in
	 * 2. host mode activation in progress due to Micro-A cable insertion
	 * 3. !BSV, but its handling is in progress by otg sm_work
	 */

	if ((test_bit(B_SESS_VLD, &motg->inputs) && !device_bus_suspend &&
		!dcp && !prop_charger && !floated_charger) ||
		test_bit(A_BUS_REQ, &motg->inputs)) {
		test_bit(A_BUS_REQ, &motg->inputs) || sm_work_busy) {
		motg->ui_enabled = 1;
		enable_irq(motg->irq);
		return -EBUSY;