• Shardar Shariff Md's avatar
    serial: tegra: handle race condition on uart rx side · 853a6997
    Shardar Shariff Md authored
    The tegra serial driver has two paths through which receive data is
    copied up to the tty layer. These are:
    1. DMA completion callback
    2. UART RX interrupt
    
    A UART RX interrupt occurs for either RX_TIMEOUT (data has been sitting
    in the Rx FIFO for more than 4 character times without being read
    because there is not enough data to reach the trigger level), End of
    Receive Data event (receiver detects that data stops coming in for more
    than 4 character times) or a receive error.
    
    In the RX interrupt path, the following happens ...
    - All RX DMA transfers are stopped
    - Any data in the DMA buffer and RX FIFO are copied up to the tty layer.
    - DMA is restarted/primed for the RX path
    
    In the DMA completion callback, the DMA buffer is copied up to the tty
    layer but there is no check to see if the RX interrupt could have
    occurred between the DMA interrupt firing the the DMA callback running.
    Hence, if a RX interrupt was to occur shortly after the DMA completion
    interrupt, it is possible that the RX interrupt path has already copied
    the DMA buffer before the DMA callback has been called. Therefore, when
    the DMA callback is called, if the DMA is already in-progress, then this
    indicates that the UART RX interrupt has already occurred and there is
    nothing to do in the DMA callback. This race condition can cause
    duplicated data to be received.
    Signed-off-by: default avatarShardar Shariff Md <smohammed@nvidia.com>
    [jonathanh@nvidia.com: Moved async_tx_ack() call to after check to see
     if DMA has completed because if the DMA is in progress we do not need
     to ACK yet. Changed the print from dev_info to dev_debug. Updated
     changelog to add more commentary on the race condition based upon
     feedback from author.]
    Signed-off-by: default avatarJon Hunter <jonathanh@nvidia.com>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    853a6997
serial-tegra.c 37.6 KB