Thread (6 messages) 6 messages, 3 authors, 2021-05-20

RE: [PATCH v3 1/2] serial: 8250: Add UART_BUG_TXRACE workaround for Aspeed VUART

From: ChiaWei Wang <hidden>
Date: 2021-05-20 05:42:34
Also in: linux-aspeed, linux-serial, lkml, openbmc

-----Original Message-----
From: Jiri Slaby <jirislaby@kernel.org>
Sent: Thursday, May 20, 2021 1:25 PM

On 20. 05. 21, 4:13, Andrew Jeffery wrote:
quoted
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.
quoted
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 <redacted>
Signed-off-by: Andrew Jeffery <redacted>
Reviewed-by: Jiri Slaby <jirislaby@kernel.org>
Tested-by: ChiaWei Wang <redacted>
quoted
---
  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(+)
diff --git a/drivers/tty/serial/8250/8250.h
b/drivers/tty/serial/8250/8250.h index 52bb21205bb6..34aa2714f3c9
100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -88,6 +88,7 @@ struct serial8250_config {
  #define UART_BUG_NOMSR	(1 << 2)	/* UART has buggy MSR status
bits (Au1x00) */
quoted
  #define UART_BUG_THRE	(1 << 3)	/* UART has buggy THRE
reassertion */
quoted
  #define UART_BUG_PARITY	(1 << 4)	/* UART mishandles parity if FIFO
enabled */
quoted
+#define UART_BUG_TXRACE	(1 << 5)	/* UART Tx fails to set remote DR
*/
quoted

  #ifdef CONFIG_SERIAL_8250_SHARE_IRQ
diff --git a/drivers/tty/serial/8250/8250_aspeed_vuart.c
b/drivers/tty/serial/8250/8250_aspeed_vuart.c
index a28a394ba32a..4caab8714e2c 100644
--- a/drivers/tty/serial/8250/8250_aspeed_vuart.c
+++ b/drivers/tty/serial/8250/8250_aspeed_vuart.c
@@ -440,6 +440,7 @@ static int aspeed_vuart_probe(struct
platform_device *pdev)
quoted
  	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);
quoted
  	if (rc < 0)
diff --git a/drivers/tty/serial/8250/8250_port.c
b/drivers/tty/serial/8250/8250_port.c
index d45dab1ab316..fc5ab2032282 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -1809,6 +1809,18 @@ void serial8250_tx_chars(struct uart_8250_port
*up)
quoted
  	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))
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help