If when we backup the ring contents for reemit before a ring reset, we skip jobs associated with the bad context, however, we need to make sure the fences are reemited as unprocessed submissions may depend on them.
Signed-off-by: Alex Deucher <[email protected]> --- drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c | 29 +++++++++++++++++++---- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 8 ++++++- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c index 334ddd6e48c06..9dfae9532c70e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c @@ -116,8 +116,10 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct amdgpu_fence *af, &ring->fence_drv.lock, adev->fence_context + ring->idx, seq); + amdgpu_fence_save_fence_wptr_start(af); amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr, seq, flags | AMDGPU_FENCE_FLAG_INT); + amdgpu_fence_save_fence_wptr_end(af); amdgpu_fence_save_wptr(af); pm_runtime_get_noresume(adev_to_drm(adev)->dev); ptr = &ring->fence_drv.fences[seq & ring->fence_drv.num_fences_mask]; @@ -743,10 +745,6 @@ void amdgpu_fence_driver_guilty_force_completion(struct amdgpu_fence *af) /* if we've already reemitted once then just cancel everything */ amdgpu_fence_driver_force_completion(af->ring); af->ring->ring_backup_entries_to_copy = 0; - } else { - /* signal the guilty fence */ - amdgpu_fence_write(ring, (u32)af->base.seqno); - amdgpu_fence_process(ring); } } @@ -755,6 +753,18 @@ void amdgpu_fence_save_wptr(struct amdgpu_fence *af) af->wptr = af->ring->wptr; } +void amdgpu_fence_save_fence_wptr_start(struct amdgpu_fence *af) +{ + af->fence_wptr_start[af->fence_count] = af->ring->wptr; +} + +void amdgpu_fence_save_fence_wptr_end(struct amdgpu_fence *af) +{ + af->fence_wptr_end[af->fence_count] = af->ring->wptr; + if (af->fence_count < 2) + af->fence_count++; +} + static void amdgpu_ring_backup_unprocessed_command(struct amdgpu_ring *ring, u64 start_wptr, u32 end_wptr) { @@ -775,6 +785,7 @@ void amdgpu_ring_backup_unprocessed_commands(struct amdgpu_ring *ring, struct amdgpu_fence *fence; u64 wptr; u32 seq, last_seq; + int i; last_seq = amdgpu_fence_read(ring) & ring->fence_drv.num_fences_mask; seq = ring->fence_drv.sync_seq & ring->fence_drv.num_fences_mask; @@ -796,9 +807,17 @@ void amdgpu_ring_backup_unprocessed_commands(struct amdgpu_ring *ring, * just save the content from other contexts. */ if (!fence->reemitted && - (!guilty_fence || (fence->context != guilty_fence->context))) + (!guilty_fence || (fence->context != guilty_fence->context))) { amdgpu_ring_backup_unprocessed_command(ring, wptr, fence->wptr); + } else if (!fence->reemitted) { + /* always save the fences */ + for (i = 0; i < fence->fence_count; i++) { + amdgpu_ring_backup_unprocessed_command(ring, + fence->fence_wptr_start[i], + fence->fence_wptr_end[i]); + } + } wptr = fence->wptr; fence->reemitted++; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h index f93bf83f7f5e4..51b80c18ded9c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h @@ -151,12 +151,16 @@ struct amdgpu_fence { struct amdgpu_ring *ring; ktime_t start_timestamp; - /* wptr for the fence for resets */ + /* wptr for the total submission for resets */ u64 wptr; /* fence context for resets */ u64 context; /* has this fence been reemitted */ unsigned int reemitted; + /* wptrs for the fences for the submission */ + u64 fence_wptr_start[2]; + u64 fence_wptr_end[2]; + unsigned int fence_count; }; extern const struct drm_sched_backend_ops amdgpu_sched_ops; @@ -165,6 +169,8 @@ void amdgpu_fence_driver_set_error(struct amdgpu_ring *ring, int error); void amdgpu_fence_driver_force_completion(struct amdgpu_ring *ring); void amdgpu_fence_driver_guilty_force_completion(struct amdgpu_fence *af); void amdgpu_fence_save_wptr(struct amdgpu_fence *af); +void amdgpu_fence_save_fence_wptr_start(struct amdgpu_fence *af); +void amdgpu_fence_save_fence_wptr_end(struct amdgpu_fence *af); int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring); int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring, -- 2.51.1
