diff options
author | Diana Z <dzigterman@chromium.org> | 2021-05-07 15:58:00 -0600 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-06-01 21:16:42 +0000 |
commit | baef8699dcc089643fddc56f31fb4b4b9aab7e4d (patch) | |
tree | 401a83797f1a18ba175bf741390ee23bf3643dad /common/usbc/usb_pe_drp_sm.c | |
parent | aba2646790307038bc9743a83a8b685c053e5ca1 (diff) | |
download | chrome-ec-baef8699dcc089643fddc56f31fb4b4b9aab7e4d.tar.gz |
TCPMv2: Re-enable SOP' transmission on interruption to Vconn swap
If a Vconn swap is interrupted before we receive a PS_RDY from the
partner, re-enable SOP' transition. Note this doesn't matter for the
case of no PS_RDY received as we'll proceed to hard reset which will
also reset our Vconn role. This is primarily applicable if the
interruption is for an unexpected message, which interrupts the swap and
leaves us the Vconn source.
BRANCH=volteer
BUG=b:186886218
TEST=on drobit, ensure cable entry doesn't fail after failed Vconn swap
with dock
Signed-off-by: Diana Z <dzigterman@chromium.org>
Change-Id: I952c04535ae9527f07cb203c403a51182c67cba7
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2881020
Tested-by: Benson Leung <bleung@google.com>
Reviewed-by: Abe Levkoy <alevkoy@chromium.org>
Reviewed-by: Keith Short <keithshort@chromium.org>
Diffstat (limited to 'common/usbc/usb_pe_drp_sm.c')
-rw-r--r-- | common/usbc/usb_pe_drp_sm.c | 64 |
1 files changed, 39 insertions, 25 deletions
diff --git a/common/usbc/usb_pe_drp_sm.c b/common/usbc/usb_pe_drp_sm.c index b819e9abfa..90fe07470b 100644 --- a/common/usbc/usb_pe_drp_sm.c +++ b/common/usbc/usb_pe_drp_sm.c @@ -6199,23 +6199,6 @@ static void pe_vcs_evaluate_swap_entry(int port) /* NOTE: PE_VCS_Accept_Swap State embedded here */ PE_SET_FLAG(port, PE_FLAGS_ACCEPT); send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_ACCEPT); - - /* - * The USB PD 3.0 spec indicates that the initial VCONN source - * shall cease sourcing VCONN within tVCONNSourceOff (25ms) - * after receiving the PS_RDY message. However, some partners - * begin sending SOP' messages only 1 ms after sending PS_RDY - * during VCONN swap. - * - * Preemptively disable receipt of SOP' and SOP'' messages while - * we wait for PS_RDY so we don't attempt to process messages - * directed at the cable. If the partner fails to send PS_RDY we - * perform a hard reset so no need to re-enable SOP' messages. - * - * We continue to source VCONN while we wait as required by the - * spec. - */ - tcpm_sop_prime_enable(port, false); } } @@ -6295,11 +6278,6 @@ static void pe_vcs_send_swap_run(int port) */ if (type == PD_CTRL_ACCEPT) { if (tc_is_vconn_src(port)) { - /* - * Prevent receiving any SOP' and SOP'' - * messages while a swap is in progress. - */ - tcpm_sop_prime_enable(port, false); set_state_pe(port, PE_VCS_WAIT_FOR_VCONN_SWAP); } else { @@ -6354,6 +6332,22 @@ static void pe_vcs_wait_for_vconn_swap_entry(int port) /* Start the VCONNOnTimer */ pd_timer_enable(port, PE_TIMER_VCONN_ON, PD_T_VCONN_SOURCE_ON); + + /* + * The USB PD 3.0 spec indicates that the initial VCONN source + * shall cease sourcing VCONN within tVCONNSourceOff (25ms) + * after receiving the PS_RDY message. However, some partners + * begin sending SOP' messages only 1 ms after sending PS_RDY + * during VCONN swap. + * + * Preemptively disable receipt of SOP' and SOP'' messages while + * we wait for PS_RDY so we don't attempt to process messages + * directed at the cable. + * + * We continue to source VCONN while we wait as required by the + * spec. + */ + tcpm_sop_prime_enable(port, false); } static void pe_vcs_wait_for_vconn_swap_run(int port) @@ -6363,15 +6357,26 @@ static void pe_vcs_wait_for_vconn_swap_run(int port) * 1) A PS_RDY Message is received. */ if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) { - PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED); /* * PS_RDY message received + * + * Note: intentionally leave the receive flag set to indicate + * our route on exit when PS_RDY is received. */ if ((PD_HEADER_CNT(rx_emsg[port].header) == 0) && - (PD_HEADER_TYPE(rx_emsg[port].header) == - PD_CTRL_PS_RDY)) { + (PD_HEADER_EXT(rx_emsg[port].header) == 0) && + (PD_HEADER_TYPE(rx_emsg[port].header) == PD_CTRL_PS_RDY)) { set_state_pe(port, PE_VCS_TURN_OFF_VCONN_SWAP); return; + } else { + /* + * Unexpected message received - reset with the SOP* of + * the incoming message. + */ + PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED); + pe_send_soft_reset(port, + PD_HEADER_GET_SOP(rx_emsg[port].header)); + return; } } @@ -6390,6 +6395,15 @@ static void pe_vcs_wait_for_vconn_swap_run(int port) static void pe_vcs_wait_for_vconn_swap_exit(int port) { + /* + * If we exited without getting PS_RDY, re-enable SOP' messaging since + * we are still the Vconn source. + */ + if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) + PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED); + else + tcpm_sop_prime_enable(port, true); + pd_timer_disable(port, PE_TIMER_VCONN_ON); } |