diff options
author | Namyoon Woo <namyoon@google.com> | 2020-04-03 16:18:20 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-04-04 11:30:11 +0000 |
commit | d87feda6fc337b1bb120866edd85e3a22d6c06ff (patch) | |
tree | c6bd919633bdb40d9f2750d30c2df1cf0ed849b5 /chip | |
parent | 84998e09565a858382a6101c06686e0340743c81 (diff) | |
download | chrome-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>
Diffstat (limited to 'chip')
-rw-r--r-- | chip/g/usart.c | 53 |
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); } |