COND_EXEC tells the CP to discard the dwords following it
when its condition is zero (false).

This is useful for GPU recovery because it can help reduce
collateral damage during GFX IP block soft reset, meaning
that it reduces the likelyhood that we fail some jobs which
are not guilty of the hang as the IP block soft reset
mechanism clears the condition before doing the reset.

Note that this packet is only 4 DW on GFX6 (as opposed
to GFX7 and newer where it's 5 DW).

Signed-off-by: Timur Kristóf <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c 
b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
index 3e0cd46cd091..7f7b81c3919a 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
@@ -2423,6 +2423,24 @@ static void gfx_v6_0_ring_emit_vm_flush(struct 
amdgpu_ring *ring,
        amdgpu_ring_write(ring, 0x20); /* poll interval */
 }
 
+static unsigned int gfx_v6_0_ring_emit_init_cond_exec(struct amdgpu_ring *ring,
+                                                 uint64_t gpu_addr)
+{
+       unsigned int ret;
+
+       /*
+        * Discard following DWs after this packet when gpu_addr==0
+        * The packet is only 4 DW on GFX6 (as opposed to GFX7+).
+        */
+       amdgpu_ring_write(ring, PACKET3(PACKET3_COND_EXEC, 2));
+       amdgpu_ring_write(ring, lower_32_bits(gpu_addr));
+       amdgpu_ring_write(ring, upper_32_bits(gpu_addr));
+       ret = ring->wptr & ring->buf_mask;
+       /* patch dummy value later */
+       amdgpu_ring_write(ring, 0);
+       return ret;
+}
+
 static void gfx_v6_0_ring_emit_wreg(struct amdgpu_ring *ring,
                                    uint32_t reg, uint32_t val)
 {
@@ -3579,6 +3597,8 @@ static const struct amdgpu_ring_funcs 
gfx_v6_0_ring_funcs_gfx = {
        .get_wptr = gfx_v6_0_ring_get_wptr,
        .set_wptr = gfx_v6_0_ring_set_wptr_gfx,
        .emit_frame_size =
+               4 + /* gfx_v6_0_ring_emit_init_cond_exec (from 
amdgpu_ib_schedule) */
+               4 + /* gfx_v6_0_ring_emit_init_cond_exec (from amdgpu_vm_flush) 
*/
                5 + 5 + /* hdp flush / invalidate */
                14 + 14 + 14 + /* gfx_v6_0_ring_emit_fence x3 for user fence, 
vm fence */
                7 + /* gfx_v6_0_ring_emit_pipeline_sync */
@@ -3596,6 +3616,7 @@ static const struct amdgpu_ring_funcs 
gfx_v6_0_ring_funcs_gfx = {
        .insert_nop = amdgpu_ring_insert_nop,
        .emit_switch_buffer = gfx_v6_0_ring_emit_sb,
        .emit_cntxcntl = gfx_v6_ring_emit_cntxcntl,
+       .init_cond_exec = gfx_v6_0_ring_emit_init_cond_exec,
        .emit_wreg = gfx_v6_0_ring_emit_wreg,
        .emit_mem_sync = gfx_v6_0_emit_mem_sync,
 };
@@ -3608,6 +3629,8 @@ static const struct amdgpu_ring_funcs 
gfx_v6_0_ring_funcs_compute = {
        .get_wptr = gfx_v6_0_ring_get_wptr,
        .set_wptr = gfx_v6_0_ring_set_wptr_compute,
        .emit_frame_size =
+               4 + /* gfx_v6_0_ring_emit_init_cond_exec (from 
amdgpu_ib_schedule) */
+               4 + /* gfx_v6_0_ring_emit_init_cond_exec (from amdgpu_vm_flush) 
*/
                5 + 5 + /* hdp flush / invalidate */
                7 + /* gfx_v6_0_ring_emit_pipeline_sync */
                SI_FLUSH_GPU_TLB_NUM_WREG * 5 + 7 + 2 + /* 
gfx_v6_0_ring_emit_vm_flush */
@@ -3623,6 +3646,7 @@ static const struct amdgpu_ring_funcs 
gfx_v6_0_ring_funcs_compute = {
        .test_ib = gfx_v6_0_ring_test_ib,
        .insert_nop = amdgpu_ring_insert_nop,
        .emit_switch_buffer = gfx_v6_0_ring_emit_sb,
+       .init_cond_exec = gfx_v6_0_ring_emit_init_cond_exec,
        .emit_wreg = gfx_v6_0_ring_emit_wreg,
        .emit_mem_sync = gfx_v6_0_emit_mem_sync,
 };
-- 
2.55.0

Reply via email to