usb: msm_otg: 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: Saket Saurabh <ssaurabh@codeaurora.org>
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index c4e5962..ea724d6 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -2438,6 +2438,11 @@
* 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);
@@ -2541,7 +2546,7 @@
* 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");
@@ -2550,7 +2555,7 @@
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");
@@ -2627,11 +2632,6 @@
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,
@@ -2701,6 +2701,8 @@
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);
@@ -4054,7 +4056,7 @@
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
@@ -4067,12 +4069,12 @@
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
@@ -4910,7 +4912,7 @@
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.
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 4ecacc7..44fe134 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -191,6 +191,20 @@
};
/**
+ * 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,
+};
+
+
+/**
* struct msm_otg_platform_data - platform device data
* for msm_otg driver.
* @phy_init_seq: PHY configuration sequence. val, reg pairs
@@ -463,7 +477,7 @@
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;
int ui_enabled;
bool pm_done;