summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorJack Pham <jackp@codeaurora.org>2016-10-25 19:13:37 -0700
committerJack Pham <jackp@codeaurora.org>2016-10-26 09:11:04 -0700
commitdf63068acb2ce8f5410fda353795311d8132f550 (patch)
tree1f0e3e545eb9f6935032754d3ae1618e195276fc /drivers
parent46aa49c1188a77f52dc4969f82292c176d8f399b (diff)
usb: pd: Fix sink hard reset looping bug
commit f2449fb61a25 ("usb: pd: Clear PD_IN_HARD_RESET in PE_SNK_TRANSITION_TO_DEFAULT") introduced a subtle bug by moving the clearing of the pd->hard_reset flag in sink mode to the PE_SNK_TRANSITION_TO_DEFAULT state. This caused a regression in which the state machine acts as if it had received a hard reset signal and infinitely loops back there. The cycle could only be broken if a physical disconnect happens. Fix this by renaming the flag to hard_reset_recvd and only using it when receiving, and not sending a hard reset. Change-Id: I04008d0bfc9a874e08b45f78a937004e9f37527d Signed-off-by: Jack Pham <jackp@codeaurora.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/pd/policy_engine.c30
1 files changed, 12 insertions, 18 deletions
diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c
index a72c874f19a5..2eef9052bd00 100644
--- a/drivers/usb/pd/policy_engine.c
+++ b/drivers/usb/pd/policy_engine.c
@@ -274,7 +274,7 @@ struct usbpd {
struct extcon_dev *extcon;
enum usbpd_state current_state;
- bool hard_reset;
+ bool hard_reset_recvd;
u8 rx_msg_type;
u8 rx_msg_len;
u32 rx_payload[7];
@@ -487,16 +487,12 @@ static int pd_eval_src_caps(struct usbpd *pd, const u32 *src_caps)
static void pd_send_hard_reset(struct usbpd *pd)
{
- int ret;
-
usbpd_dbg(&pd->dev, "send hard reset");
/* Force CC logic to source/sink to keep Rp/Rd unchanged */
set_power_role(pd, pd->current_pr);
pd->hard_reset_count++;
- ret = pd_phy_signal(HARD_RESET_SIG, 5); /* tHardResetComplete */
- if (!ret)
- pd->hard_reset = true;
+ pd_phy_signal(HARD_RESET_SIG, 5); /* tHardResetComplete */
pd->in_pr_swap = false;
}
@@ -522,7 +518,7 @@ static void phy_sig_received(struct usbpd *pd, enum pd_sig_type type)
/* Force CC logic to source/sink to keep Rp/Rd unchanged */
set_power_role(pd, pd->current_pr);
- pd->hard_reset = true;
+ pd->hard_reset_recvd = true;
kick_sm(pd, 0);
}
@@ -754,8 +750,6 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
break;
case PE_SRC_TRANSITION_TO_DEFAULT:
- pd->hard_reset = false;
-
if (pd->vconn_enabled)
regulator_disable(pd->vconn);
regulator_disable(pd->vbus);
@@ -1403,7 +1397,7 @@ static void usbpd_sm(struct work_struct *w)
pd->in_pr_swap = false;
pd->pd_connected = false;
pd->in_explicit_contract = false;
- pd->hard_reset = false;
+ pd->hard_reset_recvd = false;
pd->caps_count = 0;
pd->hard_reset_count = 0;
pd->src_cap_id = 0;
@@ -1456,7 +1450,9 @@ static void usbpd_sm(struct work_struct *w)
}
/* Hard reset? */
- if (pd->hard_reset) {
+ if (pd->hard_reset_recvd) {
+ pd->hard_reset_recvd = false;
+
val.intval = 1;
power_supply_set_property(pd->usb_psy,
POWER_SUPPLY_PROP_PD_IN_HARD_RESET, &val);
@@ -1829,8 +1825,6 @@ static void usbpd_sm(struct work_struct *w)
break;
case PE_SNK_TRANSITION_TO_DEFAULT:
- pd->hard_reset = false;
-
val.intval = 0;
power_supply_set_property(pd->usb_psy,
POWER_SUPPLY_PROP_PD_IN_HARD_RESET, &val);
@@ -2117,11 +2111,11 @@ static int psy_changed(struct notifier_block *nb, unsigned long evt, void *ptr)
* During hard reset when VBUS goes to 0 the CC logic
* will report this as a disconnection. In those cases
* it can be ignored, however the downside is that
- * pd->hard_reset can be momentarily true even when a
- * non-PD capable source is attached, and can't be
- * distinguished from a physical disconnect. In that
- * case, allow for the common case of disconnecting
- * from an SDP.
+ * we can also happen to be in the SNK_Transition_to_default
+ * state due to a hard reset attempt even with a non-PD
+ * capable source, in which a physical disconnect may get
+ * masked. In that case, allow for the common case of
+ * disconnecting from an SDP.
*
* The less common case is a PD-capable SDP which will
* result in a hard reset getting treated like a