From c5fc9f4edb6a2839e736ad9fab9383f94c274ca8 Mon Sep 17 00:00:00 2001 From: dujunbao <14829755+du-junbao@user.noreply.gitee.com> Date: Tue, 22 Sep 2026 21:43:00 +0800 Subject: [PATCH] ub: cdma: delete queues before the resources they refer to When a cdma device goes away, cdma_release_table_res() walks the device tables in one order and destroys the queued resources first: the CTP table, then the JFS table, then the JFC table, and only after that the queue table. cdma_delete_queue() calls cdma_delete_queue_res() for kernel queues, and that helper reads queue->jfs->id, queue->tp->tp_id and queue->jfc->id to destroy the resources the queue owns. By the time the queue loop runs, those objects have already been freed by the loops above, so any kernel queue that is still registered - a queue whose creator never freed it, or one left behind by a failing client teardown - makes the unload path read freed memory and hand whatever it finds to cdma_delete_jfs(), cdma_delete_ctp() and cdma_delete_jfc() as an id. Delete the queues first. cdma_delete_queue_res() destroys each kernel queue's own resources, so the loops that follow only see what is left in the tables. Removing the current entry while iterating with idr_for_each_entry() is what the existing loops already rely on. Fixes: 10a76983dadb ("ub: cdma: ELR code refactoring") --- drivers/ub/cdma/cdma_dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/ub/cdma/cdma_dev.c b/drivers/ub/cdma/cdma_dev.c index 98586c82e491..af0dcb501090 100644 --- a/drivers/ub/cdma/cdma_dev.c +++ b/drivers/ub/cdma/cdma_dev.c @@ -146,14 +146,14 @@ static void cdma_release_table_res(struct cdma_dev *cdev) struct cdma_tp *tmp; int id; + idr_for_each_entry(&cdev->queue_table.idr_tbl.idr, queue, id) + cdma_delete_queue(cdev, queue->id); idr_for_each_entry(&cdev->ctp_table.idr_tbl.idr, tmp, id) cdma_destroy_ctp_imm(cdev, tmp->base.tp_id); idr_for_each_entry(&cdev->jfs_table.idr_tbl.idr, jfs, id) cdma_delete_jfs(cdev, jfs->id); idr_for_each_entry(&cdev->jfc_table.idr_tbl.idr, jfc, id) cdma_delete_jfc(cdev, jfc->jfcn, NULL); - idr_for_each_entry(&cdev->queue_table.idr_tbl.idr, queue, id) - cdma_delete_queue(cdev, queue->id); idr_for_each_entry(&cdev->seg_table.idr_tbl.idr, seg, id) cdma_unregister_seg(cdev, seg); } -- Gitee