Hold MEC pipe reset asserted, walk every queue on that (me, pipe) and tear down CP_HQD_ACTIVE / CP_HQD_DEQUEUE_REQUEST via gfx_v11_0_clear_hqds_on_mec_pipe(), then deassert reset. Avoids releasing pipe reset while HQDs may still be active.
Legacy (non-RS64) path: read CP_MEC_CNTL for the reset mask instead of reusing CP_MEC_RS64_CNTL state. Suggested-by: Manu Rastogi <[email protected]> Signed-off-by: Jesse Zhang <[email protected]> --- drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c | 111 ++++++++++++++++--------- 1 file changed, 71 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c index 65f308b15691..7aa3853f8db7 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c @@ -5362,10 +5362,38 @@ static int gfx_v12_0_reset_kgq(struct amdgpu_ring *ring, return amdgpu_ring_reset_helper_end(ring, timedout_fence); } +/* + * With MEC pipe reset asserted, clear CP_HQD_ACTIVE / CP_HQD_DEQUEUE_REQUEST for + * every queue on (me, pipe). HQDs must be torn down while pipe reset stays + * asserted; only then clear the pipe reset bit. + * Caller must hold adev->srbm_mutex. + */ +static void gfx_v12_0_clear_hqds_on_mec_pipe(struct amdgpu_device *adev, u32 me, + u32 pipe) +{ + unsigned int q; + int j; + + for (q = 0; q < adev->gfx.mec.num_queue_per_pipe; q++) { + soc24_grbm_select(adev, me, pipe, q, 0); + /* Start from a clean HQD dequeue state before forcing HQD inactive. */ + WREG32_SOC15(GC, 0, regCP_HQD_ACTIVE, 0); + if (RREG32_SOC15(GC, 0, regCP_HQD_ACTIVE) & 1) { + WREG32_SOC15(GC, 0, regCP_HQD_DEQUEUE_REQUEST, 1); + for (j = 0; j < adev->usec_timeout; j++) { + if (!(RREG32_SOC15(GC, 0, regCP_HQD_ACTIVE) & 1)) + break; + udelay(1); + } + } + WREG32_SOC15(GC, 0, regCP_HQD_DEQUEUE_REQUEST, 0); + } +} + static int gfx_v12_0_reset_compute_pipe(struct amdgpu_ring *ring) { struct amdgpu_device *adev = ring->adev; - uint32_t reset_pipe = 0, clean_pipe = 0; + uint32_t reset_val, clean_val; int r = 0; if (!gfx_v12_pipe_reset_support(adev)) @@ -5374,74 +5402,77 @@ static int gfx_v12_0_reset_compute_pipe(struct amdgpu_ring *ring) gfx_v12_0_set_safe_mode(adev, 0); mutex_lock(&adev->srbm_mutex); soc24_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0); - - reset_pipe = RREG32_SOC15(GC, 0, regCP_MEC_RS64_CNTL); - clean_pipe = reset_pipe; - if (adev->gfx.rs64_enable) { + reset_val = RREG32_SOC15(GC, 0, regCP_MEC_RS64_CNTL); + clean_val = reset_val; + switch (ring->pipe) { case 0: - reset_pipe = REG_SET_FIELD(reset_pipe, CP_MEC_RS64_CNTL, - MEC_PIPE0_RESET, 1); - clean_pipe = REG_SET_FIELD(clean_pipe, CP_MEC_RS64_CNTL, - MEC_PIPE0_RESET, 0); + reset_val = REG_SET_FIELD(reset_val, CP_MEC_RS64_CNTL, + MEC_PIPE0_RESET, 1); + clean_val = REG_SET_FIELD(clean_val, CP_MEC_RS64_CNTL, + MEC_PIPE0_RESET, 0); break; case 1: - reset_pipe = REG_SET_FIELD(reset_pipe, CP_MEC_RS64_CNTL, - MEC_PIPE1_RESET, 1); - clean_pipe = REG_SET_FIELD(clean_pipe, CP_MEC_RS64_CNTL, - MEC_PIPE1_RESET, 0); + reset_val = REG_SET_FIELD(reset_val, CP_MEC_RS64_CNTL, + MEC_PIPE1_RESET, 1); + clean_val = REG_SET_FIELD(clean_val, CP_MEC_RS64_CNTL, + MEC_PIPE1_RESET, 0); break; case 2: - reset_pipe = REG_SET_FIELD(reset_pipe, CP_MEC_RS64_CNTL, - MEC_PIPE2_RESET, 1); - clean_pipe = REG_SET_FIELD(clean_pipe, CP_MEC_RS64_CNTL, - MEC_PIPE2_RESET, 0); + reset_val = REG_SET_FIELD(reset_val, CP_MEC_RS64_CNTL, + MEC_PIPE2_RESET, 1); + clean_val = REG_SET_FIELD(clean_val, CP_MEC_RS64_CNTL, + MEC_PIPE2_RESET, 0); break; case 3: - reset_pipe = REG_SET_FIELD(reset_pipe, CP_MEC_RS64_CNTL, - MEC_PIPE3_RESET, 1); - clean_pipe = REG_SET_FIELD(clean_pipe, CP_MEC_RS64_CNTL, - MEC_PIPE3_RESET, 0); + reset_val = REG_SET_FIELD(reset_val, CP_MEC_RS64_CNTL, + MEC_PIPE3_RESET, 1); + clean_val = REG_SET_FIELD(clean_val, CP_MEC_RS64_CNTL, + MEC_PIPE3_RESET, 0); break; default: break; } - WREG32_SOC15(GC, 0, regCP_MEC_RS64_CNTL, reset_pipe); - WREG32_SOC15(GC, 0, regCP_MEC_RS64_CNTL, clean_pipe); + WREG32_SOC15(GC, 0, regCP_MEC_RS64_CNTL, reset_val); + gfx_v12_0_clear_hqds_on_mec_pipe(adev, ring->me, ring->pipe); + soc24_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0); + WREG32_SOC15(GC, 0, regCP_MEC_RS64_CNTL, clean_val); r = (RREG32_SOC15(GC, 0, regCP_MEC_RS64_INSTR_PNTR) << 2) - RS64_FW_UC_START_ADDR_LO; } else { + reset_val = RREG32_SOC15(GC, 0, regCP_MEC_CNTL); + clean_val = reset_val; + switch (ring->pipe) { case 0: - reset_pipe = REG_SET_FIELD(reset_pipe, CP_MEC_CNTL, - MEC_ME1_PIPE0_RESET, 1); - clean_pipe = REG_SET_FIELD(clean_pipe, CP_MEC_CNTL, - MEC_ME1_PIPE0_RESET, 0); + reset_val = REG_SET_FIELD(reset_val, CP_MEC_CNTL, + MEC_ME1_PIPE0_RESET, 1); + clean_val = REG_SET_FIELD(clean_val, CP_MEC_CNTL, + MEC_ME1_PIPE0_RESET, 0); break; case 1: - reset_pipe = REG_SET_FIELD(reset_pipe, CP_MEC_CNTL, - MEC_ME1_PIPE1_RESET, 1); - clean_pipe = REG_SET_FIELD(clean_pipe, CP_MEC_CNTL, - MEC_ME1_PIPE1_RESET, 0); + reset_val = REG_SET_FIELD(reset_val, CP_MEC_CNTL, + MEC_ME1_PIPE1_RESET, 1); + clean_val = REG_SET_FIELD(clean_val, CP_MEC_CNTL, + MEC_ME1_PIPE1_RESET, 0); break; default: - break; + break; } - WREG32_SOC15(GC, 0, regCP_MEC_CNTL, reset_pipe); - WREG32_SOC15(GC, 0, regCP_MEC_CNTL, clean_pipe); - /* Doesn't find the F32 MEC instruction pointer register, and suppose - * the driver won't run into the F32 mode. - */ + + WREG32_SOC15(GC, 0, regCP_MEC_CNTL, reset_val); + gfx_v12_0_clear_hqds_on_mec_pipe(adev, ring->me, ring->pipe); + soc24_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0); + WREG32_SOC15(GC, 0, regCP_MEC_CNTL, clean_val); } soc24_grbm_select(adev, 0, 0, 0, 0); mutex_unlock(&adev->srbm_mutex); gfx_v12_0_unset_safe_mode(adev, 0); - dev_info(adev->dev, "The ring %s pipe resets: %s\n", ring->name, - r == 0 ? "successfully" : "failed"); - /* Need the ring test to verify the pipe reset result.*/ + dev_dbg(adev->dev, "The ring %s pipe resets to MEC FW start PC: %s\n", ring->name, + r == 0 ? "successfully" : "failed"); return 0; } -- 2.49.0
