summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan K <nkolluru@google.com>2021-08-31 22:47:51 -0700
committerCommit Bot <commit-bot@chromium.org>2021-09-03 04:16:56 +0000
commit7b35af03ae2054071d34dc1fb7892cf7eb1f79d8 (patch)
tree36c272895edb7565df2296b551c6398d8add7296
parenta966e7f4cbaff174c92887da833f8f378e2e4291 (diff)
downloadchrome-ec-7b35af03ae2054071d34dc1fb7892cf7eb1f79d8.tar.gz
tcpm: Mitigate EC RX circular buffer overflow
There are two FIFO buffers for USB-PD packet reception. One is located in TCPC, another was added in EC layer in crrev/c/1185727 . There are scenarios that may lead to overflow. In these scenarios, the EC RX circular buffer overflows without clearing the TCPC ALERT# signal. This in turn results in a tight-loop in the TCPC interrupt handler, leading to port "suspend". This CL is a reduced hotfix to mitigate this scenario. Further CL is needed to perform proper TCPCI spec-compliant overflow handling. BRANCH=none BUG=b:192382194 TEST=1. Connect CB282K via DP to G5 dock on old FW 2. Connect G5 dock to AKEMI on TCPMv1 3. Allow MST VDM:Attention communication to occur 4. Observe EC console prints via SuzyQ Change-Id: Ic579a3763fc595b8250d4ca78c3942675450295a Signed-off-by: Nathan K <nkolluru@google.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3135041 Reviewed-by: Aseda Aboagye <aaboagye@chromium.org>
-rw-r--r--driver/tcpm/tcpci.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/driver/tcpm/tcpci.c b/driver/tcpm/tcpci.c
index 282718bae2..73a4b68295 100644
--- a/driver/tcpm/tcpci.c
+++ b/driver/tcpm/tcpci.c
@@ -1166,6 +1166,7 @@ void tcpci_tcpc_alert(int port)
int alert_ext = 0;
int failed_attempts;
uint32_t pd_event = 0;
+ int retval = 0;
/* Read the Alert register from the TCPC */
if (tcpm_alert_status(port, &alert)) {
@@ -1201,11 +1202,24 @@ void tcpci_tcpc_alert(int port)
/* Pull all RX messages from TCPC into EC memory */
failed_attempts = 0;
while (alert & TCPC_REG_ALERT_RX_STATUS) {
- if (tcpm_enqueue_message(port))
+ retval = tcpm_enqueue_message(port);
+ if (retval)
++failed_attempts;
if (tcpm_alert_status(port, &alert))
++failed_attempts;
+
+ /*
+ * EC RX FIFO is full. Deassert ALERT# line to exit interrupt
+ * handler by discarding pending message from TCPC RX FIFO.
+ */
+ if (retval == EC_ERROR_OVERFLOW) {
+ CPRINTS("C%d: PD RX OVF!", port);
+ tcpc_write16(port, TCPC_REG_ALERT,
+ TCPC_REG_ALERT_RX_STATUS |
+ TCPC_REG_ALERT_RX_BUF_OVF);
+ }
+
/* Ensure we don't loop endlessly */
if (failed_attempts >= MAX_ALLOW_FAILED_RX_READS) {
CPRINTS("C%d Cannot consume RX buffer after %d failed attempts!",