Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

serial: 8250: Fix TX deadlock when using DMA

`dmaengine_terminate_async` does not guarantee that the
`__dma_tx_complete` callback will run. The callback is currently the
only place where `dma->tx_running` gets cleared. If the transaction is
canceled and the callback never runs, then `dma->tx_running` will never
get cleared and we will never schedule new TX DMA transactions again.

This change makes it so we clear `dma->tx_running` after we terminate
the DMA transaction. This is "safe" because `serial8250_tx_dma_flush`
is holding the UART port lock. The first thing the callback does is also
grab the UART port lock, so access to `dma->tx_running` is serialized.

Fixes: 9e512eaaf8f4 ("serial: 8250: Fix fifo underflow on flush")
Cc: stable <stable@kernel.org>
Signed-off-by: Raul E Rangel <rrangel@google.com>
Link: https://patch.msgid.link/20260209135815.1.I16366ecb0f62f3c96fe3dd5763fcf6f3c2b4d8cd@changeid
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Raul E Rangel and committed by
Greg Kroah-Hartman
a424a34b 1f318b96

+15
+15
drivers/tty/serial/8250/8250_dma.c
··· 162 162 */ 163 163 dma->tx_size = 0; 164 164 165 + /* 166 + * We can't use `dmaengine_terminate_sync` because `uart_flush_buffer` is 167 + * holding the uart port spinlock. 168 + */ 165 169 dmaengine_terminate_async(dma->txchan); 170 + 171 + /* 172 + * The callback might or might not run. If it doesn't run, we need to ensure 173 + * that `tx_running` is cleared so that we can schedule new transactions. 174 + * If it does run, then the zombie callback will clear `tx_running` again 175 + * and perform a no-op since `tx_size` was cleared above. 176 + * 177 + * In either case, we ASSUME the DMA transaction will terminate before we 178 + * issue a new `serial8250_tx_dma`. 179 + */ 180 + dma->tx_running = 0; 166 181 } 167 182 168 183 int serial8250_rx_dma(struct uart_8250_port *p)