summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorScott Collyer <scollyer@google.com>2021-03-11 11:11:14 -0800
committerCommit Bot <commit-bot@chromium.org>2021-03-31 19:29:58 +0000
commit7285b915683d22675be649776009cac268182130 (patch)
tree8f7ba26a544b0439019b9475bec72be52812fb3d /common
parent3734bffbe0538101dec858b60542a5a40fe2bb81 (diff)
downloadchrome-ec-7285b915683d22675be649776009cac268182130.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>
Diffstat (limited to 'common')
-rw-r--r--common/usbc/usb_prl_sm.c42
1 files changed, 28 insertions, 14 deletions
diff --git a/common/usbc/usb_prl_sm.c b/common/usbc/usb_prl_sm.c
index 34f0ff251d..3ee3615104 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);
}