summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAseda Aboagye <aaboagye@google.com>2019-02-19 19:27:58 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2019-05-07 15:30:49 +0000
commit5a71651ca098a17ffb50d4b04014110b9b27227a (patch)
tree4c832b8a8d1326ffbda47a612516dba151e8b768
parent08a2bed2193258a5cfcdc672f3c73a7bd96807b0 (diff)
downloadchrome-ec-5a71651ca098a17ffb50d4b04014110b9b27227a.tar.gz
pd: Don't send msgs for ~200ms after 1st request.
Some PD devices are quite chatty as soon as an explicit contract is established. Our PD stack currently has a one track mind where we interrogate the port partner, but may not have realized that we need to reply/handle an incoming message. This commit adds a "quiet time" where we hold off interrogating the port partner until this time passes. This helps us avoid a collision with the "chatty" port partner. BUG=chromium:925618 BRANCH=firmware-nocturne-10984.B TEST=Flash nocturne, plug in Dell U3818DW, verify that port does not flap between HardResets and resolves as a sink and external display works. TEST=Test with other Type-C docks and hubs(including CableMatters) and verify that no regression is seen. Change-Id: I380f82940c4e524ad08a846c110160327fbf8fd2 Signed-off-by: Aseda Aboagye <aaboagye@google.com> Reviewed-on: https://chromium-review.googlesource.com/1479153 Commit-Ready: Aseda Aboagye <aaboagye@chromium.org> Tested-by: Aseda Aboagye <aaboagye@chromium.org> Reviewed-by: Aseda Aboagye <aaboagye@chromium.org> (cherry picked from commit 3f317ba8de5fbe3366835c63b682758eff207a62) Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1597671 Reviewed-by: Jett Rink <jettrink@chromium.org> Commit-Queue: Diana Z <dzigterman@chromium.org> Tested-by: Diana Z <dzigterman@chromium.org>
-rw-r--r--common/usb_pd_protocol.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index 71c85f5ecd..81b918dc05 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -93,6 +93,15 @@ static const int debug_level;
#define PD_CAPS_COUNT 50
#define PD_SNK_CAP_RETRIES 3
+/*
+ * The time that we allow the source to send any messages after an explicit
+ * contract is established. 200ms was chosen somewhat arbitrarily as it should
+ * be long enough for sources to decide to send a message if they were going to,
+ * but not so long that a "low power charger connected" notification would be
+ * shown in the chrome OS UI.
+ */
+#define SNK_READY_HOLD_OFF_US (200 * MSEC)
+
enum vdm_states {
VDM_STATE_ERR_BUSY = -3,
VDM_STATE_ERR_SEND = -2,
@@ -233,6 +242,13 @@ static struct pd_protocol {
/* protocol revision */
uint8_t rev;
#endif
+ /*
+ * Time at which the port acting as a sink can start to request for
+ * higher power and interrogate the port partner. Some port partners
+ * are really chatty after the initial request so we allow this time for
+ * the port partner to send any messages in order to avoid a collision.
+ */
+ uint64_t snk_ready_holdoff_timer;
} pd[CONFIG_USB_PD_PORT_COUNT];
#ifdef CONFIG_COMMON_RUNTIME
@@ -668,6 +684,9 @@ static inline void set_state(int port, enum pd_states next_state)
ppc_clear_oc_event_counter(port);
}
#endif /* CONFIG_USBC_PPC */
+ /* Clear the SNK_READY holdoff timer. */
+ pd[port].snk_ready_holdoff_timer = 0;
+
/* Clear the input current limit */
pd_set_input_current_limit(port, 0, 0);
#ifdef CONFIG_CHARGE_MANAGER
@@ -1680,6 +1699,14 @@ static void handle_ctrl_request(int port, uint16_t head,
} else if (pd[port].task_state == PD_STATE_SNK_SWAP_STANDBY) {
/* Do nothing, assume this is a redundant PD_RDY */
} else if (pd[port].power_role == PD_ROLE_SINK) {
+ /*
+ * Give the source some time to send any messages before
+ * we start our interrogation.
+ */
+ if (pd[port].task_state == PD_STATE_SNK_TRANSITION)
+ pd[port].snk_ready_holdoff_timer =
+ get_time().val + SNK_READY_HOLD_OFF_US;
+
set_state(port, PD_STATE_SNK_READY);
pd_set_input_current_limit(port, pd[port].curr_limit,
pd[port].supply_voltage);
@@ -3746,6 +3773,16 @@ void pd_task(void *u)
timeout = 20*MSEC;
/*
+ * Don't send any traffic yet until our holdoff timer
+ * has expired. Some devices are chatty once we reach
+ * the SNK_READY state and we may end up in a collision
+ * of messages if we try to immediately send our
+ * interrogations.
+ */
+ if (get_time().val <= pd[port].snk_ready_holdoff_timer)
+ break;
+
+ /*
* Don't send any PD traffic if we woke up due to
* incoming packet or if VDO response pending to avoid
* collisions.