]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/amdgpu/gfx12: fix EOP interrupt routing for KQ and userq
authorJesse Zhang <Jesse.Zhang@amd.com>
Thu, 11 Jun 2026 02:26:04 +0000 (10:26 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 1 Jul 2026 16:59:56 +0000 (12:59 -0400)
Try KQ by ring_id first (KCQ and UQ never share a HW slot); fall back
to amdgpu_userq_process_fence_irq() on miss, since KCQ EOPs were
misrouted into the userq fence path when enable_mes is true.

Require a strict (me,pipe,queue) match in the gfx case, then userq gfx
EOPs fall through to amdgpu_userq_process_fence_irq().

Suggested-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Jesse Zhang <jesse.zhang@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 6c1f4f7ff08448e0e18cd7fc4e59d6c96a36f25d)
Cc: stable@vger.kernel.org
drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c

index 989c8e2baf6a2b2248b30294942ffdfa850f59ab..3f3b1754c038a8a4087be19caf9742c45497e28f 100644 (file)
@@ -4835,25 +4835,33 @@ static int gfx_v12_0_eop_irq(struct amdgpu_device *adev,
                             struct amdgpu_iv_entry *entry)
 {
        u32 doorbell_offset = entry->src_data[0];
-       u8 me_id, pipe_id, queue_id;
-       struct amdgpu_ring *ring;
-       int i;
 
        DRM_DEBUG("IH: CP EOP\n");
 
-       if (adev->enable_mes && doorbell_offset) {
-               amdgpu_userq_process_fence_irq(adev, doorbell_offset);
-       } else {
-               me_id = (entry->ring_id & 0x0c) >> 2;
-               pipe_id = (entry->ring_id & 0x03) >> 0;
-               queue_id = (entry->ring_id & 0x70) >> 4;
+       if (!adev->gfx.disable_kq) {
+               u8 me_id = (entry->ring_id & 0x0c) >> 2;
+               u8 pipe_id = (entry->ring_id & 0x03) >> 0;
+               u8 queue_id = (entry->ring_id & 0x70) >> 4;
+               struct amdgpu_ring *ring;
+               int i;
 
                switch (me_id) {
                case 0:
-                       if (pipe_id == 0)
-                               amdgpu_fence_process(&adev->gfx.gfx_ring[0]);
-                       else
-                               amdgpu_fence_process(&adev->gfx.gfx_ring[1]);
+                       /*
+                        * MES splits gfx HQDs per (me,pipe): KGQ owns queue=0,
+                        * userq gfx owns queue>=1 (see amdgpu_mes_get_hqd_mask).
+                        * Require a strict (me,pipe,queue) match so userq gfx
+                        * EOPs fall through to amdgpu_userq_process_fence_irq().
+                        */
+                       for (i = 0; i < adev->gfx.num_gfx_rings; i++) {
+                               ring = &adev->gfx.gfx_ring[i];
+                               if ((ring->me == me_id) &&
+                                   (ring->pipe == pipe_id) &&
+                                   (ring->queue == queue_id)) {
+                                       amdgpu_fence_process(ring);
+                                       return 0;
+                               }
+                       }
                        break;
                case 1:
                case 2:
@@ -4865,13 +4873,20 @@ static int gfx_v12_0_eop_irq(struct amdgpu_device *adev,
                                 */
                                if ((ring->me == me_id) &&
                                    (ring->pipe == pipe_id) &&
-                                   (ring->queue == queue_id))
+                                   (ring->queue == queue_id)) {
                                        amdgpu_fence_process(ring);
+                                       return 0;
+                               }
                        }
                        break;
+               default:
+                       break;
                }
        }
 
+       if (adev->enable_mes && doorbell_offset)
+               amdgpu_userq_process_fence_irq(adev, doorbell_offset);
+
        return 0;
 }