If gfx is hung, we shouldn't need this since gfx won't be
powered down, but we could potentially have a case where
a queue can be preempted, but due logic errors in the commands,
the fence never signals.  GFX could potentially go into
the off state.  Protect against that.

Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Alex Deucher <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 34 +++++++++++++++++---------
 1 file changed, 23 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c 
b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
index f03cbf358cd7b..516a621d11faa 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
@@ -9528,6 +9528,7 @@ static int gfx_v10_0_reset_kgq(struct amdgpu_ring *ring,
                return -ENOMEM;
        }
 
+       amdgpu_gfx_off_ctrl(adev, false);
        addr = amdgpu_bo_gpu_offset(ring->mqd_obj) +
                offsetof(struct v10_gfx_mqd, cp_gfx_hqd_active);
        tmp = REG_SET_FIELD(0, CP_VMID_RESET, RESET_REQUEST, 1 << vmid);
@@ -9547,28 +9548,33 @@ static int gfx_v10_0_reset_kgq(struct amdgpu_ring *ring,
        r = amdgpu_ring_test_ring(kiq_ring);
        spin_unlock_irqrestore(&kiq->ring_lock, flags);
        if (r)
-               return r;
+               goto fail;
 
        r = gfx_v10_0_kgq_init_queue(ring, true);
        if (r) {
                DRM_ERROR("fail to init kgq\n");
-               return r;
+               goto fail;
        }
 
        spin_lock_irqsave(&kiq->ring_lock, flags);
 
        if (amdgpu_ring_alloc(kiq_ring, kiq->pmf->map_queues_size)) {
                spin_unlock_irqrestore(&kiq->ring_lock, flags);
-               return -ENOMEM;
+               r = -ENOMEM;
+               goto fail;
        }
        kiq->pmf->kiq_map_queues(kiq_ring, ring);
        amdgpu_ring_commit(kiq_ring);
        r = amdgpu_ring_test_ring(kiq_ring);
        spin_unlock_irqrestore(&kiq->ring_lock, flags);
        if (r)
-               return r;
+               goto fail;
 
-       return amdgpu_ring_reset_helper_end(ring, timedout_fence);
+       r = amdgpu_ring_reset_helper_end(ring, timedout_fence);
+
+fail:
+       amdgpu_gfx_off_ctrl(adev, true);
+       return r;
 }
 
 static int gfx_v10_0_reset_kcq(struct amdgpu_ring *ring,
@@ -9593,13 +9599,14 @@ static int gfx_v10_0_reset_kcq(struct amdgpu_ring *ring,
                return -ENOMEM;
        }
 
+       amdgpu_gfx_off_ctrl(adev, false);
        kiq->pmf->kiq_unmap_queues(kiq_ring, ring, RESET_QUEUES,
                                   0, 0);
        amdgpu_ring_commit(kiq_ring);
        r = amdgpu_ring_test_ring(kiq_ring);
        spin_unlock_irqrestore(&kiq->ring_lock, flags);
        if (r)
-               return r;
+               goto fail;
 
        /* make sure dequeue is complete*/
        amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
@@ -9617,28 +9624,33 @@ static int gfx_v10_0_reset_kcq(struct amdgpu_ring *ring,
        amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
        if (r) {
                dev_err(adev->dev, "fail to wait on hqd deactivate\n");
-               return r;
+               goto fail;
        }
 
        r = gfx_v10_0_kcq_init_queue(ring, true);
        if (r) {
                dev_err(adev->dev, "fail to init kcq\n");
-               return r;
+               goto fail;
        }
 
        spin_lock_irqsave(&kiq->ring_lock, flags);
        if (amdgpu_ring_alloc(kiq_ring, kiq->pmf->map_queues_size)) {
                spin_unlock_irqrestore(&kiq->ring_lock, flags);
-               return -ENOMEM;
+               r = -ENOMEM;
+               goto fail;
        }
        kiq->pmf->kiq_map_queues(kiq_ring, ring);
        amdgpu_ring_commit(kiq_ring);
        r = amdgpu_ring_test_ring(kiq_ring);
        spin_unlock_irqrestore(&kiq->ring_lock, flags);
        if (r)
-               return r;
+               goto fail;
+
+       r = amdgpu_ring_reset_helper_end(ring, timedout_fence);
 
-       return amdgpu_ring_reset_helper_end(ring, timedout_fence);
+fail:
+       amdgpu_gfx_off_ctrl(adev, true);
+       return r;
 }
 
 static void gfx_v10_ip_print(struct amdgpu_ip_block *ip_block, struct 
drm_printer *p)
-- 
2.54.0

Reply via email to