summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYilun Lin <yllin@chromium.org>2019-08-15 11:16:20 +0800
committerCommit Bot <commit-bot@chromium.org>2019-08-25 14:00:29 +0000
commite52f9b778894f07d67e76f2516193fa4c8c995b2 (patch)
treeddb0f26b66df2fcce06c5abdb522724d54d95165
parent1830e59046b7f1482c8effb3e3541441499dddaa (diff)
downloadchrome-ec-e52f9b778894f07d67e76f2516193fa4c8c995b2.tar.gz
tcpm: ignore repeated MessageID
Ignore repeated MessageID in TCPM rather than TCPC[1]. https://crrev.com/c/1513033 implemented the logic in TCPC, but according to spec[2], TCPC should pass repeated messages to TCPM. This CL simply moves the logic from TCPC to TCPM. [1] USB PD spec rev3.0 6.7.1.2 MessageID Counter Receiver Usage [2] USB Port Controller spec rev2.0 3.3 USB-PD Message Delivery * MessageID is not checked in the TCPC when a non-GoodCRC message is received. Retried messages that are received are passed to the TCPM via I2C BUG=b:134556286, b:129337537 BRANCH=None TEST=make buildall -j; See Krane boots; See servo_v4 boots. Ensure repeat request message triggered artificially are dropped without any side-effects. Cq-Depend: chromium:1763895 Change-Id: I362056d973a71f0940b1287511ffe9180f566fac Signed-off-by: Yilun Lin <yllin@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1757596 Reviewed-by: Jett Rink <jettrink@chromium.org> Reviewed-by: Aseda Aboagye <aaboagye@chromium.org>
-rw-r--r--common/usb_pd_protocol.c64
-rw-r--r--common/usb_pd_tcpc.c31
-rw-r--r--include/usb_pd_tcpc.h18
3 files changed, 50 insertions, 63 deletions
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index be0d43ced2..eab4a4d959 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -188,6 +188,9 @@ static struct pd_protocol {
/* status of last transmit */
uint8_t tx_status;
+ /* Last received */
+ uint8_t last_msg_id;
+
/* last requested voltage PDO index */
int requested_idx;
#ifdef CONFIG_USB_PD_DUAL_ROLE
@@ -642,6 +645,48 @@ static void pd_update_saved_port_flags(int port, uint8_t flag, uint8_t val)
#endif /* defined(CONFIG_USB_PD_DUAL_ROLE) */
/**
+ * Invalidate last message received at the port when the port gets disconnected
+ * or reset(soft/hard). This is used to identify and handle the duplicate
+ * messages.
+ *
+ * @param port USB PD TCPC port number
+ */
+static void invalidate_last_message_id(int port)
+{
+ /*
+ * Message id starts from 0 to 7. If last_msg_id is initialized to 0,
+ * it will lead to repetitive message id with first received packet,
+ * so initialize it with an invalid value 0xff.
+ */
+ pd[port].last_msg_id = 0xff;
+}
+
+/**
+ * Identify and drop any duplicate messages received at the port.
+ *
+ * @param port USB PD TCPC port number
+ * @param msg_header Message Header containing the RX message ID
+ * @return 1 if the received message is a duplicate one, 0 otherwise.
+ */
+static int consume_repeat_message(int port, uint16_t msg_header)
+{
+ uint8_t msg_id = PD_HEADER_ID(msg_header);
+
+ /* If repeat message ignore, except softreset control request. */
+ if (PD_HEADER_TYPE(msg_header) == PD_CTRL_SOFT_RESET &&
+ PD_HEADER_CNT(msg_header) == 0) {
+ return 0;
+ } else if (pd[port].last_msg_id != msg_id) {
+ pd[port].last_msg_id = msg_id;
+ } else if (pd[port].last_msg_id == msg_id) {
+ CPRINTF("C%d Repeat msg_id %d\n", port, msg_id);
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
* Returns true if the port is currently in the try src state.
*/
static inline int is_try_src(int port)
@@ -778,14 +823,8 @@ static inline void set_state(int port, enum pd_states next_state)
/* Disable TCPC RX */
tcpm_set_rx_enable(port, 0);
-#ifdef CONFIG_USB_PD_TCPC
- /*
- * Invalidate message IDs for PD_TCPC only, since off-board
- * TCPCs will automatically perform message id de-dup logic
- * without manual intervention.
- */
+ /* Invalidate message IDs. */
invalidate_last_message_id(port);
-#endif /* CONFIG_USB_PD_TCPC */
#ifdef CONFIG_COMMON_RUNTIME
/* detect USB PD cc disconnect */
hook_notify(HOOK_USB_PD_DISCONNECT);
@@ -1336,6 +1375,7 @@ void pd_execute_hard_reset(int port)
CPRINTF("C%d HARD RST RX\n", port);
pd[port].msg_id = 0;
+ invalidate_last_message_id(port);
#ifdef CONFIG_USB_PD_ALT_MODE_DFP
pd_dfp_exit_mode(port, 0, 0);
#endif
@@ -1400,6 +1440,7 @@ void pd_execute_hard_reset(int port)
static void execute_soft_reset(int port)
{
pd[port].msg_id = 0;
+ invalidate_last_message_id(port);
set_state(port, DUAL_ROLE_IF_ELSE(port, PD_STATE_SNK_DISCOVERY,
PD_STATE_SRC_DISCOVERY));
CPRINTF("C%d Soft Rst\n", port);
@@ -2843,6 +2884,7 @@ void pd_task(void *u)
/* Initialize TCPM driver and wait for TCPC to be ready */
res = reset_device_and_notify(port);
+ invalidate_last_message_id(port);
#ifdef CONFIG_USB_PD_DUAL_ROLE
pd_partner_port_reset(port);
@@ -3121,16 +3163,10 @@ void pd_task(void *u)
/* process any potential incoming message */
incoming_packet = tcpm_has_pending_message(port);
if (incoming_packet) {
- /*
- * Dequeue and consume duplicate message ID for PD_TCPC
- * only, since off-board TCPCs will automatically
- * perform this de-dup logic before notifying the EC.
- */
+ /* Dequeue and consume duplicate message ID. */
if (tcpm_dequeue_message(port, payload, &head) ==
EC_SUCCESS
-#ifdef CONFIG_USB_PD_TCPC
&& !consume_repeat_message(port, head)
-#endif
)
handle_request(port, head, payload);
diff --git a/common/usb_pd_tcpc.c b/common/usb_pd_tcpc.c
index ae8c2746a6..5decbb0dec 100644
--- a/common/usb_pd_tcpc.c
+++ b/common/usb_pd_tcpc.c
@@ -257,7 +257,6 @@ static struct pd_port_controller {
int rx_head[RX_BUFFER_SIZE+1];
uint32_t rx_payload[RX_BUFFER_SIZE+1][7];
int rx_buf_head, rx_buf_tail;
- uint8_t msg_id_last;
/* Next transmit */
enum tcpm_transmit_type tx_type;
@@ -266,34 +265,6 @@ static struct pd_port_controller {
const uint32_t *tx_data;
} pd[CONFIG_USB_PD_PORT_COUNT];
-void invalidate_last_message_id(int port)
-{
- /*
- * Message id starts from 0 to 7. If msg_id_last is initialized to 0,
- * it will lead to repetitive message id with first received packet,
- * so initialize it with an invalid value 0xff.
- */
- pd[port].msg_id_last = 0xff;
-}
-
-int consume_repeat_message(int port, uint16_t msg_header)
-{
- uint8_t msg_id = PD_HEADER_ID(msg_header);
-
- /* If repeat message ignore, except softreset control request. */
- if (PD_HEADER_TYPE(msg_header) == PD_CTRL_SOFT_RESET &&
- PD_HEADER_CNT(msg_header) == 0) {
- invalidate_last_message_id(port);
- } else if (pd[port].msg_id_last != msg_id) {
- pd[port].msg_id_last = msg_id;
- } else if (pd[port].msg_id_last == msg_id) {
- CPRINTF("Repeat msg_id[%d] port[%d]\n", msg_id, port);
- return 1;
- }
-
- return 0;
-}
-
static int rx_buf_is_full(int port)
{
/*
@@ -680,7 +651,6 @@ int pd_analyze_rx(int port, uint32_t *payload)
bit = pd_find_preamble(port);
if (bit == PD_RX_ERR_HARD_RESET || bit == PD_RX_ERR_CABLE_RESET) {
/* Hard reset or cable reset */
- invalidate_last_message_id(port);
return bit;
} else if (bit < 0) {
msg = "Preamble";
@@ -1215,7 +1185,6 @@ void tcpc_init(int port)
/* make sure PD monitoring is disabled initially */
pd[port].rx_enabled = 0;
- invalidate_last_message_id(port);
/* make initial readings of CC voltages */
for (i = 0; i < 2; i++) {
diff --git a/include/usb_pd_tcpc.h b/include/usb_pd_tcpc.h
index 3f6fa2d139..4ac22d4d86 100644
--- a/include/usb_pd_tcpc.h
+++ b/include/usb_pd_tcpc.h
@@ -63,22 +63,4 @@ int tcpc_transmit(int port, enum tcpm_transmit_type type, uint16_t header,
int rx_buf_is_empty(int port);
void rx_buf_clear(int port);
-/**
- * Invalidate last message received at the port when the port gets disconnected
- * or reset(soft/hard). This is used to identify and handle the duplicate
- * messages.
- *
- * @param port USB PD TCPC port number
- */
-void invalidate_last_message_id(int port);
-
-/**
- * Identify and drop any duplicate messages received at the port.
- *
- * @param port USB PD TCPC port number
- * @param msg_header Message Header containing the RX message ID
- * @return 1 if the received message is a duplicate one, 0 otherwise.
- */
-int consume_repeat_message(int port, uint16_t msg_header);
-
#endif /* __CROS_EC_USB_PD_TCPC_H */