summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaveh Jalali <caveh@chromium.org>2019-06-12 00:59:17 -0700
committerBob Moragues <moragues@chromium.org>2019-06-15 02:16:33 +0000
commit11c39dba3ff1dced5c18db57116310140f2cc66d (patch)
tree928c2e4326c27956a8d30d9481951d43d314a3ef
parent1adcdd597f7d487404eaf63a3a80d1bd511ce13d (diff)
downloadchrome-ec-11c39dba3ff1dced5c18db57116310140f2cc66d.tar.gz
pd_protocol: add hard_reset_complete_timer
certain chargers have noisy CC lines which can prevent overly sensitive TCPCs from detecting a bus idle state. this means the TCPC will not send out messages such as hard_reset. this condition may not clear which means our pd_task() will retry sending hard_resets. although we specify a "timeout" for the event loop in this state, the timeout can be ignored by the event wait when there are pending events. this gets us into a tight event processing loop that starves the watchdog! the solution is to add an explicit timeout timer when processing the PD_STATE_HARD_RESET_SEND state. BUG=b:134702480 BRANCH=none TEST=no more EC watchdog on affected systems Change-Id: I207323fd9cff06487c56e2edec5e9c30f4517ee3 Signed-off-by: Caveh Jalali <caveh@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1654872 Commit-Queue: Bob Moragues <moragues@chromium.org> Reviewed-by: Bob Moragues <moragues@chromium.org> Reviewed-by: Aseda Aboagye <aaboagye@chromium.org>
-rw-r--r--common/usb_pd_protocol.c59
-rw-r--r--include/usb_pd.h69
2 files changed, 73 insertions, 55 deletions
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index fa7904c9eb..084e765a64 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -249,6 +249,11 @@ static struct pd_protocol {
* of our own.
*/
uint64_t ready_state_holdoff_timer;
+ /*
+ * PD 2.0 spec, section 6.5.11.1
+ * When we can give up on a HARD_RESET transmission.
+ */
+ uint64_t hard_reset_complete_timer;
} pd[CONFIG_USB_PD_PORT_COUNT];
#ifdef CONFIG_COMMON_RUNTIME
@@ -4041,8 +4046,10 @@ void pd_task(void *u)
break;
case PD_STATE_HARD_RESET_SEND:
hard_reset_count++;
- if (pd[port].last_state != pd[port].task_state)
+ if (pd[port].last_state != pd[port].task_state) {
hard_reset_sent = 0;
+ pd[port].hard_reset_complete_timer = 0;
+ }
#ifdef CONFIG_CHARGE_MANAGER
if (pd[port].last_state == PD_STATE_SNK_DISCOVERY ||
(pd[port].last_state == PD_STATE_SOFT_RESET &&
@@ -4062,29 +4069,39 @@ void pd_task(void *u)
}
#endif
+ if (hard_reset_sent)
+ break;
/* try sending hard reset until it succeeds */
- if (!hard_reset_sent) {
- if (pd_transmit(port, TCPC_TX_HARD_RESET,
- 0, NULL) < 0) {
- timeout = 10*MSEC;
- break;
- }
+ now = get_time();
+ if (now.val < pd[port].hard_reset_complete_timer) {
+ CPRINTF("C%d: Waiting for "
+ "hard reset complete timer\n", port);
+ timeout = pd[port].hard_reset_complete_timer -
+ now.val;
+ break;
+ }
+ if (pd_transmit(port, TCPC_TX_HARD_RESET,
+ 0, NULL) < 0) {
+ timeout = PD_T_HARD_RESET_COMPLETE;
+ pd[port].hard_reset_complete_timer =
+ get_time().val + timeout;
+ break;
+ }
- /* successfully sent hard reset */
- hard_reset_sent = 1;
- /*
- * If we are source, delay before cutting power
- * to allow sink time to get hard reset.
- */
- if (pd[port].power_role == PD_ROLE_SOURCE) {
- set_state_timeout(port,
- get_time().val + PD_T_PS_HARD_RESET,
+ /* successfully sent hard reset */
+ hard_reset_sent = 1;
+ /*
+ * If we are source, delay before cutting power
+ * to allow sink time to get hard reset.
+ */
+ if (pd[port].power_role == PD_ROLE_SOURCE) {
+ set_state_timeout(port,
+ get_time().val + PD_T_PS_HARD_RESET,
+ PD_STATE_HARD_RESET_EXECUTE);
+ } else {
+ set_state(port,
PD_STATE_HARD_RESET_EXECUTE);
- } else {
- set_state(port,
- PD_STATE_HARD_RESET_EXECUTE);
- timeout = 10*MSEC;
- }
+ timeout = 10*MSEC;
}
break;
case PD_STATE_HARD_RESET_EXECUTE:
diff --git a/include/usb_pd.h b/include/usb_pd.h
index 7cc1a58021..ece23eef17 100644
--- a/include/usb_pd.h
+++ b/include/usb_pd.h
@@ -150,37 +150,38 @@ enum pd_rx_errors {
#define SVID_DISCOVERY_MAX 16
/* Timers */
-#define PD_T_SINK_TX (18*MSEC) /* between 16ms and 20 */
-#define PD_T_CHUNK_SENDER_RSP (24*MSEC) /* between 24ms and 30ms */
-#define PD_T_CHUNK_SENDER_REQ (24*MSEC) /* between 24ms and 30ms */
-#define PD_T_SEND_SOURCE_CAP (100*MSEC) /* between 100ms and 200ms */
-#define PD_T_SINK_WAIT_CAP (600*MSEC) /* between 310ms and 620ms */
-#define PD_T_SINK_TRANSITION (35*MSEC) /* between 20ms and 35ms */
-#define PD_T_SOURCE_ACTIVITY (45*MSEC) /* between 40ms and 50ms */
-#define PD_T_SENDER_RESPONSE (30*MSEC) /* between 24ms and 30ms */
-#define PD_T_PS_TRANSITION (500*MSEC) /* between 450ms and 550ms */
-#define PD_T_PS_SOURCE_ON (480*MSEC) /* between 390ms and 480ms */
-#define PD_T_PS_SOURCE_OFF (920*MSEC) /* between 750ms and 920ms */
-#define PD_T_PS_HARD_RESET (25*MSEC) /* between 25ms and 35ms */
-#define PD_T_ERROR_RECOVERY (25*MSEC) /* 25ms */
+#define PD_T_SINK_TX (18*MSEC) /* between 16ms and 20 */
+#define PD_T_CHUNK_SENDER_RSP (24*MSEC) /* between 24ms and 30ms */
+#define PD_T_CHUNK_SENDER_REQ (24*MSEC) /* between 24ms and 30ms */
+#define PD_T_HARD_RESET_COMPLETE (5*MSEC) /* between 4ms and 5ms*/
+#define PD_T_SEND_SOURCE_CAP (100*MSEC) /* between 100ms and 200ms */
+#define PD_T_SINK_WAIT_CAP (600*MSEC) /* between 310ms and 620ms */
+#define PD_T_SINK_TRANSITION (35*MSEC) /* between 20ms and 35ms */
+#define PD_T_SOURCE_ACTIVITY (45*MSEC) /* between 40ms and 50ms */
+#define PD_T_SENDER_RESPONSE (30*MSEC) /* between 24ms and 30ms */
+#define PD_T_PS_TRANSITION (500*MSEC) /* between 450ms and 550ms */
+#define PD_T_PS_SOURCE_ON (480*MSEC) /* between 390ms and 480ms */
+#define PD_T_PS_SOURCE_OFF (920*MSEC) /* between 750ms and 920ms */
+#define PD_T_PS_HARD_RESET (25*MSEC) /* between 25ms and 35ms */
+#define PD_T_ERROR_RECOVERY (25*MSEC) /* 25ms */
#define PD_T_CC_DEBOUNCE (100*MSEC) /* between 100ms and 200ms */
/* DRP_SNK + DRP_SRC must be between 50ms and 100ms with 30%-70% duty cycle */
-#define PD_T_DRP_SNK (40*MSEC) /* toggle time for sink DRP */
-#define PD_T_DRP_SRC (30*MSEC) /* toggle time for source DRP */
-#define PD_T_DEBOUNCE (15*MSEC) /* between 10ms and 20ms */
-#define PD_T_SINK_ADJ (55*MSEC) /* between PD_T_DEBOUNCE and 60ms */
-#define PD_T_SRC_RECOVER (760*MSEC) /* between 660ms and 1000ms */
-#define PD_T_SRC_RECOVER_MAX (1000*MSEC) /* 1000ms */
-#define PD_T_SRC_TURN_ON (275*MSEC) /* 275ms */
-#define PD_T_SAFE_0V (650*MSEC) /* 650ms */
-#define PD_T_NO_RESPONSE (5500*MSEC) /* between 4.5s and 5.5s */
-#define PD_T_BIST_TRANSMIT (50*MSEC) /* 50ms (used for task_wait arg) */
-#define PD_T_BIST_RECEIVE (60*MSEC) /* 60ms (max time to process bist) */
-#define PD_T_VCONN_SOURCE_ON (100*MSEC) /* 100ms */
-#define PD_T_DRP_TRY (125*MSEC) /* btween 75 and 150ms(monitor Vbus) */
-#define PD_T_TRY_TIMEOUT (550*MSEC) /* between 550ms and 1100ms */
-#define PD_T_TRY_WAIT (600*MSEC) /* Max time for TryWait.SNK state */
-#define PD_T_SINK_REQUEST (100*MSEC) /* Wait 100ms before next request */
+#define PD_T_DRP_SNK (40*MSEC) /* toggle time for sink DRP */
+#define PD_T_DRP_SRC (30*MSEC) /* toggle time for source DRP */
+#define PD_T_DEBOUNCE (15*MSEC) /* between 10ms and 20ms */
+#define PD_T_SINK_ADJ (55*MSEC) /* between PD_T_DEBOUNCE and 60ms */
+#define PD_T_SRC_RECOVER (760*MSEC) /* between 660ms and 1000ms */
+#define PD_T_SRC_RECOVER_MAX (1000*MSEC) /* 1000ms */
+#define PD_T_SRC_TURN_ON (275*MSEC) /* 275ms */
+#define PD_T_SAFE_0V (650*MSEC) /* 650ms */
+#define PD_T_NO_RESPONSE (5500*MSEC) /* between 4.5s and 5.5s */
+#define PD_T_BIST_TRANSMIT (50*MSEC) /* 50ms (used for task_wait arg) */
+#define PD_T_BIST_RECEIVE (60*MSEC) /* 60ms (max time to process bist) */
+#define PD_T_VCONN_SOURCE_ON (100*MSEC) /* 100ms */
+#define PD_T_DRP_TRY (125*MSEC) /* btween 75 and 150ms(monitor Vbus) */
+#define PD_T_TRY_TIMEOUT (550*MSEC) /* between 550ms and 1100ms */
+#define PD_T_TRY_WAIT (600*MSEC) /* Max time for TryWait.SNK state */
+#define PD_T_SINK_REQUEST (100*MSEC) /* Wait 100ms before next request */
/* number of edges and time window to detect CC line is not idle */
#define PD_RX_TRANSITION_COUNT 3
@@ -190,11 +191,11 @@ enum pd_rx_errors {
#define PD_T_AME (1*SECOND) /* timeout from UFP attach to Alt Mode Entry */
/* VDM Timers ( USB PD Spec Rev2.0 Table 6-30 )*/
-#define PD_T_VDM_BUSY (100*MSEC) /* at least 100ms */
-#define PD_T_VDM_E_MODE (25*MSEC) /* enter/exit the same max */
-#define PD_T_VDM_RCVR_RSP (15*MSEC) /* max of 15ms */
-#define PD_T_VDM_SNDR_RSP (30*MSEC) /* max of 30ms */
-#define PD_T_VDM_WAIT_MODE_E (100*MSEC) /* enter/exit the same max */
+#define PD_T_VDM_BUSY (100*MSEC) /* at least 100ms */
+#define PD_T_VDM_E_MODE (25*MSEC) /* enter/exit the same max */
+#define PD_T_VDM_RCVR_RSP (15*MSEC) /* max of 15ms */
+#define PD_T_VDM_SNDR_RSP (30*MSEC) /* max of 30ms */
+#define PD_T_VDM_WAIT_MODE_E (100*MSEC) /* enter/exit the same max */
/* function table for entered mode */
struct amode_fx {