Public

Reviewed-by: Harish [email protected]
________________________________
From: Huang, JinHuiEric <[email protected]>
Sent: Thursday, June 11, 2026 2:43 PM
To: [email protected] <[email protected]>
Cc: Kasiviswanathan, Harish <[email protected]>; Huang, JinHuiEric 
<[email protected]>
Subject: [PATCH] drm/amdkfd: avoid race condition of mqd when reading sdma 
counter

MQD used outside of dpm_lock is unsafe because of the queue
could be destroyed during the window of dqm_unlock, moving into
dqm_lock range is the best practice.

Signed-off-by: Eric Huang <[email protected]>
---
 drivers/gpu/drm/amd/amdkfd/kfd_process.c | 32 +++++++++++++-----------
 1 file changed, 18 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
index e0b885b2395a..1cf689cb5e2c 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -91,7 +91,6 @@ struct kfd_sdma_activity_handler_workarea {

 struct temp_sdma_queue_list {
         uint64_t __user *rptr;
-       void *mqd;
         uint64_t sdma_val;
         unsigned int queue_id;
         struct list_head list;
@@ -154,6 +153,22 @@ static void kfd_sdma_activity_worker(struct work_struct 
*work)
                     (q->properties.type != KFD_QUEUE_TYPE_SDMA_XGMI))
                         continue;

+               if (KFD_GC_VERSION(dqm->dev) > IP_VERSION(9, 4, 2)) {
+                       ret = dqm->dev->kfd2kgd->hqd_sdma_get_counter ?
+                             dqm->dev->kfd2kgd->hqd_sdma_get_counter(
+                                       dqm->dev->adev, q->mqd,
+                                       
dqm->dev->kfd->device_info.num_sdma_queues_per_engine,
+                                       &val) :
+                             -EOPNOTSUPP;
+
+                       if (ret)
+                               pr_debug("Failed to read SDMA queue active 
counter %i\n", ret);
+                       else
+                               workarea->sdma_activity_counter += val;
+
+                       continue;
+               }
+
                 sdma_q = kzalloc(sizeof(struct temp_sdma_queue_list), 
GFP_KERNEL);
                 if (!sdma_q) {
                         dqm_unlock(dqm);
@@ -162,7 +177,6 @@ static void kfd_sdma_activity_worker(struct work_struct 
*work)

                 INIT_LIST_HEAD(&sdma_q->list);
                 sdma_q->rptr = (uint64_t __user *)q->properties.read_ptr;
-               sdma_q->mqd = q->mqd;
                 sdma_q->queue_id = q->properties.queue_id;
                 list_add_tail(&sdma_q->list, &sdma_q_list.list);
         }
@@ -173,7 +187,7 @@ static void kfd_sdma_activity_worker(struct work_struct 
*work)
          * count
          */
         if (list_empty(&sdma_q_list.list)) {
-               workarea->sdma_activity_counter = 
pdd->sdma_past_activity_counter;
+               workarea->sdma_activity_counter += 
pdd->sdma_past_activity_counter;
                 dqm_unlock(dqm);
                 return;
         }
@@ -191,17 +205,7 @@ static void kfd_sdma_activity_worker(struct work_struct 
*work)

         list_for_each_entry(sdma_q, &sdma_q_list.list, list) {
                 val = 0;
-
-               if (KFD_GC_VERSION(dqm->dev) <= IP_VERSION(9, 4, 2))
-                       ret = read_sdma_queue_counter(sdma_q->rptr, &val);
-               else
-                       ret = dqm->dev->kfd2kgd->hqd_sdma_get_counter ?
-                             dqm->dev->kfd2kgd->hqd_sdma_get_counter(
-                                       dqm->dev->adev, sdma_q->mqd,
-                                       
dqm->dev->kfd->device_info.num_sdma_queues_per_engine,
-                                       &val) :
-                             -EOPNOTSUPP;
-
+               ret = read_sdma_queue_counter(sdma_q->rptr, &val);
                 if (ret) {
                         pr_debug("Failed to read SDMA queue active counter for 
queue id: %d",
                                  sdma_q->queue_id);
--
2.34.1

Reply via email to