Skip to content

Commit 3135281

Browse files
ij-intelgregkh
authored andcommitted
serial: 8250_dma: Fix DMA Rx completion race
__dma_rx_complete() is called from two places: - Through the DMA completion callback dma_rx_complete() - From serial8250_rx_dma_flush() after IIR_RLSI or IIR_RX_TIMEOUT The former does not hold port's lock during __dma_rx_complete() which allows these two to race and potentially insert the same data twice. Extend port's lock coverage in dma_rx_complete() to prevent the race and check if the DMA Rx is still pending completion before calling into __dma_rx_complete(). Reported-by: Gilles BULOZ <[email protected]> Tested-by: Gilles BULOZ <[email protected]> Fixes: 9ee4b83 ("serial: 8250: Add support for dmaengine") Cc: [email protected] Signed-off-by: Ilpo Järvinen <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 3f6c02f commit 3135281

File tree

1 file changed

+7
-2
lines changed

1 file changed

+7
-2
lines changed

drivers/tty/serial/8250/8250_dma.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,14 @@ static void dma_rx_complete(void *param)
6262
struct uart_8250_dma *dma = p->dma;
6363
unsigned long flags;
6464

65-
__dma_rx_complete(p);
66-
6765
spin_lock_irqsave(&p->port.lock, flags);
66+
if (dma->rx_running)
67+
__dma_rx_complete(p);
68+
69+
/*
70+
* Cannot be combined with the previous check because __dma_rx_complete()
71+
* changes dma->rx_running.
72+
*/
6873
if (!dma->rx_running && (serial_lsr_in(p) & UART_LSR_DR))
6974
p->dma->rx_dma(p);
7075
spin_unlock_irqrestore(&p->port.lock, flags);

0 commit comments

Comments
 (0)