patch "serial: 8250: Add UART_BUG_TXRACE workaround for Aspeed VUART" added to tty-linus
This is a note to let you know that I've just added the patch titled
serial: 8250: Add UART_BUG_TXRACE workaround for Aspeed VUART
to my tty git tree which can be found at
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git
in the tty-linus branch.
The patch will show up in the next release of the linux-next tree (usually sometime within the next 24 hours during the week.)
The patch will hopefully also be merged in Linus's tree for the next -rc kernel release.
If you have any questions about this process, please let me know.
From df8f2be2fd0b44b2cb6077068f52e05f0ac40897 Mon Sep 17 00:00:00 2001
From: Andrew Jeffery <[email protected]>
Date: Thu, 20 May 2021 11:43:33 +0930
Subject: serial: 8250: Add UART_BUG_TXRACE workaround for Aspeed VUART
Aspeed Virtual UARTs directly bridge e.g. the system console UART on the LPC bus to the UART interface on the BMC's internal APB. As such there's no RS-232 signalling involved - the UART interfaces on each bus are directly connected as the producers and consumers of the one set of FIFOs.
The APB in the AST2600 generally runs at 100MHz while the LPC bus peaks at 33MHz. The difference in clock speeds exposes a race in the VUART design where a Tx data burst on the APB interface can result in a byte lost on the LPC interface. The symptom is LSR[DR] remains clear on the LPC interface despite data being present in its Rx FIFO, while LSR[THRE] remains clear on the APB interface as the host has not consumed the data the BMC has transmitted. In this state, the UART has stalled and no further data can be transmitted without manual intervention (e.g. resetting the FIFOs, resulting in loss of data).
The recommended work-around is to insert a read cycle on the APB interface between writes to THR.
--- drivers/tty/serial/8250/8250.h | 1 + drivers/tty/serial/8250/8250_aspeed_vuart.c | 1 + drivers/tty/serial/8250/8250_port.c | 12 ++++++++++++ 3 files changed, 14 insertions(+)
drivers/tty/serial/8250/8250.h +1 -0
@@ -88,6 +88,7 @@ struct serial8250_config {#define UART_BUG_NOMSR (1 << 2)/* UART has buggy MSR status bits (Au1x00) */ #define UART_BUG_THRE (1 << 3)/* UART has buggy THRE reassertion */ #define UART_BUG_PARITY (1 << 4)/* UART mishandles parity if FIFO enabled */ +#define UART_BUG_TXRACE (1 << 5)/* UART Tx fails to set remote DR */ #ifdef CONFIG_SERIAL_8250_SHARE_IRQ
drivers/tty/serial/8250/8250_aspeed_vuart.c +1 -0
@@ -437,6 +437,7 @@ static int aspeed_vuart_probe(struct platform_device *pdev) port.port.status =UPSTAT_SYNC_FIFO ; port.port.dev = &pdev->dev; port.port.has_sysrq =IS_ENABLED (CONFIG_SERIAL_8250_CONSOLE ); + port.bugs |=UART_BUG_TXRACE ; rc =sysfs_create_group (&vuart->dev->kobj, &aspeed_vuart_attr_group);if (rc <0 )
drivers/tty/serial/8250/8250_port.c +12 -0
@@ -1809,6 +1809,18 @@ void serial8250_tx_chars(struct uart_8250_port *up) count = up->tx_loadsz; do { serial_out(up, UART_TX, xmit->buf[xmit->tail]); + if (up->bugs & UART_BUG_TXRACE) { + /* + * The Aspeed BMC virtual UARTs have a bug where data + * may get stuck in the BMC's Tx FIFO from bursts of + * writes on the APB interface. + * + * Delay back-to-back writes by a read cycle to avoid + * stalling the VUART. Read a register that won't have + * side-effects and discard the result. + */ + serial_in(up, UART_SCR); + } xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); port->icount.tx++; if (uart_circ_empty(xmit))
Signature · 1 line
2.31.1