Skip to content

Commit df8f2be

Browse files
amboargregkh
authored andcommitted
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. Cc: ChiaWei Wang <[email protected]> Tested-by: ChiaWei Wang <[email protected]> Reviewed-by: Jiri Slaby <[email protected]> Signed-off-by: Andrew Jeffery <[email protected]> Cc: stable <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 3c35d2a commit df8f2be

File tree

3 files changed

+14
-0
lines changed

3 files changed

+14
-0
lines changed

drivers/tty/serial/8250/8250.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ struct serial8250_config {
8888
#define UART_BUG_NOMSR (1 << 2) /* UART has buggy MSR status bits (Au1x00) */
8989
#define UART_BUG_THRE (1 << 3) /* UART has buggy THRE reassertion */
9090
#define UART_BUG_PARITY (1 << 4) /* UART mishandles parity if FIFO enabled */
91+
#define UART_BUG_TXRACE (1 << 5) /* UART Tx fails to set remote DR */
9192

9293

9394
#ifdef CONFIG_SERIAL_8250_SHARE_IRQ

drivers/tty/serial/8250/8250_aspeed_vuart.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,7 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
437437
port.port.status = UPSTAT_SYNC_FIFO;
438438
port.port.dev = &pdev->dev;
439439
port.port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE);
440+
port.bugs |= UART_BUG_TXRACE;
440441

441442
rc = sysfs_create_group(&vuart->dev->kobj, &aspeed_vuart_attr_group);
442443
if (rc < 0)

drivers/tty/serial/8250/8250_port.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1809,6 +1809,18 @@ void serial8250_tx_chars(struct uart_8250_port *up)
18091809
count = up->tx_loadsz;
18101810
do {
18111811
serial_out(up, UART_TX, xmit->buf[xmit->tail]);
1812+
if (up->bugs & UART_BUG_TXRACE) {
1813+
/*
1814+
* The Aspeed BMC virtual UARTs have a bug where data
1815+
* may get stuck in the BMC's Tx FIFO from bursts of
1816+
* writes on the APB interface.
1817+
*
1818+
* Delay back-to-back writes by a read cycle to avoid
1819+
* stalling the VUART. Read a register that won't have
1820+
* side-effects and discard the result.
1821+
*/
1822+
serial_in(up, UART_SCR);
1823+
}
18121824
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
18131825
port->icount.tx++;
18141826
if (uart_circ_empty(xmit))

0 commit comments

Comments
 (0)