[PATCH] serial: 8250: Fix THRE flag usage for CAP_MINI

Stefan Wahren stefan.wahren at i2se.com
Mon Jun 26 08:05:21 PDT 2017


Hi Phil,

Am 26.06.2017 um 15:59 schrieb Phil Elwell:
> The BCM2835 MINI UART has non-standard THRE semantics. Conventionally
> the bit means that the FIFO is empty (although there may still be a
> byte in the transmit register), but on 2835 it indicates that the FIFO
> is not full. This causes interrupts after every byte is transmitted,
> with the FIFO providing some interrupt latency tolerance.
>
> A consequence of this difference is that the usual strategy of writing
> multiple bytes into the TX FIFO after checking THRE once is unsafe.
> In the worst case of 7 bytes in the FIFO, writing 8 bytes loses all
> but the first since by then the FIFO is full.
>
> There is an HFIFO ("Hidden FIFO") capability that causes the transmit
> loop to terminate when both THRE and TEMT are set, i.e. when the TX
> block is completely idle. This is unnecessarily cautious, potentially
> causing gaps in transmission.
>
> Add a new conditional to the transmit loop, predicated on CAP_MINI,
> that exits when THRE is no longer set (the FIFO is full). This allows
> the FIFO to fill quickly but subsequent writes are paced by the
> transmission rate.

thanks for this good explanation.

But this looks like a bug / quirk than a capability?

It would be better to name this define more self-explaining.

Btw can't see the definition of UART_CAP_MINI?

Thanks
Stefan

>
> Signed-off-by: Phil Elwell <phil at raspberrypi.org>
> ---
>  drivers/tty/serial/8250/8250_port.c | 4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
> index 4c620be..a5fe0e6 100644
> --- a/drivers/tty/serial/8250/8250_port.c
> +++ b/drivers/tty/serial/8250/8250_port.c
> @@ -1764,6 +1764,10 @@ void serial8250_tx_chars(struct uart_8250_port *up)
>  		if ((up->capabilities & UART_CAP_HFIFO) &&
>  		    (serial_in(up, UART_LSR) & BOTH_EMPTY) != BOTH_EMPTY)
>  			break;
> +		/* The BCM2835 MINI UART THRE bit is really a not-full bit. */
> +		if ((up->capabilities & UART_CAP_MINI) &&
> +		    !(serial_in(up, UART_LSR) & UART_LSR_THRE))
> +			break;
>  	} while (--count > 0);
>  
>  	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)



More information about the linux-rpi-kernel mailing list