summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNamyoon Woo <namyoon@google.com>2020-04-03 16:18:20 -0700
committerCommit Bot <commit-bot@chromium.org>2020-04-04 11:30:11 +0000
commitd87feda6fc337b1bb120866edd85e3a22d6c06ff (patch)
treec6bd919633bdb40d9f2750d30c2df1cf0ed849b5
parent84998e09565a858382a6101c06686e0340743c81 (diff)
downloadchrome-ec-d87feda6fc337b1bb120866edd85e3a22d6c06ff.tar.gz
prevent EC UART TX channel lockup caused by EFS introduction
If UART-EC TX is disabled, the USB input data used to be ignored in UART-EC TX interrupt handler, but it neglected to call uartn_tx_stop(), which was a defect. In this patch, those data shall be ignored when they arrive from USB (in USB RX stream handler), which is earlier than UART-EC TX interrupt, and uartn_tx_start() won't be called. BUG=b:153198965 TEST=Repeated to lock and open CCD, and checked EC-UART is RO or RW. Checked EC-EFS2 working, and uart_stress_tester as well. Signed-off-by: Namyoon Woo <namyoon@google.com> Change-Id: I1c3c2c5a7626850f6389616bbe1f69188d5eca6d Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2135140 Tested-by: Namyoon Woo <namyoon@chromium.org> Reviewed-by: Vadim Bendebury <vbendeb@chromium.org> Commit-Queue: Namyoon Woo <namyoon@chromium.org>
-rw-r--r--chip/g/usart.c53
1 files changed, 31 insertions, 22 deletions
diff --git a/chip/g/usart.c b/chip/g/usart.c
index 4329a673bc..7389d9a911 100644
--- a/chip/g/usart.c
+++ b/chip/g/usart.c
@@ -164,26 +164,6 @@ void get_data_from_usb(struct usart_config const *config)
struct queue const *uart_out = config->consumer.queue;
int c;
-#ifdef BOARD_CR50
- if (config->uart == UART_EC) {
- /*
- * If USB-to-UART bridging is disabled, do not forward data.
- * Otherwise, data could be pushed into UART TX FIFO, and
- * transferred to EC eventually once EC-CR50 communication
- * enables EC UART.
- */
- if (!ec_bridge_tx_enabled_)
- return;
-
- /*
- * If EC-CR50 communication is on-going, then let's not forward
- * console input to EC for now.
- */
- if (ec_comm_is_uart_in_packet_mode(UART_EC))
- return;
- }
-#endif /* BOARD_CR50 */
-
/* Copy output from buffer until TX fifo full or output buffer empty */
while (queue_count(uart_out) && QUEUE_REMOVE_UNITS(uart_out, &c, 1))
uartn_write_char(config->uart, c);
@@ -222,7 +202,7 @@ void send_data_to_usb(struct usart_config const *config)
if (ec_comm_process_packet(ch))
continue;
- if ((count != q_room) && ec_bridge_enabled_) {
+ if ((count != q_room) && uart_ec_bridge_is_enabled()) {
uart_in->buffer[tail] = ch;
tail = (tail + 1) & mask;
count++;
@@ -237,7 +217,7 @@ void send_data_to_usb(struct usart_config const *config)
* If UART-to-USB bridging is not allowed, do not put any output
* data to uart_in queue.
*/
- if ((uart == UART_EC) && !ec_bridge_enabled_)
+ if ((uart == UART_EC) && !uart_ec_bridge_is_enabled())
return;
#endif /* BOARD_CR50 */
@@ -267,6 +247,35 @@ static void uart_written(struct consumer const *consumer, size_t count)
}
#endif
+#ifdef BOARD_CR50
+ if (config->uart == UART_EC) {
+ /*
+ * If USB-to-UART bridging is disabled, do not forward data.
+ * Otherwise, data could be pushed into UART TX FIFO, and
+ * transferred to EC eventually once EC-CR50 communication
+ * enables EC UART.
+ */
+ if (!uart_ec_bridge_tx_is_enabled()) {
+ /*
+ * Empty the RX queue, so that host won't suffer from
+ * congestion. Also, if data remains in the queue, then
+ * they might be transferred when UART TX gets enabled
+ * in future.
+ */
+ queue_advance_head(consumer->queue,
+ queue_count(consumer->queue));
+ return;
+ }
+
+ /*
+ * If EC-CR50 communication is on-going, then let's not forward
+ * console input to EC for now.
+ */
+ if (ec_comm_is_uart_in_packet_mode(UART_EC))
+ return;
+ }
+#endif /* BOARD_CR50 */
+
if (uartn_tx_ready(config->uart) && queue_count(consumer->queue))
uartn_tx_start(config->uart);
}