drm/amdgpu: set completion status as preempted for the resubmission
authorJiadong Zhu <Jiadong.Zhu@amd.com>
Wed, 26 Jul 2023 07:21:48 +0000 (15:21 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 27 Jul 2023 19:04:19 +0000 (15:04 -0400)
The driver's CSA buffer is shared by all the ibs. When the high priority ib
is submitted after the preempted ib, CP overrides the ib_completion_status
as completed in the csa buffer. After that the preempted ib is resubmitted,
CP would clear some locals stored for ib resume when reading the completed
status, which causes gpu hang in some cases.

Always set status as preempted for those resubmitted ib instead of reading
everything from the CSA buffer.

Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2535
Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2717
Signed-off-by: Jiadong Zhu <Jiadong.Zhu@amd.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.h
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c

index b22d4fb2a8470e457ba5f0db4a9dcda352865716..d3186b570b82e352c3574a8eac1e86dd603be38a 100644 (file)
@@ -56,6 +56,15 @@ enum amdgpu_ring_mux_offset_type {
        AMDGPU_MUX_OFFSET_TYPE_CE,
 };
 
+enum ib_complete_status {
+       /* IB not started/reset value, default value. */
+       IB_COMPLETION_STATUS_DEFAULT = 0,
+       /* IB preempted, started but not completed. */
+       IB_COMPLETION_STATUS_PREEMPTED = 1,
+       /* IB completed. */
+       IB_COMPLETION_STATUS_COMPLETED = 2,
+};
+
 struct amdgpu_ring_mux {
        struct amdgpu_ring      *real_ring;
 
index 0a74116b3142f145822b12a0b808840895b2e0fb..458faf657042e3d6a2b8af49b508db2867bf3295 100644 (file)
@@ -5226,6 +5226,9 @@ static void gfx_v9_0_ring_patch_de_meta(struct amdgpu_ring *ring,
                de_payload_cpu_addr = adev->virt.csa_cpu_addr + payload_offset;
        }
 
+       ((struct v9_de_ib_state *)de_payload_cpu_addr)->ib_completion_status =
+               IB_COMPLETION_STATUS_PREEMPTED;
+
        if (offset + (payload_size >> 2) <= ring->buf_mask + 1) {
                memcpy((void *)&ring->ring[offset], de_payload_cpu_addr, payload_size);
        } else {