[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