Skip to content

Commit

Permalink
drm/amdgpu/gfx11: Implement the GFX11 KCQ pipe reset
Browse files Browse the repository at this point in the history
Implement the GFX11 compute pipe reset. As the GFX11 CPFW
still hasn't fully supported pipe reset yet, therefore
disable the KCQ pipe reset temporarily.

Signed-off-by: Prike Liang <Prike.Liang@amd.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
  • Loading branch information
Prike Liang authored and Alex Deucher committed Apr 7, 2025
1 parent dcc8e14 commit d69248c
Showing 1 changed file with 134 additions and 2 deletions.
136 changes: 134 additions & 2 deletions drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
Original file line number Diff line number Diff line change
Expand Up @@ -6703,6 +6703,136 @@ static int gfx_v11_0_reset_kgq(struct amdgpu_ring *ring, unsigned int vmid)
return amdgpu_ring_test_ring(ring);
}

static int gfx_v11_0_reset_compute_pipe(struct amdgpu_ring *ring)
{

struct amdgpu_device *adev = ring->adev;
uint32_t reset_pipe = 0, clean_pipe = 0;
int r;

if (!gfx_v11_pipe_reset_support(adev))
return -EOPNOTSUPP;

gfx_v11_0_set_safe_mode(adev, 0);
mutex_lock(&adev->srbm_mutex);
soc21_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) {

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);
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);
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);
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);
break;
default:
break;
}
WREG32_SOC15(GC, 0, regCP_MEC_RS64_CNTL, reset_pipe);
WREG32_SOC15(GC, 0, regCP_MEC_RS64_CNTL, clean_pipe);
r = (RREG32_SOC15(GC, 0, regCP_MEC_RS64_INSTR_PNTR) << 2) -
RS64_FW_UC_START_ADDR_LO;
} else {
if (ring->me == 1) {
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);
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);
break;
case 2:
reset_pipe = REG_SET_FIELD(reset_pipe, CP_MEC_CNTL,
MEC_ME1_PIPE2_RESET, 1);
clean_pipe = REG_SET_FIELD(clean_pipe, CP_MEC_CNTL,
MEC_ME1_PIPE2_RESET, 0);
break;
case 3:
reset_pipe = REG_SET_FIELD(reset_pipe, CP_MEC_CNTL,
MEC_ME1_PIPE3_RESET, 1);
clean_pipe = REG_SET_FIELD(clean_pipe, CP_MEC_CNTL,
MEC_ME1_PIPE3_RESET, 0);
break;
default:
break;
}
/* mec1 fw pc: CP_MEC1_INSTR_PNTR */
} else {
switch (ring->pipe) {
case 0:
reset_pipe = REG_SET_FIELD(reset_pipe, CP_MEC_CNTL,
MEC_ME2_PIPE0_RESET, 1);
clean_pipe = REG_SET_FIELD(clean_pipe, CP_MEC_CNTL,
MEC_ME2_PIPE0_RESET, 0);
break;
case 1:
reset_pipe = REG_SET_FIELD(reset_pipe, CP_MEC_CNTL,
MEC_ME2_PIPE1_RESET, 1);
clean_pipe = REG_SET_FIELD(clean_pipe, CP_MEC_CNTL,
MEC_ME2_PIPE1_RESET, 0);
break;
case 2:
reset_pipe = REG_SET_FIELD(reset_pipe, CP_MEC_CNTL,
MEC_ME2_PIPE2_RESET, 1);
clean_pipe = REG_SET_FIELD(clean_pipe, CP_MEC_CNTL,
MEC_ME2_PIPE2_RESET, 0);
break;
case 3:
reset_pipe = REG_SET_FIELD(reset_pipe, CP_MEC_CNTL,
MEC_ME2_PIPE3_RESET, 1);
clean_pipe = REG_SET_FIELD(clean_pipe, CP_MEC_CNTL,
MEC_ME2_PIPE3_RESET, 0);
break;
default:
break;
}
/* mec2 fw pc: CP:CP_MEC2_INSTR_PNTR */
}
WREG32_SOC15(GC, 0, regCP_MEC_CNTL, reset_pipe);
WREG32_SOC15(GC, 0, regCP_MEC_CNTL, clean_pipe);
r = RREG32(SOC15_REG_OFFSET(GC, 0, regCP_MEC1_INSTR_PNTR));
}

soc21_grbm_select(adev, 0, 0, 0, 0);
mutex_unlock(&adev->srbm_mutex);
gfx_v11_0_unset_safe_mode(adev, 0);

dev_info(adev->dev, "The ring %s pipe resets to MEC FW start PC: %s\n", ring->name,
r == 0 ? "successfully" : "failed");
/*FIXME:Sometimes driver can't cache the MEC firmware start PC correctly, so the pipe
* reset status relies on the compute ring test result.
*/
return 0;
}

static int gfx_v11_0_reset_kcq(struct amdgpu_ring *ring, unsigned int vmid)
{
struct amdgpu_device *adev = ring->adev;
Expand All @@ -6713,8 +6843,10 @@ static int gfx_v11_0_reset_kcq(struct amdgpu_ring *ring, unsigned int vmid)

r = amdgpu_mes_reset_legacy_queue(ring->adev, ring, vmid, true);
if (r) {
dev_err(adev->dev, "reset via MMIO failed %d\n", r);
return r;
dev_warn(adev->dev, "fail(%d) to reset kcq and try pipe reset\n", r);
r = gfx_v11_0_reset_compute_pipe(ring);
if (r)
return r;
}

r = gfx_v11_0_kcq_init_queue(ring, true);
Expand Down

0 comments on commit d69248c

Please sign in to comment.