summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Hurst <shurst@google.com>2019-11-12 09:27:24 -0800
committerCommit Bot <commit-bot@chromium.org>2019-12-07 03:06:18 +0000
commit3d50fa0b973c1feeab88087ed864173d67878c97 (patch)
tree8ea6c558b0bb1459a07b5692f9518ae5fa5a5694
parentfdcc690ac4bd08bb28df5a88aee0a10ac5397e22 (diff)
downloadchrome-ec-3d50fa0b973c1feeab88087ed864173d67878c97.tar.gz
TCPMv2: Don't use SinkTXOK/NG in middle of partner-initiated PD3.0 AMS
Don't send ACCEPT message (to PR_SWAP AMS initiated by partner) after lowering Rp to SnkTXNG. BUG=chromium:1023064 BRANCH=none TEST=make -j buildall manual tests: Connected several docks with charger and verified PR_SWAP. Also works with the CM dock that triggered this bug. Change-Id: Iab5474174cf8313c24bae8a7869565005504af25 Signed-off-by: Sam Hurst <shurst@google.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1912161 Reviewed-by: Jett Rink <jettrink@chromium.org>
-rw-r--r--common/usbc/usb_pe_drp_sm.c60
1 files changed, 35 insertions, 25 deletions
diff --git a/common/usbc/usb_pe_drp_sm.c b/common/usbc/usb_pe_drp_sm.c
index 7521db7edb..447b5ca583 100644
--- a/common/usbc/usb_pe_drp_sm.c
+++ b/common/usbc/usb_pe_drp_sm.c
@@ -105,6 +105,8 @@
#define PE_FLAGS_WAITING_DR_SWAP BIT(24)
/* FLAG to track if port partner is dualrole capable */
#define PE_FLAGS_PORT_PARTNER_IS_DUALROLE BIT(25)
+/* FLAG is set when an AMS is initiated locally. ie. AP requested a PR_SWAP */
+#define PE_FLAGS_LOCALLY_INITIATED_AMS BIT(26)
/* 6.7.3 Hard Reset Counter */
#define N_HARD_RESET_COUNT 2
@@ -304,9 +306,6 @@ static struct policy_engine {
enum pd_power_role power_role;
/* current port data role (DFP or UFP) */
enum pd_data_role data_role;
- /* saved data and power roles while communicating with a cable plug */
- enum pd_data_role saved_data_role;
- enum pd_power_role saved_power_role;
/* state machine flags */
uint32_t flags;
/* Device Policy Manager Request */
@@ -1163,12 +1162,6 @@ static void pe_src_send_capabilities_entry(int port)
/* Stop sender response timer */
pe[port].sender_response_timer = TIMER_DISABLED;
-
- /*
- * Clear PE_FLAGS_INTERRUPTIBLE_AMS flag if it was set
- * in the src_discovery state
- */
- PE_CLR_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS);
}
static void pe_src_send_capabilities_run(int port)
@@ -1404,6 +1397,8 @@ static void pe_src_ready_entry(int port)
{
print_current_state(port);
+ PE_CLR_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS);
+
/*
* If the transition into PE_SRC_Ready is the result of Protocol Error
* that has not caused a Soft Reset (see Section 8.3.3.4.1) then the
@@ -1413,7 +1408,6 @@ static void pe_src_ready_entry(int port)
if (PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) {
PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR);
} else {
- PE_CLR_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS);
prl_end_ams(port);
}
@@ -1491,6 +1485,8 @@ static void pe_src_ready_run(int port)
pe[port].vdm_cnt = 1;
set_state_pe(port, PE_VDM_REQUEST);
}
+
+ PE_SET_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS);
return;
}
@@ -1595,8 +1591,9 @@ static void pe_src_ready_exit(int port)
* notify the Protocol Layer that the first Message in an AMS will
* follow.
*/
- if (!PE_CHK_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS))
+ if (PE_CHK_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS))
prl_start_ams(port);
+
}
/**
@@ -2089,7 +2086,7 @@ static void pe_snk_ready_entry(int port)
{
print_current_state(port);
- PE_CLR_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS);
+ PE_CLR_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS);
prl_end_ams(port);
/*
@@ -2187,6 +2184,7 @@ static void pe_snk_ready_run(int port)
PE_CLR_DPM_REQUEST(port, DPM_REQUEST_GET_SNK_CAPS);
set_state_pe(port, PE_DR_SNK_GET_SINK_CAP);
}
+ PE_SET_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS);
return;
}
@@ -2285,7 +2283,11 @@ static void pe_snk_ready_run(int port)
static void pe_snk_ready_exit(int port)
{
- if (!PE_CHK_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS))
+ /*
+ * If the Sink is initiating an AMS then notify the Protocol Layer
+ * that the first Message in the AMS will follow
+ */
+ if (PE_CHK_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS))
prl_start_ams(port);
}
@@ -2962,7 +2964,7 @@ static void pe_prs_src_snk_wait_source_on_run(int port)
int cnt;
int ext;
- if (pe[port].ps_source_timer != TIMER_DISABLED &&
+ if (pe[port].ps_source_timer == TIMER_DISABLED &&
PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
@@ -2975,7 +2977,8 @@ static void pe_prs_src_snk_wait_source_on_run(int port)
* Transition to PE_SNK_Startup when:
* 1) An PS_RDY Message is received.
*/
- if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
+ if (pe[port].ps_source_timer != TIMER_DISABLED &&
+ PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
type = PD_HEADER_TYPE(emsg[port].header);
@@ -3494,6 +3497,11 @@ static void pe_handle_custom_vdm_request_run(int port)
}
}
+static void pe_handle_custom_vdm_request_exit(int port)
+{
+ PE_CLR_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS);
+}
+
/**
* PE_DO_PORT_Discovery
*
@@ -3635,15 +3643,7 @@ static void pe_vdm_request_entry(int port)
emsg[port].len = pe[port].vdm_cnt * 4;
}
- if (pe[port].partner_type) {
- /* Save power and data roles */
- pe[port].saved_power_role = tc_get_power_role(port);
- pe[port].saved_data_role = tc_get_data_role(port);
-
- prl_send_data_msg(port, TCPC_TX_SOP_PRIME, PD_DATA_VENDOR_DEF);
- } else {
- prl_send_data_msg(port, TCPC_TX_SOP, PD_DATA_VENDOR_DEF);
- }
+ prl_send_data_msg(port, TCPC_TX_SOP, PD_DATA_VENDOR_DEF);
pe[port].vdm_response_timer = TIMER_DISABLED;
}
@@ -3838,6 +3838,9 @@ static void pe_vdm_response_entry(int port)
print_current_state(port);
+ /* This is an Interruptible AMS */
+ PE_SET_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS);
+
/* Get the message */
payload = (uint32_t *)emsg[port].buf;
vdo_cmd = PD_VDO_CMD(payload[0]);
@@ -3952,6 +3955,11 @@ static void pe_vdm_response_run(int port)
}
}
+static void pe_vdm_response_exit(int port)
+{
+ PE_CLR_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS);
+}
+
/*
* PE_VCS_Evaluate_Swap
*/
@@ -5191,10 +5199,12 @@ static const struct usb_state pe_states[] = {
[PE_VDM_RESPONSE] = {
.entry = pe_vdm_response_entry,
.run = pe_vdm_response_run,
+ .exit = pe_vdm_response_exit,
},
[PE_HANDLE_CUSTOM_VDM_REQUEST] = {
.entry = pe_handle_custom_vdm_request_entry,
- .run = pe_handle_custom_vdm_request_run
+ .run = pe_handle_custom_vdm_request_run,
+ .exit = pe_handle_custom_vdm_request_exit,
},
[PE_WAIT_FOR_ERROR_RECOVERY] = {
.entry = pe_wait_for_error_recovery_entry,