summaryrefslogtreecommitdiff
path: root/driver/tcpm/tcpci.c
diff options
context:
space:
mode:
authorDiana Z <dzigterman@chromium.org>2020-08-27 10:22:41 -0600
committerCommit Bot <commit-bot@chromium.org>2020-09-10 02:13:05 +0000
commitcecdf1100bc6d0038fba9f62833e26c2a27f78e2 (patch)
tree8d81162143950e608e13664cb110675722161285 /driver/tcpm/tcpci.c
parent075ea16af36d71f22473b7b9cafa860b5083ec3e (diff)
downloadchrome-ec-cecdf1100bc6d0038fba9f62833e26c2a27f78e2.tar.gz
TCPCI: Stop I2C transfer after discovering no message to read
Set I2C_XFER_STOP after reading an invalid number of bytes, either a count less than 0 or one larger than the driver can cache. Also ensure the STOP is sent on failed header reads. BRANCH=None BUG=b:162557086 TEST=on boten, charging ports do not become stuck on dongle unplug Signed-off-by: Diana Z <dzigterman@chromium.org> Change-Id: I51a07fe629a58b61fe2f1d34425741acbfab8cba Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2380174
Diffstat (limited to 'driver/tcpm/tcpci.c')
-rw-r--r--driver/tcpm/tcpci.c21
1 files changed, 15 insertions, 6 deletions
diff --git a/driver/tcpm/tcpci.c b/driver/tcpm/tcpci.c
index 64de918dff..0c281f5ffd 100644
--- a/driver/tcpm/tcpci.c
+++ b/driver/tcpm/tcpci.c
@@ -748,22 +748,28 @@ static int tcpci_rev2_0_tcpm_get_message_raw(int port, uint32_t *payload,
cnt = tmp[0];
frm = tmp[1];
- /* READABLE_BYTE_COUNT includes 3 bytes for frame type and header */
+ /*
+ * READABLE_BYTE_COUNT includes 3 bytes for frame type and header, and
+ * may be 0 if the TCPC saw a disconnect before the message read
+ */
cnt -= 3;
- if (cnt > member_size(struct cached_tcpm_message, payload)) {
+ if ((cnt < 0) ||
+ (cnt > member_size(struct cached_tcpm_message, payload))) {
+ /* Continue to send the stop bit with the header read */
rv = EC_ERROR_UNKNOWN;
- goto clear;
+ cnt = 0;
}
/* The next two bytes are the header */
- rv = tcpc_xfer_unlocked(port, NULL, 0, (uint8_t *)head, 2,
+ rv |= tcpc_xfer_unlocked(port, NULL, 0, (uint8_t *)head, 2,
cnt ? 0 : I2C_XFER_STOP);
/* Encode message address in bits 31 to 28 */
*head &= 0x0000ffff;
*head |= PD_HEADER_SOP(frm);
- if (rv == EC_SUCCESS && cnt > 0) {
+ /* Execute read and I2C_XFER_STOP, even if header read failed */
+ if (cnt > 0) {
tcpc_xfer_unlocked(port, NULL, 0, (uint8_t *)payload, cnt,
I2C_XFER_STOP);
}
@@ -773,7 +779,10 @@ clear:
/* Read complete, clear RX status alert bit */
tcpc_write16(port, TCPC_REG_ALERT, TCPC_REG_ALERT_RX_STATUS);
- return rv;
+ if (rv)
+ return EC_ERROR_UNKNOWN;
+
+ return EC_SUCCESS;
}
static int tcpci_rev1_0_tcpm_get_message_raw(int port, uint32_t *payload,