Implement detect_hung_queue() by matching enabled HQD doorbells over
MMIO, allowing GFX reset to locate the queue without a MES request.

Signed-off-by: Jesse Zhang <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 38 ++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c 
b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
index a7ed4923857b..76e133d283a9 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
@@ -1102,6 +1102,43 @@ static int gfx_v11_0_get_gfx_shadow_info(struct 
amdgpu_device *adev,
        }
 }
 
+static bool gfx_v11_0_detect_hung_queue(struct amdgpu_device *adev,
+                                       u32 doorbell_index,
+                                       u32 *me, u32 *pipe, u32 *queue)
+{
+       u32 i, k, p, db_ctrl, dboff;
+       bool found = false;
+
+       amdgpu_gfx_off_ctrl(adev, false);
+       mutex_lock(&adev->srbm_mutex);
+       for (i = 0; i < adev->gfx.me.num_me && !found; i++) {
+               for (p = 0; p < adev->gfx.me.num_pipe_per_me && !found; p++) {
+                       for (k = 0; k < adev->gfx.me.num_queue_per_pipe; k++) {
+                               soc21_grbm_select(adev, i, p, k, 0);
+                               db_ctrl = RREG32_SOC15(GC, 0,
+                                                      
regCP_RB_DOORBELL_CONTROL);
+                               if (!(db_ctrl & 
CP_RB_DOORBELL_CONTROL__DOORBELL_EN_MASK))
+                                       continue;
+                               dboff = (db_ctrl &
+                                        
CP_RB_DOORBELL_CONTROL__DOORBELL_OFFSET_MASK) >>
+                                       
CP_RB_DOORBELL_CONTROL__DOORBELL_OFFSET__SHIFT;
+                               if (dboff == doorbell_index) {
+                                       *me = i;
+                                       *pipe = p;
+                                       *queue = k;
+                                       found = true;
+                                       break;
+                               }
+                       }
+               }
+       }
+       soc21_grbm_select(adev, 0, 0, 0, 0);
+       mutex_unlock(&adev->srbm_mutex);
+       amdgpu_gfx_off_ctrl(adev, true);
+
+       return found;
+}
+
 static const struct amdgpu_gfx_funcs gfx_v11_0_gfx_funcs = {
        .get_gpu_clock_counter = &gfx_v11_0_get_gpu_clock_counter,
        .select_se_sh = &gfx_v11_0_select_se_sh,
@@ -1112,6 +1149,7 @@ static const struct amdgpu_gfx_funcs gfx_v11_0_gfx_funcs 
= {
        .update_perfmon_mgcg = &gfx_v11_0_update_perf_clk,
        .get_gfx_shadow_info = &gfx_v11_0_get_gfx_shadow_info,
        .get_hdp_flush_mask = &amdgpu_gfx_get_hdp_flush_mask,
+       .detect_hung_queue = &gfx_v11_0_detect_hung_queue,
 };
 
 static int gfx_v11_0_gpu_early_init(struct amdgpu_device *adev)
-- 
2.49.0

Reply via email to