drm/amdkfd: Check preemption status on all XCDs
authorMukul Joshi <mukul.joshi@amd.com>
Thu, 14 Mar 2024 00:26:55 +0000 (20:26 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 20 Mar 2024 17:38:12 +0000 (13:38 -0400)
This patch adds the following functionality:
- Check the queue preemption status on all XCDs in a partition
  for GFX 9.4.3.
- Update the queue preemption debug message to print the queue
  doorbell id for which preemption failed.
- Change the signature of check preemption failed function to
  return a bool instead of uint32_t and pass the MQD manager
  as an argument.

Suggested-by: Jay Cornwall <jay.cornwall@amd.com>
Signed-off-by: Mukul Joshi <mukul.joshi@amd.com>
Reviewed-by: Felix Kuehling <felix.kuehling@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c
drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h
drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c
drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c
drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c
drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c
drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c

index 1ce398ab0b3d11cc92ceb578914d0f9f2d7f7cb3..151fabf84040020f9a925d0069b76adaa2e524d5 100644 (file)
@@ -1997,8 +1997,7 @@ static int unmap_queues_cpsch(struct device_queue_manager *dqm,
         * check those fields
         */
        mqd_mgr = dqm->mqd_mgrs[KFD_MQD_TYPE_HIQ];
-       if (mqd_mgr->check_preemption_failed(dqm->packet_mgr.priv_queue->queue->mqd)) {
-               dev_err(dev, "HIQ MQD's queue_doorbell_id0 is not 0, Queue preemption time out\n");
+       if (mqd_mgr->check_preemption_failed(mqd_mgr, dqm->packet_mgr.priv_queue->queue->mqd)) {
                while (halt_if_hws_hang)
                        schedule();
                return -ETIME;
index 050a6936ff841de7ac62be7c331cb7f9125cca1e..8746a61a852dc230d3c84a843f96478c4cd7bead 100644 (file)
@@ -290,3 +290,21 @@ uint64_t kfd_mqd_stride(struct mqd_manager *mm,
 {
        return mm->mqd_size;
 }
+
+bool kfd_check_hiq_mqd_doorbell_id(struct kfd_node *node, uint32_t doorbell_id,
+                                  uint32_t inst)
+{
+       if (doorbell_id) {
+               struct device *dev = node->adev->dev;
+
+               if (node->adev->xcp_mgr && node->adev->xcp_mgr->num_xcps > 0)
+                       dev_err(dev, "XCC %d: Queue preemption failed for queue with doorbell_id: %x\n",
+                                                       inst, doorbell_id);
+               else
+                       dev_err(dev, "Queue preemption failed for queue with doorbell_id: %x\n",
+                                                       doorbell_id);
+               return true;
+       }
+
+       return false;
+}
index ba3eebb2ca6de6435962a78345f8e2b9dcafdba3..17cc1f25c8d08a967180ebe9fd5318591c47a35f 100644 (file)
@@ -119,7 +119,7 @@ struct mqd_manager {
 #if defined(CONFIG_DEBUG_FS)
        int     (*debugfs_show_mqd)(struct seq_file *m, void *data);
 #endif
-       uint32_t (*check_preemption_failed)(void *mqd);
+       bool (*check_preemption_failed)(struct mqd_manager *mm, void *mqd);
        uint64_t (*mqd_stride)(struct mqd_manager *mm,
                                struct queue_properties *p);
 
@@ -198,4 +198,6 @@ void kfd_get_hiq_xcc_mqd(struct kfd_node *dev,
 uint64_t kfd_hiq_mqd_stride(struct kfd_node *dev);
 uint64_t kfd_mqd_stride(struct mqd_manager *mm,
                        struct queue_properties *q);
+bool kfd_check_hiq_mqd_doorbell_id(struct kfd_node *node, uint32_t doorbell_id,
+                                  uint32_t inst);
 #endif /* KFD_MQD_MANAGER_H_ */
index 8f9f56f7a8b041458ba1c7436310c41fa6ef0743..05f3ac2eaef9e2fdde6f00ced6965b1e9fddbb84 100644 (file)
@@ -206,11 +206,11 @@ static void __update_mqd(struct mqd_manager *mm, void *mqd,
        q->is_active = QUEUE_IS_ACTIVE(*q);
 }
 
-static uint32_t check_preemption_failed(void *mqd)
+static bool check_preemption_failed(struct mqd_manager *mm, void *mqd)
 {
        struct cik_mqd *m = (struct cik_mqd *)mqd;
 
-       return m->queue_doorbell_id0;
+       return kfd_check_hiq_mqd_doorbell_id(mm->dev, m->queue_doorbell_id0, 0);
 }
 
 static void update_mqd(struct mqd_manager *mm, void *mqd,
index d4cf7d845928e3ebe936d57c043117b2bed8696e..2eff37aaf8273bfd6f35d289fe3acbd97253ab27 100644 (file)
@@ -224,11 +224,11 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
        q->is_active = QUEUE_IS_ACTIVE(*q);
 }
 
-static uint32_t check_preemption_failed(void *mqd)
+static bool check_preemption_failed(struct mqd_manager *mm, void *mqd)
 {
        struct v10_compute_mqd *m = (struct v10_compute_mqd *)mqd;
 
-       return m->queue_doorbell_id0;
+       return kfd_check_hiq_mqd_doorbell_id(mm->dev, m->queue_doorbell_id0, 0);
 }
 
 static int get_wave_state(struct mqd_manager *mm, void *mqd,
index 2b9f57c267eb7c68153f813090988cae82bbb80b..68dbc0399c87aa17c0ffd0c6b4816bb485022dae 100644 (file)
@@ -278,11 +278,11 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
        q->is_active = QUEUE_IS_ACTIVE(*q);
 }
 
-static uint32_t check_preemption_failed(void *mqd)
+static bool check_preemption_failed(struct mqd_manager *mm, void *mqd)
 {
        struct v11_compute_mqd *m = (struct v11_compute_mqd *)mqd;
 
-       return m->queue_doorbell_id0;
+       return kfd_check_hiq_mqd_doorbell_id(mm->dev, m->queue_doorbell_id0, 0);
 }
 
 static int get_wave_state(struct mqd_manager *mm, void *mqd,
index 7c93a0932677fa571eed88d9721a14f876b0383c..6bddc16808d7a909ce669c2da6eabb5186f88cef 100644 (file)
@@ -316,11 +316,11 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
 }
 
 
-static uint32_t check_preemption_failed(void *mqd)
+static bool check_preemption_failed(struct mqd_manager *mm, void *mqd)
 {
        struct v9_mqd *m = (struct v9_mqd *)mqd;
 
-       return m->queue_doorbell_id0;
+       return kfd_check_hiq_mqd_doorbell_id(mm->dev, m->queue_doorbell_id0, 0);
 }
 
 static int get_wave_state(struct mqd_manager *mm, void *mqd,
@@ -607,6 +607,24 @@ static int destroy_hiq_mqd_v9_4_3(struct mqd_manager *mm, void *mqd,
        return err;
 }
 
+static bool check_preemption_failed_v9_4_3(struct mqd_manager *mm, void *mqd)
+{
+       uint64_t hiq_mqd_size = kfd_hiq_mqd_stride(mm->dev);
+       uint32_t xcc_mask = mm->dev->xcc_mask;
+       int inst = 0, xcc_id;
+       struct v9_mqd *m;
+       bool ret = false;
+
+       for_each_inst(xcc_id, xcc_mask) {
+               m = get_mqd(mqd + hiq_mqd_size * inst);
+               ret |= kfd_check_hiq_mqd_doorbell_id(mm->dev,
+                                       m->queue_doorbell_id0, inst);
+               ++inst;
+       }
+
+       return ret;
+}
+
 static void get_xcc_mqd(struct kfd_mem_obj *mqd_mem_obj,
                               struct kfd_mem_obj *xcc_mqd_mem_obj,
                               uint64_t offset)
@@ -881,15 +899,16 @@ struct mqd_manager *mqd_manager_init_v9(enum KFD_MQD_TYPE type,
 #if defined(CONFIG_DEBUG_FS)
                mqd->debugfs_show_mqd = debugfs_show_mqd;
 #endif
-               mqd->check_preemption_failed = check_preemption_failed;
                if (KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 3)) {
                        mqd->init_mqd = init_mqd_hiq_v9_4_3;
                        mqd->load_mqd = hiq_load_mqd_kiq_v9_4_3;
                        mqd->destroy_mqd = destroy_hiq_mqd_v9_4_3;
+                       mqd->check_preemption_failed = check_preemption_failed_v9_4_3;
                } else {
                        mqd->init_mqd = init_mqd_hiq;
                        mqd->load_mqd = kfd_hiq_load_mqd_kiq;
                        mqd->destroy_mqd = destroy_hiq_mqd;
+                       mqd->check_preemption_failed = check_preemption_failed;
                }
                break;
        case KFD_MQD_TYPE_DIQ:
index dbc868e0363fdb931fa0a464c2931f824dd86563..c1fafc50251589824e5d13f2c58e0c259364027d 100644 (file)
@@ -237,11 +237,11 @@ static void __update_mqd(struct mqd_manager *mm, void *mqd,
        q->is_active = QUEUE_IS_ACTIVE(*q);
 }
 
-static uint32_t check_preemption_failed(void *mqd)
+static bool check_preemption_failed(struct mqd_manager *mm, void *mqd)
 {
        struct vi_mqd *m = (struct vi_mqd *)mqd;
 
-       return m->queue_doorbell_id0;
+       return kfd_check_hiq_mqd_doorbell_id(mm->dev, m->queue_doorbell_id0, 0);
 }
 
 static void update_mqd(struct mqd_manager *mm, void *mqd,