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
