summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiana Z <dzigterman@chromium.org>2020-03-31 15:08:34 -0600
committerCommit Bot <commit-bot@chromium.org>2020-04-17 17:20:42 +0000
commit8d2f8964ffc7ef794166b81cd475e208b5c4328b (patch)
treeb77fb10cec5b143beee97adf494d294ac4baed44
parent380e33b10fed03f41ba17de764ca80facf40e42c (diff)
downloadchrome-ec-8d2f8964ffc7ef794166b81cd475e208b5c4328b.tar.gz
TCPMv2: Revamp pe_attempt_port_discovery
Revamps pe_attempt_port_discovery to be called from the ready run states, try once to be DFP and Vconn source, and moves timer check and discovery calls into this function. Note that nDiscoverIdentityCount and DiscoverIdentityTimer are only applicable to cable plugs, though here the discover identity timer is also repurposed to space out requests to a BUSY partner. Long term, the policy decisions regarding our data and vconn role will be moved out into their own file in order to support allowing the AP to override EC default policies. BRANCH=None BUG=b:152417977 TEST=on kindred running TCPMv2, ensured we could complete discovery and enter mode DP mode (when applicable) with: - PD 2.0 Apple dongle, with and without external power - PD 2.0 Acer hub - PD 2.0 charger which would DR swap - PD 3.0 Cable Matters hub, with and without external power - PD 3.0 Hoo Too hub, with and without external power Ensured we did not attempt discovery with: - PD 2.0 charger which won't DR swap Signed-off-by: Diana Z <dzigterman@chromium.org> Change-Id: I9c049690a87f3fc0eca3b9d2c85128470cbb2a91 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2130478 Reviewed-by: Jett Rink <jettrink@chromium.org>
-rw-r--r--common/usbc/usb_pe_drp_sm.c176
-rw-r--r--test/usb_pe_drp.c4
2 files changed, 93 insertions, 87 deletions
diff --git a/common/usbc/usb_pe_drp_sm.c b/common/usbc/usb_pe_drp_sm.c
index 013dcf321e..0653324f85 100644
--- a/common/usbc/usb_pe_drp_sm.c
+++ b/common/usbc/usb_pe_drp_sm.c
@@ -100,7 +100,7 @@
#define PE_FLAGS_FAST_ROLE_SWAP_ENABLED BIT(21)
/* Flag to note TCPC passed on FRS signal from port partner */
#define PE_FLAGS_FAST_ROLE_SWAP_SIGNALED BIT(22)
-/* For PD2.0, triggers a DR SWAP from UFP to DFP before sending a DiscID msg */
+/* TODO: POLICY decision: Triggers a DR SWAP attempt from UFP to DFP */
#define PE_FLAGS_DR_SWAP_TO_DFP BIT(23)
/* Flag to trigger a message resend after receiving a WAIT from port partner */
#define PE_FLAGS_WAITING_DR_SWAP BIT(24)
@@ -112,6 +112,8 @@
#define PE_FLAGS_FIRST_MSG BIT(27)
/* Flag to continue port discovery if it was interrupted */
#define PE_FLAGS_DISCOVER_PORT_CONTINUE BIT(28)
+/* TODO: POLICY decision: Triggers a Vconn SWAP attempt to on */
+#define PE_FLAGS_VCONN_SWAP_TO_ON BIT(29)
/* 6.7.3 Hard Reset Counter */
#define N_HARD_RESET_COUNT 2
@@ -1117,53 +1119,81 @@ static void pe_prl_execute_hard_reset(int port)
prl_execute_hard_reset(port);
}
+#ifdef CONFIG_USB_PD_ALT_MODE_DFP
/*
- * This function must only be called from the PE_SNK_READY entry and
- * PE_SRC_READY entry State.
+ * Run discovery at our leisure from PE_SNK_Ready or PE_SRC_Ready, after
+ * attempting to get into the desired default policy of DFP/Vconn source
+ *
+ * Return indicates whether set_state was called, in which case the calling
+ * function should return as well.
*/
-static void pe_attempt_port_discovery(int port)
+static bool pe_attempt_port_discovery(int port)
{
- if (!PE_CHK_FLAG(port, PE_FLAGS_MODAL_OPERATION |
- PE_FLAGS_DISCOVER_PORT_IDENTITY_DONE) &&
- pe[port].discover_port_identity_counter <=
- N_DISCOVER_IDENTITY_COUNT) {
- /*
- * If we are operating as PD2.0 version, make sure we are
- * DFP before sending Discover Identity message.
- */
- if (prl_get_rev(port, TCPC_TX_SOP) == PD_REV20 &&
- pe[port].data_role == PD_ROLE_UFP) {
- /*
- * If we are UFP and DR SWAP fails
- * N_DR_SWAP_ATTEMPT_COUNT number of times, give up
- * port discovery. Also give up if the Port Partner
- * rejected the DR_SWAP.
- */
- if ((pe[port].dr_swap_attempt_counter >=
- N_DR_SWAP_ATTEMPT_COUNT) ||
- (pe[port].dr_swap_attempt_counter > 0 &&
- !PE_CHK_FLAG(port, PE_FLAGS_WAITING_DR_SWAP))) {
- PE_SET_FLAG(port,
- PE_FLAGS_DISCOVER_PORT_IDENTITY_DONE);
- pe[port].discover_port_identity_timer =
- TIMER_DISABLED;
- } else {
- PE_SET_FLAG(port, PE_FLAGS_DR_SWAP_TO_DFP);
- pe[port].discover_port_identity_timer =
- get_time().val + PD_T_DISCOVER_IDENTITY;
- }
- } else {
- pe[port].discover_port_identity_timer =
- get_time().val + PD_T_DISCOVER_IDENTITY;
+ /*
+ * DONE set once modal entry is successful, discovery completes, or
+ * discovery results in a NAK
+ */
+ if (PE_CHK_FLAG(port, PE_FLAGS_DISCOVER_PORT_IDENTITY_DONE))
+ return false;
+
+ /*
+ * TODO: POLICY decision: move policy functionality out to a separate
+ * file. For now, try once to become DFP/Vconn source
+ */
+ if (PE_CHK_FLAG(port, PE_FLAGS_DR_SWAP_TO_DFP)) {
+ PE_CLR_FLAG(port, PE_FLAGS_DR_SWAP_TO_DFP);
+
+ if (pe[port].data_role == PD_ROLE_UFP) {
+ set_state_pe(port, PE_DRS_SEND_SWAP);
+ return true;
}
- } else {
+ }
+
+ if (PE_CHK_FLAG(port, PE_FLAGS_VCONN_SWAP_TO_ON)) {
+ PE_CLR_FLAG(port, PE_FLAGS_VCONN_SWAP_TO_ON);
+
+ if (!tc_is_vconn_src(port)) {
+ set_state_pe(port, PE_VCS_SEND_SWAP);
+ return true;
+ }
+ }
+
+ /* If mode entry was successful, disable the timer */
+ if (PE_CHK_FLAG(port, PE_FLAGS_MODAL_OPERATION)) {
PE_SET_FLAG(port, PE_FLAGS_DISCOVER_PORT_IDENTITY_DONE);
pe[port].discover_port_identity_timer = TIMER_DISABLED;
+ return false;
}
- /* Clear the PE_FLAGS_WAITING_DR_SWAP flag if it was set. */
- PE_CLR_FLAG(port, PE_FLAGS_WAITING_DR_SWAP);
+ /*
+ * Run discovery functions when the timer indicating either cable
+ * discovery spacing or BUSY spacing runs out.
+ */
+ if (get_time().val > pe[port].discover_port_identity_timer) {
+ if (pe[port].cable.discovery == PD_DISC_NEEDED &&
+ pe_can_send_sop_prime(port)) {
+ set_state_pe(port, PE_VDM_IDENTITY_REQUEST_CBL);
+ return true;
+ } else if (pd_get_identity_discovery(port, TCPC_TX_SOP) ==
+ PD_DISC_NEEDED &&
+ pe_can_send_sop_vdm(port, CMD_DISCOVER_IDENT)) {
+ set_state_pe(port,
+ PE_INIT_PORT_VDM_IDENTITY_REQUEST);
+ return true;
+ /*
+ * Note: determine if next VDM can be sent by taking advantage
+ * of discovery following the VDM command enum ordering.
+ * Remove once do_port_discovery can be removed.
+ */
+ } else if (pe_can_send_sop_vdm(port, pe[port].vdm_cmd + 1)) {
+ set_state_pe(port, PE_DO_PORT_DISCOVERY);
+ return true;
+ }
+ }
+
+ return false;
}
+#endif
int pd_dev_store_rw_hash(int port, uint16_t dev_id, uint32_t *rw_hash,
uint32_t current_image)
@@ -1651,14 +1681,6 @@ static void pe_src_ready_entry(int port)
}
/*
- * Do port partner discovery
- *
- * This function modifies state variables that are used in the run
- * part of this state. See pe_attempt_port_discovery for details.
- */
- pe_attempt_port_discovery(port);
-
- /*
* Wait and add jitter if we are operating in PD2.0 mode and no messages
* have been sent since enter this state.
*/
@@ -1783,22 +1805,11 @@ static void pe_src_ready_run(int port)
pe[port].wait_and_add_jitter_timer = TIMER_DISABLED;
/*
- * Start Port Discovery when:
- * 1) The DiscoverIdentityTimer times out.
+ * Attempt discovery if possible, and return if state was
+ * changed for that discovery.
*/
- if (get_time().val > pe[port].discover_port_identity_timer) {
- if (pe[port].cable.discovery == PD_DISC_NEEDED &&
- pe_can_send_sop_prime(port))
- set_state_pe(port, PE_VDM_IDENTITY_REQUEST_CBL);
- else if (pd_get_identity_discovery(port, TCPC_TX_SOP) ==
- PD_DISC_NEEDED &&
- pe_can_send_sop_vdm(port, CMD_DISCOVER_IDENT))
- set_state_pe(port,
- PE_INIT_PORT_VDM_IDENTITY_REQUEST);
- else
- set_state_pe(port, PE_DO_PORT_DISCOVERY);
+ if (pe_attempt_port_discovery(port))
return;
- }
/*
* Handle Device Policy Manager Requests
@@ -2058,6 +2069,12 @@ static void pe_snk_startup_entry(int port)
if (PE_CHK_FLAG(port, PE_FLAGS_PR_SWAP_COMPLETE)) {
PE_CLR_FLAG(port, PE_FLAGS_PR_SWAP_COMPLETE);
} else {
+ /*
+ * Set DiscoverIdentityTimer to trigger when we enter
+ * snk_ready for the first time.
+ */
+ pe[port].discover_port_identity_timer = get_time().val;
+
/* Clear port discovery flags */
PE_CLR_FLAG(port, PE_FLAGS_DISCOVER_PORT_IDENTITY_DONE);
pd_dfp_discovery_init(port);
@@ -2066,6 +2083,13 @@ static void pe_snk_startup_entry(int port)
/* Reset dr swap attempt counter */
pe[port].dr_swap_attempt_counter = 0;
+
+ /*
+ * TODO: POLICY decision:
+ * Mark that we'd like to try being Vconn source and DFP
+ */
+ PE_SET_FLAG(port, PE_FLAGS_DR_SWAP_TO_DFP);
+ PE_SET_FLAG(port, PE_FLAGS_VCONN_SWAP_TO_ON);
}
}
@@ -2410,17 +2434,8 @@ static void pe_snk_ready_entry(int port)
}
/*
- * Do port partner discovery
- *
- * This function modifies state variables that are used in
- * the run part of this state. See pe_attempt_port_discovery
- * for details.
- */
- pe_attempt_port_discovery(port);
-
- /*
- * Wait and add jitter if we are operating in PD2.0 mode and no
- * messages have been sent since enter this state.
+ * Wait and add jitter if we are operating in PD2.0 mode and no messages
+ * have been sent since enter this state.
*/
pe_update_wait_and_add_jitter_timer(port);
}
@@ -2548,22 +2563,11 @@ static void pe_snk_ready_run(int port)
}
/*
- * Start Port Discovery when:
- * 1) The PortDiscoverIdentityTimer times out.
+ * Attempt discovery if possible, and return if state was
+ * changed for that discovery.
*/
- if (get_time().val > pe[port].discover_port_identity_timer) {
- if (pe[port].cable.discovery == PD_DISC_NEEDED &&
- pe_can_send_sop_prime(port))
- set_state_pe(port, PE_VDM_IDENTITY_REQUEST_CBL);
- else if (pd_get_identity_discovery(port, TCPC_TX_SOP) ==
- PD_DISC_NEEDED &&
- pe_can_send_sop_vdm(port, CMD_DISCOVER_IDENT))
- set_state_pe(port,
- PE_INIT_PORT_VDM_IDENTITY_REQUEST);
- else
- set_state_pe(port, PE_DO_PORT_DISCOVERY);
+ if (pe_attempt_port_discovery(port))
return;
- }
/*
* Handle Device Policy Manager Requests
diff --git a/test/usb_pe_drp.c b/test/usb_pe_drp.c
index 9c5771851b..8fe474ce8f 100644
--- a/test/usb_pe_drp.c
+++ b/test/usb_pe_drp.c
@@ -64,9 +64,11 @@ static int test_pe_frs(void)
/*
* FRS will only trigger when we are SNK, with an Explicit
- * contract. So set this state up manually
+ * contract. So set this state up manually. Also ensure any
+ * background tasks (ex. discovery) aren't running.
*/
tc_prs_src_snk_assert_rd(PORT0);
+ pe_set_flag(PORT0, PE_FLAGS_DISCOVER_PORT_IDENTITY_DONE);
pe_set_flag(PORT0, PE_FLAGS_EXPLICIT_CONTRACT);
set_state_pe(PORT0, PE_SNK_READY);
pe_run(PORT0, EVT_IGNORED, ENABLED);