summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Hurst <shurst@google.com>2020-04-02 19:14:34 -0700
committerCommit Bot <commit-bot@chromium.org>2020-05-02 07:21:15 +0000
commit220feed8668d94077900a6293e385c0e6a636205 (patch)
tree8b02201e5d136462fbd4ea3c286c28849b67ebff
parent6071cb1e1682796730f1f77072ae75c51b61c4f9 (diff)
downloadchrome-ec-220feed8668d94077900a6293e385c0e6a636205.tar.gz
TCPMv2: Send Soft Reset to SOP* that caused a protocol error
On a protocol error, sends soft reset to SOP* of incoming or outgoing message. BUG=b:150614211 BRANCH=none TEST=make -j buildall Manual tests: Passed FAFT_PD on hatch. Port partner was SOP Modified FAFT_PD test to send soft reset from SOP' All tests passed Change-Id: Ic9832fe3b9efd6f313cbfde74cfa3a7922121678 Signed-off-by: Sam Hurst <shurst@google.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2135328 Reviewed-by: Diana Z <dzigterman@chromium.org>
-rw-r--r--common/usbc/usb_pe_ctvpd_sm.c2
-rw-r--r--common/usbc/usb_pe_drp_sm.c45
-rw-r--r--common/usbc/usb_prl_sm.c15
-rw-r--r--include/usb_pe_sm.h4
-rw-r--r--test/usb_prl.c4
5 files changed, 45 insertions, 25 deletions
diff --git a/common/usbc/usb_pe_ctvpd_sm.c b/common/usbc/usb_pe_ctvpd_sm.c
index 96afc42f49..7e215e4113 100644
--- a/common/usbc/usb_pe_ctvpd_sm.c
+++ b/common/usbc/usb_pe_ctvpd_sm.c
@@ -98,7 +98,7 @@ void pe_got_hard_reset(int port)
/* No implementation needed by this policy engine */
}
-void pe_report_error(int port, enum pe_error e)
+void pe_report_error(int port, enum pe_error e, enum tcpm_transmit_type type)
{
/* 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 4f80eb72f4..2402654868 100644
--- a/common/usbc/usb_pe_drp_sm.c
+++ b/common/usbc/usb_pe_drp_sm.c
@@ -366,6 +366,9 @@ static struct policy_engine {
/* last requested voltage PDO index */
int requested_idx;
+ /* port address where soft resets are sent */
+ enum tcpm_transmit_type soft_reset_sop;
+
/* Current limit / voltage based on the last request message */
uint32_t curr_limit;
uint32_t supply_voltage;
@@ -782,7 +785,13 @@ static bool pe_can_send_sop_vdm(int port, int vdm_cmd)
return false;
}
-void pe_report_error(int port, enum pe_error e)
+static void pe_send_soft_reset(const int port, enum tcpm_transmit_type type)
+{
+ pe[port].soft_reset_sop = type;
+ set_state_pe(port, PE_SEND_SOFT_RESET);
+}
+
+void pe_report_error(int port, enum pe_error e, enum tcpm_transmit_type type)
{
/* This should only be called from the PD task */
assert(port == TASK_ID_TO_PD_PORT(task_get_current()));
@@ -831,7 +840,7 @@ void pe_report_error(int port, enum pe_error e)
if (!PE_CHK_FLAG(port, PE_FLAGS_EXPLICIT_CONTRACT) &&
(!PE_CHK_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS)
|| (e == ERR_TCH_XMIT))) {
- set_state_pe(port, PE_SEND_SOFT_RESET);
+ pe_send_soft_reset(port, type);
}
/*
* Transition to PE_Snk_Ready or PE_Src_Ready by a Protocol
@@ -986,7 +995,8 @@ static bool common_src_snk_dpm_requests(int port)
DPM_REQUEST_SOFT_RESET_SEND)) {
PE_CLR_DPM_REQUEST(port,
DPM_REQUEST_SOFT_RESET_SEND);
- set_state_pe(port, PE_SEND_SOFT_RESET);
+ /* Currently only support sending soft reset to SOP */
+ pe_send_soft_reset(port, TCPC_TX_SOP);
return true;
} else if (PE_CHK_DPM_REQUEST(port,
DPM_REQUEST_PORT_DISCOVERY)) {
@@ -1527,13 +1537,14 @@ static void pe_src_send_capabilities_run(int port)
* PE_SNK/SRC_READY if explicit contract
* PE_SEND_SOFT_RESET otherwise
*/
- if (PE_CHK_FLAG(port, PE_FLAGS_EXPLICIT_CONTRACT))
+ if (PE_CHK_FLAG(port, PE_FLAGS_EXPLICIT_CONTRACT)) {
if (pe[port].power_role == PD_ROLE_SINK)
set_state_pe(port, PE_SNK_READY);
else
set_state_pe(port, PE_SRC_READY);
- else
- set_state_pe(port, PE_SEND_SOFT_RESET);
+ } else {
+ pe_send_soft_reset(port, TCPC_TX_SOP);
+ }
return;
}
@@ -2154,7 +2165,7 @@ static void pe_snk_startup_run(int port)
* is entered.
*/
sysjump_occurred = false;
- set_state_pe(port, PE_SEND_SOFT_RESET);
+ pe_send_soft_reset(port, TCPC_TX_SOP);
} else {
/*
* Once the reset process completes, the Policy Engine Shall
@@ -2298,6 +2309,7 @@ static void pe_snk_select_capability_run(int port)
{
uint8_t type;
uint8_t cnt;
+ enum tcpm_transmit_type sop;
/* Wait until message is sent */
if (pe[port].sender_response_timer == TIMER_DISABLED) {
@@ -2315,6 +2327,7 @@ static void pe_snk_select_capability_run(int port)
PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
type = PD_HEADER_TYPE(rx_emsg[port].header);
cnt = PD_HEADER_CNT(rx_emsg[port].header);
+ sop = PD_HEADER_GET_SOP(rx_emsg[port].header);
/*
* Transition to the PE_SNK_Transition_Sink state when:
@@ -2383,7 +2396,7 @@ static void pe_snk_select_capability_run(int port)
*/
else {
/* Send Soft Reset */
- set_state_pe(port, PE_SEND_SOFT_RESET);
+ pe_send_soft_reset(port, sop);
return;
}
}
@@ -2392,7 +2405,7 @@ static void pe_snk_select_capability_run(int port)
*/
else {
/* Send Soft Reset */
- set_state_pe(port, PE_SEND_SOFT_RESET);
+ pe_send_soft_reset(port, sop);
return;
}
}
@@ -2829,7 +2842,8 @@ static void pe_send_soft_reset_run(int port)
* unexpected incoming message type
*/
/* Send Soft Reset message */
- prl_send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_SOFT_RESET);
+ prl_send_ctrl_msg(port,
+ pe[port].soft_reset_sop, PD_CTRL_SOFT_RESET);
/* Initialize and run SenderResponseTimer */
pe[port].sender_response_timer =
@@ -4143,7 +4157,7 @@ static void pe_vdm_identity_request_cbl_run(int port)
/* Message received */
if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
uint32_t *payload;
- int sop;
+ enum tcpm_transmit_type sop;
uint8_t type;
uint8_t cnt;
uint8_t ext;
@@ -4224,7 +4238,7 @@ static void pe_vdm_identity_request_cbl_run(int port)
* incoming message
*/
if (get_last_state_pe(port) == PE_SRC_DISCOVERY) {
- set_state_pe(port, PE_SEND_SOFT_RESET);
+ pe_send_soft_reset(port, sop);
} else {
/*
* Otherwise, return to PE_S[RC,NK]_Ready to process
@@ -4836,6 +4850,7 @@ static void pe_vcs_send_swap_run(int port)
{
uint8_t type;
uint8_t cnt;
+ enum tcpm_transmit_type sop;
/* Wait until message is sent */
if (pe[port].sender_response_timer == TIMER_DISABLED &&
@@ -4854,6 +4869,7 @@ static void pe_vcs_send_swap_run(int port)
type = PD_HEADER_TYPE(rx_emsg[port].header);
cnt = PD_HEADER_CNT(rx_emsg[port].header);
+ sop = PD_HEADER_GET_SOP(rx_emsg[port].header);
/* Only look at control messages */
if (cnt == 0) {
@@ -4894,7 +4910,7 @@ static void pe_vcs_send_swap_run(int port)
*/
else {
/* Send Soft Reset */
- set_state_pe(port, PE_SEND_SOFT_RESET);
+ pe_send_soft_reset(port, sop);
return;
}
}
@@ -5029,7 +5045,6 @@ static void pe_vcs_send_ps_rdy_swap_entry(int port)
/* Send a PS_RDY Message */
prl_send_ctrl_msg(port, TCPC_TX_SOP, PD_CTRL_PS_RDY);
-
pe[port].sub = PE_SUB0;
}
@@ -5085,7 +5100,7 @@ static void pe_vcs_send_ps_rdy_swap_run(int port)
if (pe[port].sub == PE_SUB0) {
/* PS_RDY didn't send, soft reset */
- set_state_pe(port, PE_SEND_SOFT_RESET);
+ pe_send_soft_reset(port, TCPC_TX_SOP);
} else {
/*
* Cable plug wasn't present,
diff --git a/common/usbc/usb_prl_sm.c b/common/usbc/usb_prl_sm.c
index 8b375abfab..23282d4e22 100644
--- a/common/usbc/usb_prl_sm.c
+++ b/common/usbc/usb_prl_sm.c
@@ -174,6 +174,8 @@ static struct tx_chunked {
/* Message Reception State Machine Object */
static struct protocol_layer_rx {
+ /* received message type */
+ enum tcpm_transmit_type sop;
/* message ids for all valid port partners */
int msg_id[NUM_SOP_STAR_TYPES];
} prl_rx[CONFIG_USB_PD_PORT_MAX_COUNT];
@@ -1254,10 +1256,10 @@ static void rch_report_error_entry(const int port)
/* Pass Message to Policy Engine */
pe_message_received(port);
/* Report error */
- pe_report_error(port, ERR_RCH_MSG_REC);
+ pe_report_error(port, ERR_RCH_MSG_REC, prl_rx[port].sop);
} else {
/* Report error */
- pe_report_error(port, ERR_RCH_CHUNKED);
+ pe_report_error(port, ERR_RCH_CHUNKED, prl_rx[port].sop);
}
}
@@ -1555,7 +1557,7 @@ static void tch_message_sent_entry(const int port)
static void tch_report_error_entry(const int port)
{
/* Report Error To Policy Engine */
- pe_report_error(port, tch[port].error);
+ pe_report_error(port, tch[port].error, prl_tx[port].last_xmit_type);
set_state_tch(port, TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE);
}
@@ -1567,7 +1569,6 @@ static void prl_rx_wait_for_phy_message(const int port, int evt)
uint32_t header;
uint8_t type;
uint8_t cnt;
- uint8_t sop;
int8_t msid;
/* If we don't have any message, just stop processing now. */
@@ -1579,7 +1580,7 @@ static void prl_rx_wait_for_phy_message(const int port, int evt)
type = PD_HEADER_TYPE(header);
cnt = PD_HEADER_CNT(header);
msid = PD_HEADER_ID(header);
- sop = PD_HEADER_GET_SOP(header);
+ prl_rx[port].sop = PD_HEADER_GET_SOP(header);
/* Make sure an incorrect count doesn't overflow the chunk buffer */
if (cnt > CHK_BUF_SIZE)
@@ -1628,7 +1629,7 @@ static void prl_rx_wait_for_phy_message(const int port, int evt)
/*
* Ignore if this is a duplicate message. Stop processing.
*/
- if (prl_rx[port].msg_id[sop] == msid)
+ if (prl_rx[port].msg_id[prl_rx[port].sop] == msid)
return;
/*
@@ -1644,7 +1645,7 @@ static void prl_rx_wait_for_phy_message(const int port, int evt)
}
/* Store Message Id */
- prl_rx[port].msg_id[sop] = msid;
+ prl_rx[port].msg_id[prl_rx[port].sop] = msid;
/* RTR Chunked Message Router States. */
/*
diff --git a/include/usb_pe_sm.h b/include/usb_pe_sm.h
index 26427f23d5..771b4d408b 100644
--- a/include/usb_pe_sm.h
+++ b/include/usb_pe_sm.h
@@ -8,6 +8,7 @@
#ifndef __CROS_EC_USB_PE_H
#define __CROS_EC_USB_PE_H
+#include "usb_pd_tcpm.h"
#include "usb_sm.h"
/* Policy Engine Receive and Transmit Errors */
@@ -72,8 +73,9 @@ void pe_message_sent(int port);
*
* @param port USB-C port number
* @param e error
+ * @param type port address where error was generated
*/
-void pe_report_error(int port, enum pe_error e);
+void pe_report_error(int port, enum pe_error e, enum tcpm_transmit_type type);
/**
* Called by the Protocol Layer to informs the Policy Engine
diff --git a/test/usb_prl.c b/test/usb_prl.c
index f0d71a75d2..e169fc2f05 100644
--- a/test/usb_prl.c
+++ b/test/usb_prl.c
@@ -99,6 +99,7 @@ static struct pd_prl {
enum pd_data_role data_role;
int msg_tx_id;
int msg_rx_id;
+ enum tcpm_transmit_type sop;
int mock_pe_message_sent;
int mock_pe_error;
@@ -737,9 +738,10 @@ enum pd_cable_plug tc_get_cable_plug(int port)
return PD_PLUG_FROM_DFP_UFP;
}
-void pe_report_error(int port, enum pe_error e)
+void pe_report_error(int port, enum pe_error e, enum tcpm_transmit_type type)
{
pd_port[port].mock_pe_error = e;
+ pd_port[port].sop = type;
}
void pe_got_hard_reset(int port)