diff options
author | Jonathan Brandmeyer <jbrandmeyer@chromium.org> | 2018-10-03 09:16:33 -0600 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-10-04 17:09:01 -0700 |
commit | 31fe290061fdf9d1b0e8a634c77cb7a30b2f012b (patch) | |
tree | 4c86c978f86dce2e5868f71a0e756bb38cbaf7af /driver/tcpm | |
parent | 356083b7f0b36ffd5b8d387e332ff488810ed47e (diff) | |
download | chrome-ec-31fe290061fdf9d1b0e8a634c77cb7a30b2f012b.tar.gz |
tcpc: Resume suspended ports after an interval
When it appears that the TCPC queue handling logic may be stuck in an
infinite loop, the EC will break the loop by disabling the port in order
to avoid task starvation. However, nothing attempts to resume the port,
and it therefore remains disabled until the next EC reset. Wake back up
after a reasonable interval in order to automatically retry. On port
suspend, completely drain the TCPM message queue.
BUG=chromium:891713
TEST=On Careena hardware, with analogix TCPC firmware v1.5 and an
electronically marked cable that sends SOP' messages, verify that the EC
auto-retries every second. After removing the offending cable, and PD
power supply will work.
BRANCH=grunt
Change-Id: I563b763501333eb36ee1f76e6f484ebb3245c82a
Signed-off-by: Jonathan Brandmeyer <jbrandmeyer@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1258571
Reviewed-by: Jett Rink <jettrink@chromium.org>
Diffstat (limited to 'driver/tcpm')
-rw-r--r-- | driver/tcpm/anx74xx.c | 7 | ||||
-rw-r--r-- | driver/tcpm/stub.c | 5 | ||||
-rw-r--r-- | driver/tcpm/tcpci.c | 14 | ||||
-rw-r--r-- | driver/tcpm/tcpm.h | 7 |
4 files changed, 27 insertions, 6 deletions
diff --git a/driver/tcpm/anx74xx.c b/driver/tcpm/anx74xx.c index fd114f7385..e0c01f52dc 100644 --- a/driver/tcpm/anx74xx.c +++ b/driver/tcpm/anx74xx.c @@ -931,13 +931,14 @@ void anx74xx_tcpc_alert(int port) /* Ensure we don't loop endlessly */ if (failed_attempts >= MAX_ALLOW_FAILED_RX_READS) { CPRINTF("C%d Cannot consume RX buffer after %d failed " - "attempts!", - failed_attempts); + "attempts!", port, failed_attempts); /* * The port is in a bad state, we don't want to consume - * all EC resources so suspend port forever. + * all EC resources so suspend the port for a little + * while. */ pd_set_suspend(port, 1); + pd_deferred_resume(port); return; } } diff --git a/driver/tcpm/stub.c b/driver/tcpm/stub.c index 1d748de6b1..23529b5185 100644 --- a/driver/tcpm/stub.c +++ b/driver/tcpm/stub.c @@ -103,6 +103,11 @@ int tcpm_dequeue_message(int port, uint32_t *payload, int *head) return ret; } +void tcpm_clear_pending_messages(int port) +{ + rx_buf_clear(port); +} + int tcpm_transmit(int port, enum tcpm_transmit_type type, uint16_t header, const uint32_t *data) { diff --git a/driver/tcpm/tcpci.c b/driver/tcpm/tcpci.c index 1c1c04868d..00067c18d6 100644 --- a/driver/tcpm/tcpci.c +++ b/driver/tcpm/tcpci.c @@ -446,6 +446,13 @@ int tcpm_dequeue_message(const int port, uint32_t *const payload, return EC_SUCCESS; } +void tcpm_clear_pending_messages(int port) +{ + struct queue *const q = &cached_messages[port]; + + q->tail = q->head; +} + int tcpci_tcpm_transmit(int port, enum tcpm_transmit_type type, uint16_t header, const uint32_t *data) { @@ -528,13 +535,14 @@ void tcpci_tcpc_alert(int port) /* Ensure we don't loop endlessly */ if (failed_attempts >= MAX_ALLOW_FAILED_RX_READS) { CPRINTF("C%d Cannot consume RX buffer after %d failed " - "attempts!", - failed_attempts); + "attempts!", port, failed_attempts); /* * The port is in a bad state, we don't want to consume - * all EC resources so suspend port forever. + * all EC resources so suspend the port for a little + * while. */ pd_set_suspend(port, 1); + pd_deferred_resume(port); return; } } diff --git a/driver/tcpm/tcpm.h b/driver/tcpm/tcpm.h index fc0cd2791d..66792d34c8 100644 --- a/driver/tcpm/tcpm.h +++ b/driver/tcpm/tcpm.h @@ -372,4 +372,11 @@ int tcpm_dequeue_message(int port, uint32_t *payload, int *header); */ int tcpm_has_pending_message(int port); +/** + * Clear any pending messages in the RX queue. This function must be + * called from the same context as the caller of tcpm_dequeue_message to avoid + * race conditions. + */ +void tcpm_clear_pending_messages(int port); + #endif |