Re: serial: 8250: Potential loss of transmission error information in serial8250_handle_irq

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

On 09/06/19 5:20 PM, Oliver Barta wrote:
> Hello,
> 
> there is a small issue in serial8250_handle_irq function.
> 
>     status = serial_port_in(port, UART_LSR);
> 
>     if (status & (UART_LSR_DR | UART_LSR_BI) &&
>         iir & UART_IIR_RDI) {
>         if (!up->dma || handle_rx_dma(up, iir))
>             status = serial8250_rx_chars(up, status);
>     }
> 
> The line status register is read unconditionally but the contained
> error flags are processed only if UART_IIR_RDI bit is set in iir
> variable which was updated by a read of the interrupt identification
> register which happened before the read of LSR. It is unlikely but
> under certain timing conditions (steps for testing below) it may
> happen that some error flags are set while the UART_IIR_RDI bit is
> cleared in iir variable. In this case the error information (e.g.
> framing error or parity error) obtained from LSR will be lost as the
> bits in the hardware register are cleared by the read.
> 

Hmm, I see a different behavior on 8250 OMAP UARTs. LSR status does not
clear/reset back, until associated character is read from UART_RX
register (TRM has this behavior documented). So unconditional read of
LSR register w/o processing received character seems ok for OMAP UART.

This seems to be different wrt Designware UART.

> 
> This problem was introduced by commit
> 
> 2e9fe539108320820016f78ca7704a7342788380 serial: 8250: Don't service
> RX FIFO if interrupts are disabled
> 
> I see two possible solutions, either reverting this change or saving
> the error flags with
> 
> up->lsr_saved_flags |= status & LSR_SAVE_FLAGS;
> 
> in case they are not processed right away as done at several other
> places. I would vote for reverting it but I would like to hear a
> second opinion first.
> 
> 
> The commit message explains that the original change was required
> because some OMAP UART driver disables UART RX FIFO interrupts as
> response to a throttling request and it needs to be ensured that UART
> RX FIFO processing is actually stopped if the corresponding interrupts
> are disabled. I'm not sure if this is the right way to handle a
> throttling request. Based on the documentation in Documentation/serial
> I would expect a throttling request to only trigger hardware flow
> control to inform the sender that it should stop sending data. It
> should be the responsibility of the sender to act accordingly.

8250 OMAP UART support automatic HW flow control, which means HW manages
RTS signal automatically depending of FIFO level. Flow control is
asserted as soon as pre defined RX FIFO threshold is reached and signal
is deasserted once driver drains RX FIFO.
I am not sure if there is a way to assert signal manually when auto flow
control is enabled. Need to explore this option.

> Stopping processing of the input FIFO seems problematic to me as this
> FIFO is typically small and will likely overflow if input processing
> is stopped immediately.
> 

Not really, idea is to stop servicing RX FIFO interrupt and allow RX
FIFO to fill up. Once, FIFO level reaches threshold (3/4 of FIFO in 8250
OMAP UART) flow control line is automatically asserted by UART HW due to
autoRTS.

Also, even though driver disables the interrupt in throttle callback, it
would still service currently pending interrupt which would drain FIFO
completely at least once and then wait for FIFO to fill up to 3/4 before
flow control is asserted. 8250 OMAP UART as 64 byte FIFO and seems to
handle this situation well w/o any HW FIFO overruns in my testing.

I understand that LSR register read as different effect on DesignWare
platforms. Will experiment bit more and come up with a more generic fix
to fix throttling problem within next couple of days.
Otherwise will send a revert for the offending patch.

Regards
Vignesh
> 
> Steps to trigger this issue:
> 1) Send a data packet which is larger than the TX FIFO.
> 2) Trigger an external function generator on the outgoing data packet
> which is programmed to send a character with a parity error with a
> specific delay relative to the outgoing packet so that the character
> is received while the UART_IIR_THRI interrupt is processed in order to
> reload the TX FIFO. In particular it needs to be received between the
> read of IIR and LSR. (During my testing I added a delay of several
> micro seconds between both read operations to increase the probability
> for this to happen.)
> 3) Check if parity error information was properly processed.
> 
> I was testing on an Intel SOC with integrated DesignWare 16550A
> compatible UART without DMA support.
> 
> Best regards,
> Oliver Barta
> 

-- 
Regards
Vignesh



[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux