[PATCH 3/4] dmaengine: dmatest: Terminate channel before freeing threads

From: Nathan Lynch via B4 Relay

Date: Wed Jul 22 2026 - 11:52:43 EST


From: Nathan Lynch <nathan.lynch@xxxxxxx>

On a channel shared by multiple threads, the completion callbacks run from
one tasklet, and dmaengine_terminate_sync() flushes it. Freeing a thread
before that flush can leave a pending callback pointing at freed memory
(dmatest_callback() reads thread->done).

Stop all channel threads and then flush the channel before freeing the
threads.

Fixes: 6f6a23a213be ("dmaengine: dmatest: move callback wait queue to thread context")
Assisted-by: Claude:claude-opus-4-8 [Claude-Code]
Signed-off-by: Nathan Lynch <nathan.lynch@xxxxxxx>
---
drivers/dma/dmatest.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index 3267c7e86f5d..0d7752c2451a 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -959,18 +959,23 @@ static void dmatest_cleanup_channel(struct dmatest_chan *dtc)
struct dmatest_thread *_thread;
int ret;

- list_for_each_entry_safe(thread, _thread, &dtc->threads, node) {
+ /* stop all threads first */
+ list_for_each_entry(thread, &dtc->threads, node) {
ret = kthread_stop(thread->task);
pr_debug("thread %s exited with status %d\n",
thread->task->comm, ret);
+ }
+
+ /* flush the channel (e.g. vchan_synchronize() -> tasklet_kill()) */
+ dmaengine_terminate_sync(dtc->chan);
+
+ /* now it is safe to free the thread memory */
+ list_for_each_entry_safe(thread, _thread, &dtc->threads, node) {
list_del(&thread->node);
put_task_struct(thread->task);
kfree(thread);
}

- /* terminate all transfers on specified channels */
- dmaengine_terminate_sync(dtc->chan);
-
kfree(dtc);
}


--
2.54.0