• Qipan Li's avatar
    serial: sirf: workaround rx process to avoid possible data loss · 1d26c9ff
    Qipan Li authored
    when UART works in DMA mode and left bytes in rx fifo less than
    a dma transfer unit, DMA engine can't transfer the bytes out
    to rx DMA buffer. so it need a way to fetch them out and
    flush them into tty buffer in time.
    
    in the above case, we want UART switch from DMA mode to PIO mode and
    fetch && flush bytes into tty layer buffer until rxfifo become empty,
    after that done let UART switch from PIO mode back to DMA mode.
    (record as method1)
    
    method1 result in the next receive result wrong. for example in PIO part
    of method1, we fetched && pushed X1...X3 bytes, when UART rxfifo newly
    received Y1...Y4 bytes, UART trigger a DMA unit transfer, the DMA unit's
    content is X1...X3Y1 and rxfifo fifo status is empty, so X1X2X3 pushed
    twice by PIO way and DMA way also the bytes Y2Y3Y4 missed. add rxfifo
    reset operation before UART switch back to DMA mode would resolve the
    issue. ([method1 + do fifo reset] record as method2)
    
    before the commit, UART driver use method2. but methd2 have a risk of
    data loss, as if UART's shift register receive a complete byte and
    transfer it into rxfifo before rxfifo reset operation the byte will
    loss.
    
    UART and USP have the similar bits CLEAR_RX_ADDR_EN(uart)/FRADDR_CLR_EN(usp),
    When found UART controller changing I/O to DMA mode, UART controller
    clears the two low bits of read point (rx_fifo_addr[1:0]).
    when enable the bit + method1(record as method3), in above example
    the DMA unit's content is X1...X3Y1 and there are Y2Y3Y4 in rxfifo by
    experiment, we just push bytes in rx DMA buffer.
    
    BTW, the workaround works only for UART receive DMA channel use SINGLE
    DMA mode.
    Signed-off-by: default avatarQipan Li <Qipan.Li@csr.com>
    Signed-off-by: default avatarBarry Song <Baohua.Song@csr.com>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    1d26c9ff
sirfsoc_uart.c 47.8 KB