diff options
author | Nathan K <nkolluru@google.com> | 2021-08-31 22:47:51 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-09-03 04:16:56 +0000 |
commit | 7b35af03ae2054071d34dc1fb7892cf7eb1f79d8 (patch) | |
tree | 36c272895edb7565df2296b551c6398d8add7296 /driver/tcpm/tcpci.c | |
parent | a966e7f4cbaff174c92887da833f8f378e2e4291 (diff) | |
download | chrome-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>
Diffstat (limited to 'driver/tcpm/tcpci.c')
-rw-r--r-- | driver/tcpm/tcpci.c | 16 |
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!", |