From f18eeff0fc684bd4240258b2a35327d66725232b Mon Sep 17 00:00:00 2001 From: Scott Chao Date: Thu, 12 Jan 2023 16:01:36 +0800 Subject: tcpci: handle tcpc tx discarded event MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In Revision 2.0, Version 1.3 USB Type-C® Port Controller Interface Specification 4.7.1. If the transmission was discarded due to an incoming received message, the TCPC sets the TransmitSOP*MessageDiscarded bit in the ALERT register. In the old process, TCPM will always send soft reset if TCPC did not set TransmitSOP*MessageSuccessful. It will cause the pending message be cleared. For example, when TCPC get ATTENTION from USB-C dock and TCPM send GET_SINK_CAP to TCPC at the same time. The TCPC will set TransmitSOP*MessageDiscarded and TCPM will send soft reset and cause TCPM did not get ATTENTION message. BUG=b:265247056 BRANCH=none TEST=make sure dock can display. TEST=make buildall TEST=./twister -v -T zephyr/test Change-Id: I2597894c1f7abceea3c352ba1066d270d2d01ba0 Signed-off-by: Scott Chao Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4160814 Reviewed-by: Diana Z --- driver/tcpm/tcpci.c | 16 ++++-- .../src/usb_malfunction_sink.c | 61 ++++++++++++++++++++-- 2 files changed, 70 insertions(+), 7 deletions(-) diff --git a/driver/tcpm/tcpci.c b/driver/tcpm/tcpci.c index 7924f653b7..84fdbe8cbc 100644 --- a/driver/tcpm/tcpci.c +++ b/driver/tcpm/tcpci.c @@ -1221,10 +1221,18 @@ void tcpci_tcpc_alert(int port) * completion events. This will send an event to the PD tasks * immediately */ - if (alert & TCPC_REG_ALERT_TX_COMPLETE) - pd_transmit_complete(port, alert & TCPC_REG_ALERT_TX_SUCCESS ? - TCPC_TX_COMPLETE_SUCCESS : - TCPC_TX_COMPLETE_FAILED); + if (alert & TCPC_REG_ALERT_TX_COMPLETE) { + int tx_status; + + if (alert & TCPC_REG_ALERT_TX_SUCCESS) + tx_status = TCPC_TX_COMPLETE_SUCCESS; + else if (alert & TCPC_REG_ALERT_TX_DISCARDED) + tx_status = TCPC_TX_COMPLETE_DISCARDED; + else + tx_status = TCPC_TX_COMPLETE_FAILED; + + pd_transmit_complete(port, tx_status); + } tcpc_get_bist_test_mode(port, &bist_mode); diff --git a/zephyr/test/drivers/usb_malfunction_sink/src/usb_malfunction_sink.c b/zephyr/test/drivers/usb_malfunction_sink/src/usb_malfunction_sink.c index fd6cab7bad..dd50f2b35b 100644 --- a/zephyr/test/drivers/usb_malfunction_sink/src/usb_malfunction_sink.c +++ b/zephyr/test/drivers/usb_malfunction_sink/src/usb_malfunction_sink.c @@ -248,14 +248,14 @@ ZTEST_F(usb_malfunction_sink, test_ignore_source_cap_and_pd_disable) struct ec_response_typec_status typec_status; /* - * Ignore first SourceCapabilities message and discard others by sending - * different messages. This will lead to PD disable. + * Ignore first SourceCapabilities message and failed others. + * This will lead to PD disable. */ fixture->actions[0].action_mask = TCPCI_FAULTY_EXT_IGNORE_SRC_CAP; fixture->actions[0].count = 1; tcpci_faulty_ext_append_action(&fixture->faulty_snk_ext, &fixture->actions[0]); - fixture->actions[1].action_mask = TCPCI_FAULTY_EXT_DISCARD_SRC_CAP; + fixture->actions[1].action_mask = TCPCI_FAULTY_EXT_FAIL_SRC_CAP; fixture->actions[1].count = TCPCI_FAULTY_EXT_INFINITE_ACTION; tcpci_faulty_ext_append_action(&fixture->faulty_snk_ext, &fixture->actions[1]); @@ -270,3 +270,58 @@ ZTEST_F(usb_malfunction_sink, test_ignore_source_cap_and_pd_disable) zassert_true(typec_status.dev_connected); zassert_false(typec_status.sop_connected); } + +ZTEST_F(usb_malfunction_sink, test_discard_source_cap) +{ + struct tcpci_partner_log_msg *msg; + uint16_t header; + int msg_cnt = 0; + + /* + * Discard SourceCapabilities messages, this will lead to SoftReset. + */ + fixture->actions[0].action_mask = TCPCI_FAULTY_EXT_DISCARD_SRC_CAP; + fixture->actions[0].count = TCPCI_FAULTY_EXT_INFINITE_ACTION; + tcpci_faulty_ext_append_action(&fixture->faulty_snk_ext, + &fixture->actions[0]); + + tcpci_partner_common_enable_pd_logging(&fixture->sink, true); + connect_sink_to_port(&fixture->sink, fixture->tcpci_emul, + fixture->charger_emul); + tcpci_partner_common_enable_pd_logging(&fixture->sink, false); + + /* + * Check if SourceCapability message alternate with Accept and + * SoftReset. + * The sequence will be + * TCPM: SourceCapability -> TCPC: Accept -> TCPM: SoftReset -> + * TCPC: Accept + */ + SYS_SLIST_FOR_EACH_CONTAINER(&fixture->sink.msg_log, msg, node) + { + header = sys_get_le16(msg->buf); + + switch (msg_cnt % 4) { + case 0: + zassert_equal( + PD_HEADER_TYPE(header), PD_DATA_SOURCE_CAP, + "Expected message %d to be SourceCapabilities, not 0x%x", + msg_cnt, PD_HEADER_TYPE(header)); + break; + case 1: + case 3: + zassert_equal( + PD_HEADER_TYPE(header), PD_CTRL_ACCEPT, + "Expected message %d to be Accept, not 0x%x", + msg_cnt, PD_HEADER_TYPE(header)); + break; + case 2: + zassert_equal( + PD_HEADER_TYPE(header), PD_CTRL_SOFT_RESET, + "Expected message %d to be SoftReset, not 0x%x", + msg_cnt, PD_HEADER_TYPE(header)); + break; + } + msg_cnt++; + } +} -- cgit v1.2.1