summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiana Z <dzigterman@chromium.org>2020-06-11 13:37:36 -0600
committerCommit Bot <commit-bot@chromium.org>2020-06-25 23:57:54 +0000
commit2f651922b48ed2ed4a592ca2f61b82d7df7f0006 (patch)
treefff962a20c981472661782e3cbf48ec2f84698f1
parent07fc2cff6d8575ca89e563fca741a0ea454fff9d (diff)
downloadchrome-ec-2f651922b48ed2ed4a592ca2f61b82d7df7f0006.tar.gz
TCPMv2: Report message discard to the PE
This commit creates a reporting function for the PRL to let the PE know when messages have been discarded. States will have to handle message discard internally since the response depends on the portion of the AMS sequence they're in. For some states which begin AMSes, a new shared parent has been added which runs the sender response timer and checks discard for the child. More states (and discard mid-AMS) are expected to be added in future CLs. The new parent state saves an average of 124 bytes of flash space. BRANCH=None BUG=b:158248741,b:157228506 TEST=on waddledoo, Dell dock no longer soft resets during power role swap Signed-off-by: Diana Z <dzigterman@chromium.org> Change-Id: I61b3e96e1d14634dcd5edda4e133968ace769b21 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2241577 Reviewed-by: Denis Brockus <dbrockus@chromium.org> Commit-Queue: Denis Brockus <dbrockus@chromium.org>
-rw-r--r--common/mock/usb_pe_sm_mock.c5
-rw-r--r--common/usbc/usb_pe_ctvpd_sm.c5
-rw-r--r--common/usbc/usb_pe_drp_sm.c151
-rw-r--r--common/usbc/usb_prl_sm.c10
-rw-r--r--include/mock/usb_pe_sm_mock.h1
-rw-r--r--include/usb_pe_sm.h7
-rw-r--r--test/usb_prl_old.c7
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;