diff options
author | Diana Z <dzigterman@chromium.org> | 2020-08-27 10:22:41 -0600 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-09-10 02:13:05 +0000 |
commit | cecdf1100bc6d0038fba9f62833e26c2a27f78e2 (patch) | |
tree | 8d81162143950e608e13664cb110675722161285 /driver/tcpm/tcpci.c | |
parent | 075ea16af36d71f22473b7b9cafa860b5083ec3e (diff) | |
download | chrome-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.c | 21 |
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, |