On 2025. december 19., péntek 12:22:00 középső államokbeli zónaidő Alex Deucher wrote: > GFX ring resets work differently on pre-GFX10 hardware since > there is no MQD managed by the scheduler. > For ring reset, you need issue the reset via CP_VMID_RESET > via KIQ or MMIO and submit the following to the gfx ring to > complete the reset: > 1. EOP packet with EXEC bit set > 2. WAIT_REG_MEM to wait for the fence > 3. Clear CP_VMID_RESET to 0 > 4. EVENT_WRITE ENABLE_LEGACY_PIPELINE > 5. EOP packet with EXEC bit set > 6. WAIT_REG_MEM to wait for the fence > Once those commands have completed the reset should > be complete and the ring can accept new packets. > > Tested-by: Jiqian Chen <[email protected]> (v1) > Signed-off-by: Alex Deucher <[email protected]>
Hi Alex, Thank you for working on this. For the entire series, Reviewed-by: Timur Kristóf <[email protected]> I can't test it at the moment but can give it a try in January or so. Best regards, Timur > --- > drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 92 ++++++++++++++++++++++++++- > 1 file changed, 89 insertions(+), 3 deletions(-) > > diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c > b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 0d8e797d59b8a..7e9d753f4a808 > 100644 > --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c > +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c > @@ -2411,8 +2411,10 @@ static int gfx_v9_0_sw_init(struct amdgpu_ip_block > *ip_block) amdgpu_get_soft_full_reset_mask(&adev->gfx.gfx_ring[0]); > adev->gfx.compute_supported_reset = > amdgpu_get_soft_full_reset_mask(&adev- >gfx.compute_ring[0]); > - if (!amdgpu_sriov_vf(adev) && !adev->debug_disable_gpu_ring_reset) > + if (!amdgpu_sriov_vf(adev) && !adev->debug_disable_gpu_ring_reset) { > adev->gfx.compute_supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE; > + adev->gfx.gfx_supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE; > + } > > r = amdgpu_gfx_kiq_init(adev, GFX9_MEC_HPD_SIZE, 0); > if (r) { > @@ -7172,6 +7174,91 @@ static void gfx_v9_ring_insert_nop(struct amdgpu_ring > *ring, uint32_t num_nop) amdgpu_ring_insert_nop(ring, num_nop - 1); > } > > +static void gfx_v9_0_ring_emit_wreg_me(struct amdgpu_ring *ring, > + uint32_t reg, > + uint32_t val) > +{ > + uint32_t cmd = 0; > + > + switch (ring->funcs->type) { > + case AMDGPU_RING_TYPE_KIQ: > + cmd = (1 << 16); /* no inc addr */ > + break; > + default: > + cmd = WR_CONFIRM; > + break; > + } > + amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); > + amdgpu_ring_write(ring, cmd); > + amdgpu_ring_write(ring, reg); > + amdgpu_ring_write(ring, 0); > + amdgpu_ring_write(ring, val); > +} > + > +static int gfx_v9_0_reset_kgq(struct amdgpu_ring *ring, > + unsigned int vmid, > + struct amdgpu_fence *timedout_fence) > +{ > + struct amdgpu_device *adev = ring->adev; > + struct amdgpu_kiq *kiq = &adev->gfx.kiq[0]; > + struct amdgpu_ring *kiq_ring = &kiq->ring; > + unsigned long flags; > + u32 tmp; > + int r; > + > + amdgpu_ring_reset_helper_begin(ring, timedout_fence); > + > + spin_lock_irqsave(&kiq->ring_lock, flags); > + > + if (amdgpu_ring_alloc(kiq_ring, 5)) { > + spin_unlock_irqrestore(&kiq->ring_lock, flags); > + return -ENOMEM; > + } > + > + /* send the reset - 5 */ > + tmp = REG_SET_FIELD(0, CP_VMID_RESET, RESET_REQUEST, 1 << vmid); > + gfx_v9_0_ring_emit_wreg(kiq_ring, > + SOC15_REG_OFFSET(GC, 0, mmCP_VMID_RESET), tmp); > + amdgpu_ring_commit(kiq_ring); > + r = amdgpu_ring_test_ring(kiq_ring); > + spin_unlock_irqrestore(&kiq->ring_lock, flags); > + if (r) > + return r; > + > + if (amdgpu_ring_alloc(ring, 8 + 7 + 5 + 2 + 8 + 7)) > + return -ENOMEM; > + /* emit the fence to finish the reset - 8 */ > + ring->trail_seq++; > + gfx_v9_0_ring_emit_fence(ring, ring->trail_fence_gpu_addr, > + ring->trail_seq, AMDGPU_FENCE_FLAG_EXEC); > + /* wait for the fence - 7 */ > + gfx_v9_0_wait_reg_mem(ring, 0, 1, 0, > + lower_32_bits(ring- >trail_fence_gpu_addr), > + upper_32_bits(ring- >trail_fence_gpu_addr), > + ring->trail_seq, 0xffffffff, 4); > + /* clear mmCP_VMID_RESET - 5 */ > + gfx_v9_0_ring_emit_wreg_me(ring, > + SOC15_REG_OFFSET(GC, 0, mmCP_VMID_RESET), 0); > + /* event write ENABLE_LEGACY_PIPELINE - 2 */ > + gfx_v9_0_ring_emit_event_write(ring, ENABLE_LEGACY_PIPELINE, 0); > + /* emit a regular fence - 8 */ > + ring->trail_seq++; > + gfx_v9_0_ring_emit_fence(ring, ring->trail_fence_gpu_addr, > + ring->trail_seq, AMDGPU_FENCE_FLAG_EXEC); > + /* wait for the fence - 7 */ > + gfx_v9_0_wait_reg_mem(ring, 1, 1, 0, > + lower_32_bits(ring- >trail_fence_gpu_addr), > + upper_32_bits(ring- >trail_fence_gpu_addr), > + ring->trail_seq, 0xffffffff, 4); > + amdgpu_ring_commit(ring); > + /* wait for the commands to complete */ > + r = amdgpu_ring_test_ring(ring); > + if (r) > + return r; > + > + return amdgpu_ring_reset_helper_end(ring, timedout_fence); > +} > + > static int gfx_v9_0_reset_kcq(struct amdgpu_ring *ring, > unsigned int vmid, > struct amdgpu_fence *timedout_fence) > @@ -7450,9 +7537,9 @@ static const struct amdgpu_ring_funcs > gfx_v9_0_ring_funcs_gfx = { .emit_wreg = gfx_v9_0_ring_emit_wreg, > .emit_reg_wait = gfx_v9_0_ring_emit_reg_wait, > .emit_reg_write_reg_wait = gfx_v9_0_ring_emit_reg_write_reg_wait, > - .soft_recovery = gfx_v9_0_ring_soft_recovery, > .emit_mem_sync = gfx_v9_0_emit_mem_sync, > .emit_cleaner_shader = gfx_v9_0_ring_emit_cleaner_shader, > + .reset = gfx_v9_0_reset_kgq, > .begin_use = amdgpu_gfx_enforce_isolation_ring_begin_use, > .end_use = amdgpu_gfx_enforce_isolation_ring_end_use, > }; > @@ -7551,7 +7638,6 @@ static const struct amdgpu_ring_funcs > gfx_v9_0_ring_funcs_compute = { .emit_wreg = gfx_v9_0_ring_emit_wreg, > .emit_reg_wait = gfx_v9_0_ring_emit_reg_wait, > .emit_reg_write_reg_wait = gfx_v9_0_ring_emit_reg_write_reg_wait, > - .soft_recovery = gfx_v9_0_ring_soft_recovery, > .emit_mem_sync = gfx_v9_0_emit_mem_sync, > .emit_wave_limit = gfx_v9_0_emit_wave_limit, > .reset = gfx_v9_0_reset_kcq,
