From 44bd0ecc3444882d08ecfbc2b2418d2f463d3186 Mon Sep 17 00:00:00 2001 From: Fan Wu Date: Fri, 21 Aug 2026 07:00:11 -0400 Subject: [PATCH] serial: amba-pl011: synchronize DMA teardown [ Upstream commit 440915499231e9db1c361aa45bb702e8fd3b4a32 ] dmaengine_terminate_all() does not wait for a running callback, so the TX callback can still touch the TX buffer after it is freed. The RX poll timer reads the RX buffers without the port lock. Switch to dmaengine_terminate_sync() and delete the RX timer before freeing the buffers. Fixes: ead76f329f77 ("ARM: 6763/1: pl011: add optional RX DMA to PL011 v2") Cc: stable Assisted-by: Codex:gpt-5.6 Signed-off-by: Fan Wu Link: https://patch.msgid.link/20260731085915.326775-4-fanwu01@zju.edu.cn Signed-off-by: Greg Kroah-Hartman [ changed upstream's `timer_delete_sync()` deletion to match this tree's `del_timer_sync()` spelling at the old call site ] Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index c881d4413b89..82d5b4919409 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1198,7 +1198,7 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap) if (uap->using_tx_dma) { /* In theory, this should already be done by pl011_dma_flush_buffer */ - dmaengine_terminate_all(uap->dmatx.chan); + dmaengine_terminate_sync(uap->dmatx.chan); if (uap->dmatx.queued) { dma_unmap_single(uap->dmatx.chan->device->dev, uap->dmatx.dma, uap->dmatx.len, @@ -1211,12 +1211,12 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap) } if (uap->using_rx_dma) { - dmaengine_terminate_all(uap->dmarx.chan); + if (uap->dmarx.poll_rate) + timer_delete_sync(&uap->dmarx.timer); + dmaengine_terminate_sync(uap->dmarx.chan); /* Clean up the RX DMA */ pl011_dmabuf_free(uap->dmarx.chan, &uap->dmarx.dbuf_a, DMA_FROM_DEVICE); pl011_dmabuf_free(uap->dmarx.chan, &uap->dmarx.dbuf_b, DMA_FROM_DEVICE); - if (uap->dmarx.poll_rate) - del_timer_sync(&uap->dmarx.timer); uap->using_rx_dma = false; } }