[PATCH] serial: 8250: Fix THRE flag usage for CAP_MINI
Phil Elwell
phil at raspberrypi.org
Mon Jun 26 08:15:37 PDT 2017
Hi Stefan,
On 26/06/2017 16:05, Stefan Wahren wrote:
> 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?
The capability was added in d087e7a991f1f61ee2c07db1be7c5cc2aa373f5d, which
is in linux-next. Given that the "capability" already exists and the quirk
is likely to be unique to BCM2835 MINI UART, I don't think we should create
a new quirk.
Besides, the "HFIFO" capability looks a lot like quirk to me.
Thanks,
Phil
>>
>> 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