aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMonk Liu <Monk.Liu@amd.com>2017-06-06 05:25:13 -0400
committerAlex Deucher <alexander.deucher@amd.com>2017-07-14 11:06:10 -0400
commit8fdf074f1840eae838bbccbec37d0a1504ee432b (patch)
tree7bfca536bc87c4ae0e8ad6129f95bc72dd6bef9a
parentbdb8cd10b99d55d35b869fbf5cd6df9420b9bd85 (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.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h2
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 */
746int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job) 746int 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,
222int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, 222int 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);
225int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job); 225int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, bool need_pipe_sync);
226void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vmhub, 226void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vmhub,
227 unsigned vmid); 227 unsigned vmid);
228void amdgpu_vm_reset_all_ids(struct amdgpu_device *adev); 228void amdgpu_vm_reset_all_ids(struct amdgpu_device *adev);