diff options
-rw-r--r-- | common/mock/usb_pe_sm_mock.c | 5 | ||||
-rw-r--r-- | common/usbc/usb_pe_ctvpd_sm.c | 5 | ||||
-rw-r--r-- | common/usbc/usb_pe_drp_sm.c | 151 | ||||
-rw-r--r-- | common/usbc/usb_prl_sm.c | 10 | ||||
-rw-r--r-- | include/mock/usb_pe_sm_mock.h | 1 | ||||
-rw-r--r-- | include/usb_pe_sm.h | 7 | ||||
-rw-r--r-- | test/usb_prl_old.c | 7 |
7 files changed, 115 insertions, 71 deletions
diff --git a/common/mock/usb_pe_sm_mock.c b/common/mock/usb_pe_sm_mock.c index 3edc3babd3..881d834b25 100644 --- a/common/mock/usb_pe_sm_mock.c +++ b/common/mock/usb_pe_sm_mock.c @@ -25,6 +25,11 @@ void pe_report_error(int port, enum pe_error e, enum tcpm_transmit_type type) mock_pe_port[port].sop = type; } +void pe_report_discard(int port) +{ + mock_pe_port[port].mock_pe_message_discarded = 1; +} + void pe_got_hard_reset(int port) { mock_pe_port[port].mock_pe_got_hard_reset = 1; diff --git a/common/usbc/usb_pe_ctvpd_sm.c b/common/usbc/usb_pe_ctvpd_sm.c index e4f3aeabd3..7dd8139832 100644 --- a/common/usbc/usb_pe_ctvpd_sm.c +++ b/common/usbc/usb_pe_ctvpd_sm.c @@ -109,6 +109,11 @@ void pe_report_error(int port, enum pe_error e, enum tcpm_transmit_type type) /* No implementation needed by this policy engine */ } +void pe_report_discard(int port) +{ + /* No implementation needed by this policy engine */ +} + void pe_got_soft_reset(int port) { /* No implementation needed by this policy engine */ diff --git a/common/usbc/usb_pe_drp_sm.c b/common/usbc/usb_pe_drp_sm.c index 053606f291..8e853ee665 100644 --- a/common/usbc/usb_pe_drp_sm.c +++ b/common/usbc/usb_pe_drp_sm.c @@ -140,6 +140,12 @@ #define PE_FLAGS_VCONN_SWAP_TO_ON BIT(28) /* FLAG to track that VDM request to port partner timed out */ #define PE_FLAGS_VDM_REQUEST_TIMEOUT BIT(29) +/* FLAG to note message was discarded due to incoming message */ +#define PE_FLAGS_MSG_DISCARDED BIT(30) + +/* Message flags which should not persist on returning to ready state */ +#define PE_FLAGS_READY_CLR (PE_FLAGS_LOCALLY_INITIATED_AMS \ + | PE_FLAGS_MSG_DISCARDED) /* 6.7.3 Hard Reset Counter */ #define N_HARD_RESET_COUNT 2 @@ -246,6 +252,9 @@ enum usb_pe_state { PE_BIST_RX, PE_DR_SNK_GET_SINK_CAP, + /* AMS Start parent - runs SenderResponseTimer */ + PE_SENDER_RESPONSE, + /* PD3.0 only states below here*/ PE_FRS_SNK_SRC_START_AMS, PE_GIVE_BATTERY_CAP, @@ -338,6 +347,8 @@ static const char * const pe_state_names[] = { [PE_BIST_RX] = "PE_Bist_RX", [PE_DR_SNK_GET_SINK_CAP] = "PE_DR_SNK_Get_Sink_Cap", + [PE_SENDER_RESPONSE] = "PE_SENDER_RESPONSE", + /* PD3.0 only states below here*/ #ifdef CONFIG_USB_PD_REV30 [PE_FRS_SNK_SRC_START_AMS] = "PE_FRS_SNK_SRC_Start_Ams", @@ -913,6 +924,18 @@ static void pe_send_soft_reset(const int port, enum tcpm_transmit_type type) set_state_pe(port, PE_SEND_SOFT_RESET); } +void pe_report_discard(int port) +{ + /* + * Clear local AMS indicator as our AMS message was discarded, and flag + * the discard for the PE + */ + PE_CLR_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS); + PE_SET_FLAG(port, PE_FLAGS_MSG_DISCARDED); + + /* TODO(b/157228506): Ensure all states are checking discard */ +} + void pe_report_error(int port, enum pe_error e, enum tcpm_transmit_type type) { /* This should only be called from the PD task */ @@ -1909,8 +1932,8 @@ static void pe_src_ready_entry(int port) { print_current_state(port); - /* Ensure any atomic message sequence is properly cleaned up */ - PE_CLR_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS); + /* Ensure any message send flags are cleaned up */ + PE_CLR_FLAG(port, PE_FLAGS_READY_CLR); /* * Wait and add jitter if we are operating in PD2.0 mode and no messages @@ -2647,8 +2670,8 @@ static void pe_snk_ready_entry(int port) { print_current_state(port); - /* Ensure any atomic message sequence is properly cleaned up */ - PE_CLR_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS); + /* Ensure any message send flags are cleaned up */ + PE_CLR_FLAG(port, PE_FLAGS_READY_CLR); /* * On entry to the PE_SNK_Ready state as the result of a wait, * then do the following: @@ -3414,8 +3437,6 @@ static void pe_drs_send_swap_entry(int port) */ /* Request the Protocol Layer to send a DR_Swap Message */ send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_DR_SWAP); - - pe[port].sender_response_timer = TIMER_DISABLED; } static void pe_drs_send_swap_run(int port) @@ -3424,25 +3445,6 @@ static void pe_drs_send_swap_run(int port) int cnt; int ext; - /* Wait until message is sent */ - if (pe[port].sender_response_timer == TIMER_DISABLED) { - if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) { - PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE); - /* Initialize and run SenderResponseTimer */ - pe[port].sender_response_timer = - get_time().val + PD_T_SENDER_RESPONSE; - } else if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) { - /* - * Message was received before outgoing message could - * send, go back to ready to handle this. - */ - set_state_pe(port, get_last_state_pe(port)); - return; - } else { - return; - } - } - /* * Transition to PE_DRS_Change when: * 1) An Accept Message is received. @@ -3647,10 +3649,6 @@ static void pe_prs_src_snk_send_swap_entry(int port) /* Request the Protocol Layer to send a PR_Swap Message. */ send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_PR_SWAP); - - /* Start the SenderResponseTimer */ - pe[port].sender_response_timer = - get_time().val + PD_T_SENDER_RESPONSE; } static void pe_prs_src_snk_send_swap_run(int port) @@ -3901,7 +3899,7 @@ static void pe_prs_snk_src_send_swap_entry(int port) /* Start the SenderResponseTimer */ pe[port].sender_response_timer = - get_time().val + PD_T_SENDER_RESPONSE; + get_time().val + PD_T_SENDER_RESPONSE; } static void pe_prs_snk_src_send_swap_run(int port) @@ -4197,6 +4195,18 @@ static void pe_vdm_send_request_run(int port) get_time().val + PD_T_VDM_SNDR_RSP; } + if (PE_CHK_FLAG(port, PE_FLAGS_MSG_DISCARDED)) { + /* + * Go back to ready on first AMS message discard + * (ready states will clear the discard flag) + */ + if (pe[port].power_role == PD_ROLE_SINK) + set_state_pe(port, PE_SNK_READY); + else + set_state_pe(port, PE_SRC_READY); + return; + } + /* * Check the VDM timer, child will be responsible for processing * messages and reacting appropriately to unexpected messages. @@ -5059,8 +5069,6 @@ static void pe_vcs_send_swap_entry(int port) /* Send a VCONN_Swap Message */ send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_VCONN_SWAP); - - pe[port].sender_response_timer = TIMER_DISABLED; } static void pe_vcs_send_swap_run(int port) @@ -5069,26 +5077,6 @@ static void pe_vcs_send_swap_run(int port) uint8_t cnt; enum tcpm_transmit_type sop; - /* Wait until message is sent */ - if (pe[port].sender_response_timer == TIMER_DISABLED && - PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) { - PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE); - /* Start the SenderResponseTimer */ - pe[port].sender_response_timer = get_time().val + - PD_T_SENDER_RESPONSE; - } - - if (pe[port].sender_response_timer == TIMER_DISABLED) { - /* - * Message was received before came before swap could send, go - * back to ready to handle it. - */ - if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) - set_state_pe(port, get_last_state_pe(port)); - - return; - } - if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) { PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED); @@ -5349,9 +5337,6 @@ static void pe_dr_snk_get_sink_cap_entry(int port) /* Send a Get Sink Cap Message */ send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_GET_SINK_CAP); - - /* Don't start the timer until message sent */ - pe[port].sender_response_timer = 0; } static void pe_dr_snk_get_sink_cap_run(int port) @@ -5361,18 +5346,6 @@ static void pe_dr_snk_get_sink_cap_run(int port) int ext; int rev; - /* Wait until message is sent */ - if (pe[port].sender_response_timer == 0) { - if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) { - PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE); - /* start the SenderResponseTimer */ - pe[port].sender_response_timer = - get_time().val + PD_T_SENDER_RESPONSE; - } else { - return; - } - } - /* * Determine if FRS is possible based on the returned Sink Caps * @@ -5440,6 +5413,42 @@ static void pe_dr_snk_get_sink_cap_run(int port) set_state_pe(port, PE_SNK_READY); } +/* + * PE_SENDER_RESPONSE + * + * Parent state to run first message in an AMS and start SenderResponseTimer + * appropriately. + */ +static void pe_sender_response_entry(int port) +{ + pe[port].sender_response_timer = TIMER_DISABLED; +} + +static void pe_sender_response_run(int port) +{ + if (PE_CHK_FLAG(port, PE_FLAGS_MSG_DISCARDED)) { + /* + * Go back to ready on first AMS message discard + * (ready states will clear the discard flag) + */ + if (pe[port].power_role == PD_ROLE_SINK) + set_state_pe(port, PE_SNK_READY); + else + set_state_pe(port, PE_SRC_READY); + return; + } + + if (pe[port].sender_response_timer == TIMER_DISABLED && + PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) { + PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE); + /* Initialize and run SenderResponseTimer */ + pe[port].sender_response_timer = + get_time().val + PD_T_SENDER_RESPONSE; + } + + /* Note: child must check timer, as response to a timeout varies */ +} + const uint32_t * const pd_get_src_caps(int port) { return pe[port].src_caps; @@ -5634,6 +5643,7 @@ static const struct usb_state pe_states[] = { [PE_DRS_SEND_SWAP] = { .entry = pe_drs_send_swap_entry, .run = pe_drs_send_swap_run, + .parent = &pe_states[PE_SENDER_RESPONSE], }, [PE_PRS_SRC_SNK_EVALUATE_SWAP] = { .entry = pe_prs_src_snk_evaluate_swap_entry, @@ -5655,6 +5665,7 @@ static const struct usb_state pe_states[] = { [PE_PRS_SRC_SNK_SEND_SWAP] = { .entry = pe_prs_src_snk_send_swap_entry, .run = pe_prs_src_snk_send_swap_run, + .parent = &pe_states[PE_SENDER_RESPONSE], }, [PE_PRS_SNK_SRC_EVALUATE_SWAP] = { .entry = pe_prs_snk_src_evaluate_swap_entry, @@ -5711,6 +5722,7 @@ static const struct usb_state pe_states[] = { [PE_VCS_SEND_SWAP] = { .entry = pe_vcs_send_swap_entry, .run = pe_vcs_send_swap_run, + .parent = &pe_states[PE_SENDER_RESPONSE], }, [PE_VCS_WAIT_FOR_VCONN_SWAP] = { .entry = pe_vcs_wait_for_vconn_swap_entry, @@ -5791,6 +5803,11 @@ static const struct usb_state pe_states[] = { [PE_DR_SNK_GET_SINK_CAP] = { .entry = pe_dr_snk_get_sink_cap_entry, .run = pe_dr_snk_get_sink_cap_run, + .parent = &pe_states[PE_SENDER_RESPONSE], + }, + [PE_SENDER_RESPONSE] = { + .entry = pe_sender_response_entry, + .run = pe_sender_response_run, }, }; diff --git a/common/usbc/usb_prl_sm.c b/common/usbc/usb_prl_sm.c index 3d2e7a5bc4..659e5f2cdc 100644 --- a/common/usbc/usb_prl_sm.c +++ b/common/usbc/usb_prl_sm.c @@ -860,9 +860,9 @@ static void prl_tx_discard_message_entry(const int port) * incoming SOP' or SOP''. However this would get the TCH out of sync. */ if (PRL_TX_CHK_FLAG(port, PRL_FLAGS_MSG_XMIT)) { - increment_msgid_counter(port); PRL_TX_CLR_FLAG(port, PRL_FLAGS_MSG_XMIT); - /* TODO(b/157228506): notify pe if needed */ + increment_msgid_counter(port); + pe_report_discard(port); } set_state_prl_tx(port, PRL_TX_PHY_LAYER_RESET); @@ -1893,8 +1893,10 @@ static void tch_message_received_entry(const int port) RCH_SET_FLAG(port, PRL_FLAGS_MSG_RECEIVED); /* Clear extended message objects */ - /* TODO: Notify PE of message discard */ - TCH_CLR_FLAG(port, PRL_FLAGS_MSG_XMIT); + if (TCH_CHK_FLAG(port, PRL_FLAGS_MSG_XMIT)) { + TCH_CLR_FLAG(port, PRL_FLAGS_MSG_XMIT); + pe_report_discard(port); + } pdmsg[port].data_objs = 0; } diff --git a/include/mock/usb_pe_sm_mock.h b/include/mock/usb_pe_sm_mock.h index b678df9d7b..720ec7d219 100644 --- a/include/mock/usb_pe_sm_mock.h +++ b/include/mock/usb_pe_sm_mock.h @@ -19,6 +19,7 @@ struct mock_pe_port_t { int mock_pe_got_hard_reset; int mock_pe_message_received; int mock_got_soft_reset; + int mock_pe_message_discarded; }; extern struct mock_pe_port_t mock_pe_port[CONFIG_USB_PD_PORT_MAX_COUNT]; diff --git a/include/usb_pe_sm.h b/include/usb_pe_sm.h index 8089fddb55..949df6d516 100644 --- a/include/usb_pe_sm.h +++ b/include/usb_pe_sm.h @@ -78,6 +78,13 @@ void pe_message_sent(int port); void pe_report_error(int port, enum pe_error e, enum tcpm_transmit_type type); /** + * Informs the Policy Engine of a discard. + * + * @param port USB-C port number + */ +void pe_report_discard(int port); + +/** * Called by the Protocol Layer to informs the Policy Engine * that a message has been received. * diff --git a/test/usb_prl_old.c b/test/usb_prl_old.c index 4c027098ea..f11db7fb5c 100644 --- a/test/usb_prl_old.c +++ b/test/usb_prl_old.c @@ -107,6 +107,7 @@ static struct pd_prl { int mock_pe_got_hard_reset; int mock_pe_message_received; int mock_got_soft_reset; + int mock_message_discard; } pd_port[CONFIG_USB_PD_PORT_MAX_COUNT]; static void init_port(int port, int rev) @@ -744,6 +745,11 @@ void pe_report_error(int port, enum pe_error e, enum tcpm_transmit_type type) pd_port[port].sop = type; } +void pe_report_discard(int port) +{ + pd_port[port].mock_message_discard = 1; +} + void pe_got_hard_reset(int port) { pd_port[port].mock_pe_got_hard_reset = 1; @@ -1353,6 +1359,7 @@ void before_test(void) pd_port[PORT0].mock_pe_message_sent = 0; pd_port[PORT0].mock_pe_error = -1; + pd_port[PORT0].mock_message_discard = 0; pd_port[PORT0].mock_pe_hard_reset_sent = 0; pd_port[PORT0].mock_pe_got_hard_reset = 0; pd_port[PORT0].mock_pe_message_received = 0; |