diff options
author | Nicolas Boichat <drinkcat@google.com> | 2016-12-08 10:25:27 +0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2016-12-08 22:47:00 -0800 |
commit | 0d5562fa73d59d00c1ebf3bfc6a0640f7c3f8f03 (patch) | |
tree | 5cd49884212feb6a7a51522a2ae17e46f1523b6c /driver | |
parent | c7559d4d23b461f21a63e4507b5b0cc403d1b096 (diff) | |
download | chrome-ec-0d5562fa73d59d00c1ebf3bfc6a0640f7c3f8f03.tar.gz |
tcpci_tcpm_get_message: TCPC_REG_RX_BYTE_CNT includes header
From TCPC spec:
"""
RECEIVE_BYTE_COUNT: Indicates number of bytes in this register
that are not stale. The TCPM should read the first RECEIVE_BYTE_COUNT
bytes in this register. This is the number of bytes in the
RX_BUFFER_DATA_OBJECTS plus three (for the RX_BUF_FRAME_TYPE and
RX_BUF_HEADER).
"""
We were always reading 3 bytes too many. This is an issue if we
receive a packet followed by a hard reset, as the register value
will be set back to 0, but TCPC_REG_RX_HDR may contain a valid
header, leading to corrupted packets being passed down the stack.
Also update usb_pd_tcpc to match the specification.
BRANCH=none
BUG=chrome-os-partner:60575
TEST=elm FW as of 65fb80d (later version include a fix that would
hide this issue), cherry-pick this patch, connect j5create
adapter, then HDMI, then power => no crash
Change-Id: I9ed8f3b500d5733ec7563e31246505e0b8bd48bb
Reviewed-on: https://chromium-review.googlesource.com/417442
Commit-Ready: Nicolas Boichat <drinkcat@chromium.org>
Tested-by: Nicolas Boichat <drinkcat@chromium.org>
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
Diffstat (limited to 'driver')
-rw-r--r-- | driver/tcpm/tcpci.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/driver/tcpm/tcpci.c b/driver/tcpm/tcpci.c index 3f4b52657e..68453706c7 100644 --- a/driver/tcpm/tcpci.c +++ b/driver/tcpm/tcpci.c @@ -199,8 +199,16 @@ int tcpci_tcpm_get_message(int port, uint32_t *payload, int *head) rv = tcpc_read(port, TCPC_REG_RX_BYTE_CNT, &cnt); - rv |= tcpc_read16(port, TCPC_REG_RX_HDR, (int *)head); + /* RX_BYTE_CNT includes 3 bytes for frame type and header */ + if (rv != EC_SUCCESS || cnt < 3) { + *head = 0; + rv = EC_ERROR_UNKNOWN; + goto clear; + } + + rv = tcpc_read16(port, TCPC_REG_RX_HDR, (int *)head); + cnt = cnt - 3; if (rv == EC_SUCCESS && cnt > 0) { tcpc_lock(port, 1); rv = tcpc_xfer(port, @@ -209,6 +217,7 @@ int tcpci_tcpm_get_message(int port, uint32_t *payload, int *head) tcpc_lock(port, 0); } +clear: /* Read complete, clear RX status alert bit */ tcpc_write16(port, TCPC_REG_ALERT, TCPC_REG_ALERT_RX_STATUS); |