summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Collyer <scollyer@google.com>2021-03-11 11:11:14 -0800
committerCommit Bot <commit-bot@chromium.org>2021-04-01 17:59:46 +0000
commitabd9439d63e2a9e172b343d3990e9bb419d5eb66 (patch)
tree8ed618b222ca011b3b39021c0922c0f3f10b41be
parenta17fa216d466880d7045d57e0c07c5f8f4176c5e (diff)
downloadchrome-ec-abd9439d63e2a9e172b343d3990e9bb419d5eb66.tar.gz
TCPMv2: PRL: Enahnce support for the tx message discard path
This CL modifies the tx message discard path in the PRL. The states that should have triggered tx message discard events, would only act on messages pending from PE, but not passed yet to the phy. This behavior was required to account for the serial nature of the different PRL state machines and inherent delay in sending/receiving messages to/from off chip TCPCs via the I2C bus. This CL adds a new WAIT value to the xmit_status enum so that a message being sent to the phy but not reponse yet can be known. In addition, xmit_status == DISCARDED is no longer treated automatically as a protocol error. BUG=b:181179550,b:173028144 BRANCH=None TEST=Running VDMU.E16 compliance test. Validated that the SVDM command sequence is properly interrupted in most all cases. This test only fails if collision events are present which is a happening on honybuns for 2 reasons: 1) GRL test waits too long to interrupt the VDM command (~1 msec) 2) honeybuns ucpd is faster since it doesn't have i2c delays. Signed-off-by: Scott Collyer <scollyer@google.com> Change-Id: I2bec09b96d7f6ea6122fcb369246717950987ca8 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2752251 Tested-by: Scott Collyer <scollyer@chromium.org> Reviewed-by: Diana Z <dzigterman@chromium.org> Commit-Queue: Scott Collyer <scollyer@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2799918 Tested-by: Abe Levkoy <alevkoy@chromium.org> Reviewed-by: Abe Levkoy <alevkoy@chromium.org> Commit-Queue: Abe Levkoy <alevkoy@chromium.org>
-rw-r--r--common/usbc/usb_prl_sm.c42
-rw-r--r--include/usb_pd_tcpm.h7
2 files changed, 32 insertions, 17 deletions
diff --git a/common/usbc/usb_prl_sm.c b/common/usbc/usb_prl_sm.c
index 6c786b8a52..bc5b6fa453 100644
--- a/common/usbc/usb_prl_sm.c
+++ b/common/usbc/usb_prl_sm.c
@@ -844,6 +844,8 @@ static void prl_tx_phy_layer_reset_entry(const int port)
static void prl_tx_wait_for_message_request_entry(const int port)
{
+ /* No phy layer response is pending */
+ prl_tx[port].xmit_status = TCPC_TX_UNSET;
print_current_prl_tx_state(port);
}
@@ -936,8 +938,17 @@ static void prl_tx_discard_message_entry(const int port)
* Discard queued message
* Note: We differ from spec here, which allows us to not discard on
* incoming SOP' or SOP''. However this would get the TCH out of sync.
+ *
+ * prl_tx will be set to this state following message reception in
+ * prl_rx. So this path will be entered following each rx message. If
+ * this state is entered, and there is either a message from the PE
+ * pending, or if a message was passed to the phy and there is either no
+ * response yet, or it was discarded in the phy layer, then a tx message
+ * discard event has been detected.
*/
- if (PRL_TX_CHK_FLAG(port, PRL_FLAGS_MSG_XMIT)) {
+ if (PRL_TX_CHK_FLAG(port, PRL_FLAGS_MSG_XMIT) ||
+ prl_tx[port].xmit_status == TCPC_TX_WAIT ||
+ prl_tx[port].xmit_status == TCPC_TX_COMPLETE_DISCARDED) {
PRL_TX_CLR_FLAG(port, PRL_FLAGS_MSG_XMIT);
increment_msgid_counter(port);
pe_report_discard(port);
@@ -1058,12 +1069,13 @@ static void prl_tx_construct_message(const int port)
/* Save SOP* so the correct msg_id_counter can be incremented */
prl_tx[port].last_xmit_type = pdmsg[port].xmit_type;
+ /* Indicate that a tx message is being passed to the phy layer */
+ prl_tx[port].xmit_status = TCPC_TX_WAIT;
/*
- * These flags could be set if this function is called before the
- * Policy Engine is informed of the previous transmission. Clear the
- * flags so that this message can be sent.
+ * PRL_FLAGS_TX_COMPLETE could be set if this function is called before
+ * the Policy Engine is informed of the previous transmission. Clear the
+ * flag so that this message can be sent.
*/
- prl_tx[port].xmit_status = TCPC_TX_UNSET;
PDMSG_CLR_FLAG(port, PRL_FLAGS_TX_COMPLETE);
/*
@@ -1117,8 +1129,7 @@ static void prl_tx_wait_for_phy_response_run(const int port)
task_wake(PD_PORT_TO_TASK_ID(port));
set_state_prl_tx(port, PRL_TX_WAIT_FOR_MESSAGE_REQUEST);
} else if (pd_timer_is_expired(port, PR_TIMER_TCPC_TX_TIMEOUT) ||
- prl_tx[port].xmit_status == TCPC_TX_COMPLETE_FAILED ||
- prl_tx[port].xmit_status == TCPC_TX_COMPLETE_DISCARDED) {
+ prl_tx[port].xmit_status == TCPC_TX_COMPLETE_FAILED) {
/*
* NOTE: PRL_Tx_Transmission_Error State embedded
* here.
@@ -1144,7 +1155,6 @@ static void prl_tx_wait_for_phy_response_run(const int port)
static void prl_tx_wait_for_phy_response_exit(const int port)
{
- prl_tx[port].xmit_status = TCPC_TX_UNSET;
pd_timer_disable(port, PR_TIMER_TCPC_TX_TIMEOUT);
}
@@ -1852,13 +1862,17 @@ static void tch_wait_for_transmission_complete_run(const int port)
return;
}
/*
- * Any message received and not in state TCH_Wait_Chunk_Request
- * MUST be checked after transmission status due to our TCPC
- * architecture, and should not be checked if prl_tx is still waiting on
- * the TCPC.
+ * A message was received while TCH is waiting for the phy to complete
+ * sending a tx message.
+ *
+ * Because of our prl_sm architecture and I2C access delays for TCPCs,
+ * it's possible to have a message received and the prl_tx state not be
+ * in its default waiting state. To avoid a false protocol error, only
+ * jump to TCH_MESSAGE_RECEIVED if the phy layer has not indicated that
+ * the tx message was sent successfully.
*/
if (TCH_CHK_FLAG(port, PRL_FLAGS_MSG_RECEIVED) &&
- prl_tx_get_state(port) != PRL_TX_WAIT_FOR_PHY_RESPONSE) {
+ prl_tx[port].xmit_status != TCPC_TX_COMPLETE_SUCCESS) {
TCH_CLR_FLAG(port, PRL_FLAGS_MSG_RECEIVED);
set_state_tch(port, TCH_MESSAGE_RECEIVED);
return;
@@ -2199,7 +2213,7 @@ static void prl_rx_wait_for_phy_message(const int port, int evt)
* complete at the same time as a response so only do this if a
* message is pending.
*/
- if (prl_tx_get_state(port) != PRL_TX_WAIT_FOR_PHY_RESPONSE ||
+ if (prl_tx[port].xmit_status != TCPC_TX_COMPLETE_SUCCESS ||
PRL_TX_CHK_FLAG(port, PRL_FLAGS_MSG_XMIT))
set_state_prl_tx(port, PRL_TX_DISCARD_MESSAGE);
}
diff --git a/include/usb_pd_tcpm.h b/include/usb_pd_tcpm.h
index 8e461b43b6..df195d1832 100644
--- a/include/usb_pd_tcpm.h
+++ b/include/usb_pd_tcpm.h
@@ -81,9 +81,10 @@ enum tcpm_transmit_type {
enum tcpc_transmit_complete {
TCPC_TX_UNSET = -1,
- TCPC_TX_COMPLETE_SUCCESS = 0,
- TCPC_TX_COMPLETE_DISCARDED = 1,
- TCPC_TX_COMPLETE_FAILED = 2,
+ TCPC_TX_WAIT = 0,
+ TCPC_TX_COMPLETE_SUCCESS = 1,
+ TCPC_TX_COMPLETE_DISCARDED = 2,
+ TCPC_TX_COMPLETE_FAILED = 3,
};
/*