diff options
author | Monk Liu <Monk.Liu@amd.com> | 2017-06-06 05:25:13 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2017-07-14 11:06:10 -0400 |
commit | 8fdf074f1840eae838bbccbec37d0a1504ee432b (patch) | |
tree | 7bfca536bc87c4ae0e8ad6129f95bc72dd6bef9a | |
parent | bdb8cd10b99d55d35b869fbf5cd6df9420b9bd85 (diff) |
drm/amdgpu:fix world switch hang
for SR-IOV, we must keep the pipeline-sync in the protection
of COND_EXEC, otherwise the command consumed by CPG is not
consistent when world switch triggerd, e.g.:
world switch hit and the IB frame is skipped so the fence
won't signal, thus CP will jump to the next DMAframe's pipeline-sync
command, and it will make CP hang foever.
after pipelin-sync moved into COND_EXEC the consistency can be
guaranteed
Signed-off-by: Monk Liu <Monk.Liu@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 2 |
3 files changed, 9 insertions, 5 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c index 1b30d2ab9c51..659997bfff30 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | |||
@@ -130,6 +130,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, | |||
130 | 130 | ||
131 | unsigned i; | 131 | unsigned i; |
132 | int r = 0; | 132 | int r = 0; |
133 | bool need_pipe_sync = false; | ||
133 | 134 | ||
134 | if (num_ibs == 0) | 135 | if (num_ibs == 0) |
135 | return -EINVAL; | 136 | return -EINVAL; |
@@ -165,7 +166,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, | |||
165 | if (ring->funcs->emit_pipeline_sync && job && | 166 | if (ring->funcs->emit_pipeline_sync && job && |
166 | ((tmp = amdgpu_sync_get_fence(&job->sched_sync)) || | 167 | ((tmp = amdgpu_sync_get_fence(&job->sched_sync)) || |
167 | amdgpu_vm_need_pipeline_sync(ring, job))) { | 168 | amdgpu_vm_need_pipeline_sync(ring, job))) { |
168 | amdgpu_ring_emit_pipeline_sync(ring); | 169 | need_pipe_sync = true; |
169 | dma_fence_put(tmp); | 170 | dma_fence_put(tmp); |
170 | } | 171 | } |
171 | 172 | ||
@@ -173,7 +174,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, | |||
173 | ring->funcs->insert_start(ring); | 174 | ring->funcs->insert_start(ring); |
174 | 175 | ||
175 | if (job) { | 176 | if (job) { |
176 | r = amdgpu_vm_flush(ring, job); | 177 | r = amdgpu_vm_flush(ring, job, need_pipe_sync); |
177 | if (r) { | 178 | if (r) { |
178 | amdgpu_ring_undo(ring); | 179 | amdgpu_ring_undo(ring); |
179 | return r; | 180 | return r; |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index cda9e5d8b831..30c4322ddce7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | |||
@@ -743,7 +743,7 @@ static bool amdgpu_vm_is_large_bar(struct amdgpu_device *adev) | |||
743 | * | 743 | * |
744 | * Emit a VM flush when it is necessary. | 744 | * Emit a VM flush when it is necessary. |
745 | */ | 745 | */ |
746 | int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job) | 746 | int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, bool need_pipe_sync) |
747 | { | 747 | { |
748 | struct amdgpu_device *adev = ring->adev; | 748 | struct amdgpu_device *adev = ring->adev; |
749 | unsigned vmhub = ring->funcs->vmhub; | 749 | unsigned vmhub = ring->funcs->vmhub; |
@@ -765,12 +765,15 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job) | |||
765 | vm_flush_needed = true; | 765 | vm_flush_needed = true; |
766 | } | 766 | } |
767 | 767 | ||
768 | if (!vm_flush_needed && !gds_switch_needed) | 768 | if (!vm_flush_needed && !gds_switch_needed && !need_pipe_sync) |
769 | return 0; | 769 | return 0; |
770 | 770 | ||
771 | if (ring->funcs->init_cond_exec) | 771 | if (ring->funcs->init_cond_exec) |
772 | patch_offset = amdgpu_ring_init_cond_exec(ring); | 772 | patch_offset = amdgpu_ring_init_cond_exec(ring); |
773 | 773 | ||
774 | if (need_pipe_sync) | ||
775 | amdgpu_ring_emit_pipeline_sync(ring); | ||
776 | |||
774 | if (ring->funcs->emit_vm_flush && vm_flush_needed) { | 777 | if (ring->funcs->emit_vm_flush && vm_flush_needed) { |
775 | struct dma_fence *fence; | 778 | struct dma_fence *fence; |
776 | 779 | ||
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h index 936f158bc5ec..3441ec58c823 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | |||
@@ -222,7 +222,7 @@ int amdgpu_vm_alloc_pts(struct amdgpu_device *adev, | |||
222 | int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, | 222 | int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, |
223 | struct amdgpu_sync *sync, struct dma_fence *fence, | 223 | struct amdgpu_sync *sync, struct dma_fence *fence, |
224 | struct amdgpu_job *job); | 224 | struct amdgpu_job *job); |
225 | int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job); | 225 | int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, bool need_pipe_sync); |
226 | void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vmhub, | 226 | void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vmhub, |
227 | unsigned vmid); | 227 | unsigned vmid); |
228 | void amdgpu_vm_reset_all_ids(struct amdgpu_device *adev); | 228 | void amdgpu_vm_reset_all_ids(struct amdgpu_device *adev); |