diff options
author | Scott Chao <scott_chao@wistron.corp-partner.google.com> | 2023-01-12 16:01:36 +0800 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2023-01-18 22:56:20 +0000 |
commit | f18eeff0fc684bd4240258b2a35327d66725232b (patch) | |
tree | a0af38c5c50639ca05431bf05a48eac6f5fdb1ed | |
parent | bcdc60f600c507d99cab3dc9b98c3b8987b90411 (diff) | |
download | chrome-ec-f18eeff0fc684bd4240258b2a35327d66725232b.tar.gz |
tcpci: handle tcpc tx discarded event
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 <scott_chao@wistron.corp-partner.google.com>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4160814
Reviewed-by: Diana Z <dzigterman@chromium.org>
-rw-r--r-- | driver/tcpm/tcpci.c | 16 | ||||
-rw-r--r-- | zephyr/test/drivers/usb_malfunction_sink/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++; + } +} |