summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Boichat <drinkcat@google.com>2016-12-08 10:25:27 +0800
committerchrome-bot <chrome-bot@chromium.org>2016-12-08 22:47:00 -0800
commit0d5562fa73d59d00c1ebf3bfc6a0640f7c3f8f03 (patch)
tree5cd49884212feb6a7a51522a2ae17e46f1523b6c
parentc7559d4d23b461f21a63e4507b5b0cc403d1b096 (diff)
downloadchrome-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>
-rw-r--r--common/usb_pd_tcpc.c2
-rw-r--r--driver/tcpm/tcpci.c11
2 files changed, 11 insertions, 2 deletions
diff --git a/common/usb_pd_tcpc.c b/common/usb_pd_tcpc.c
index a9ce499dbc..18e90c583a 100644
--- a/common/usb_pd_tcpc.c
+++ b/common/usb_pd_tcpc.c
@@ -1235,7 +1235,7 @@ static int tcpc_i2c_read(int port, int reg, uint8_t *payload)
payload[1] = (pd[port].alert_mask >> 8) & 0xff;
return 2;
case TCPC_REG_RX_BYTE_CNT:
- payload[0] = 4 *
+ payload[0] = 3 + 4 *
PD_HEADER_CNT(pd[port].rx_head[pd[port].rx_buf_tail]);
return 1;
case TCPC_REG_RX_HDR:
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);