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

Commit 6eae5c28 authored by Saket Saurabh's avatar Saket Saurabh
Browse files

usb: phy-msm-usb.c: Fix timeout during usb disconnect with hvdcp charger



Once DCP is detected, ext_chg_active is set to true and DCP uevent
reached to user space. The hvdcp main thread mark dcp_connected to
true and wakesup the detector thread to do hvdcp detection. But before
the detector thread gets a chance to run, DCP is removed. The disconnect
uevent reached the user space and the hvdcp main thread marks the
dcp_connected to false and it will not call any ioctl call. As
ext_chg_active is still set to true, it is waiting for 3 seconds while
processing usb disconnect.

Also it is possible that DCP uevent is reached to the user space much
before ext_chg_active flag is set to true in otg state machine work which
later leads to timeout of 3 seconds later while processing usb disconnect.

Fix these issues by maintaining different states for ext_chg_active. Upon
DCP disconnect, if the ext_chg_active value is still default, mark it to
inactive. This avoid the 3 seconds wait timeout while processing the usb
disconnect.

CRs-Fixed: 671181
Change-Id: Ic4aa6745e994a007bd6bd2e75d4f44fb8f7ac9c1
Signed-off-by: default avatarSaket Saurabh <ssaurabh@codeaurora.org>
parent 394c9c0d
Loading
Loading
Loading
Loading
+13 −11
Original line number Diff line number Diff line
@@ -2433,6 +2433,11 @@ static void msm_chg_detect_work(struct work_struct *w)
		 * Notify the charger type to power supply
		 * owner as soon as we determine the charger.
		 */
		if (motg->chg_type == USB_DCP_CHARGER &&
			motg->ext_chg_opened) {
				init_completion(&motg->ext_chg_wait);
				motg->ext_chg_active = DEFAULT;
		}
		msm_otg_notify_chg_type(motg);
		msm_chg_block_off(motg);
		msm_chg_enable_aca_det(motg);
@@ -2562,7 +2567,7 @@ static void msm_otg_wait_for_ext_chg_done(struct msm_otg *motg)
	 * detection is completed.
	 */

	if (motg->ext_chg_active) {
	if (motg->ext_chg_active == ACTIVE) {

do_wait:
		pr_debug("before msm_otg ext chg wait\n");
@@ -2571,7 +2576,7 @@ do_wait:
				msecs_to_jiffies(3000));
		if (!t)
			pr_err("msm_otg ext chg wait timeout\n");
		else if (motg->ext_chg_active)
		else if (motg->ext_chg_active == ACTIVE)
			goto do_wait;
		else
			pr_debug("msm_otg ext chg wait done\n");
@@ -2648,11 +2653,6 @@ static void msm_otg_sm_work(struct work_struct *w)
				case USB_DCP_CHARGER:
					/* Enable VDP_SRC */
					ulpi_write(otg->phy, 0x2, 0x85);
					if (motg->ext_chg_opened) {
						init_completion(
							&motg->ext_chg_wait);
						motg->ext_chg_active = true;
					}
					/* fall through */
				case USB_PROPRIETARY_CHARGER:
					msm_otg_notify_charger(motg,
@@ -2722,6 +2722,8 @@ static void msm_otg_sm_work(struct work_struct *w)
			motg->chg_type = USB_INVALID_CHARGER;
			msm_otg_notify_charger(motg, 0);
			if (dcp) {
				if (motg->ext_chg_active == DEFAULT)
					motg->ext_chg_active = INACTIVE;
				msm_otg_wait_for_ext_chg_done(motg);
				/* Turn off VDP_SRC */
				ulpi_write(otg->phy, 0x2, 0x86);
@@ -4119,7 +4121,7 @@ msm_otg_ext_chg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
		pr_debug("%s: LPM block request %d\n", __func__, val);
		if (val) { /* block LPM */
			if (motg->chg_type == USB_DCP_CHARGER) {
				motg->ext_chg_active = true;
				motg->ext_chg_active = ACTIVE;
				/*
				 * If device is already suspended, resume it.
				 * The PM usage counter is incremented in
@@ -4132,12 +4134,12 @@ msm_otg_ext_chg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
				else
					pm_runtime_get_sync(motg->phy.dev);
			} else {
				motg->ext_chg_active = false;
				motg->ext_chg_active = INACTIVE;
				complete(&motg->ext_chg_wait);
				ret = -ENODEV;
			}
		} else {
			motg->ext_chg_active = false;
			motg->ext_chg_active = INACTIVE;
			complete(&motg->ext_chg_wait);
			/*
			 * If usb cable is disconnected and then userspace
@@ -5078,7 +5080,7 @@ static int msm_otg_runtime_idle(struct device *dev)
	if (phy->state == OTG_STATE_UNDEFINED)
		return -EAGAIN;

	if (motg->ext_chg_active) {
	if (motg->ext_chg_active == DEFAULT) {
		dev_dbg(dev, "Deferring LPM\n");
		/*
		 * Charger detection may happen in user space.
+14 −1
Original line number Diff line number Diff line
@@ -190,6 +190,19 @@ enum usb_vdd_value {
	VDD_VAL_MAX,
};

/**
 * Maintain state for hvdcp external charger status
 * DEFAULT	This is used when DCP is detected
 * ACTIVE	This is used when ioctl is called to block LPM
 * INACTIVE	This is used when ioctl is called to unblock LPM
 */

enum usb_ext_chg_status {
	DEFAULT = 1,
	ACTIVE,
	INACTIVE,
};

/**
 * Supported USB controllers
 */
@@ -495,7 +508,7 @@ struct msm_otg {
	struct class *ext_chg_class;
	struct device *ext_chg_device;
	bool ext_chg_opened;
	bool ext_chg_active;
	enum usb_ext_chg_status ext_chg_active;
	struct completion ext_chg_wait;
	struct pinctrl *phy_pinctrl;
	int ui_enabled;