diff options
author | Yilun Lin <yllin@chromium.org> | 2019-08-15 11:16:20 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2019-08-25 14:00:29 +0000 |
commit | e52f9b778894f07d67e76f2516193fa4c8c995b2 (patch) | |
tree | ddb0f26b66df2fcce06c5abdb522724d54d95165 | |
parent | 1830e59046b7f1482c8effb3e3541441499dddaa (diff) | |
download | chrome-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.c | 64 | ||||
-rw-r--r-- | common/usb_pd_tcpc.c | 31 | ||||
-rw-r--r-- | include/usb_pd_tcpc.h | 18 |
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 */ |