Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amdgpu: add pipeline sync while vmid switch in same ctx

Since vmid-mgr supports vmid sharing in one vm, the same ctx could
get different vmids for two emits without vm flush, vm_flush could
be done in another ring.

Signed-off-by: Chunming Zhou <David1.Zhou@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Chunming Zhou and committed by
Alex Deucher
2ba272d7 fdff8cfa

+13 -6
+3 -1
drivers/gpu/drm/amd/amdgpu/amdgpu.h
··· 799 799 unsigned cond_exe_offs; 800 800 u64 cond_exe_gpu_addr; 801 801 volatile u32 *cond_exe_cpu_addr; 802 + int vmid; 802 803 }; 803 804 804 805 /* ··· 937 936 unsigned vm_id, uint64_t pd_addr, 938 937 uint32_t gds_base, uint32_t gds_size, 939 938 uint32_t gws_base, uint32_t gws_size, 940 - uint32_t oa_base, uint32_t oa_size); 939 + uint32_t oa_base, uint32_t oa_size, 940 + bool vmid_switch); 941 941 void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vm_id); 942 942 uint64_t amdgpu_vm_map_gart(const dma_addr_t *pages_addr, uint64_t addr); 943 943 int amdgpu_vm_update_page_directory(struct amdgpu_device *adev,
+7 -2
drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
··· 122 122 bool skip_preamble, need_ctx_switch; 123 123 unsigned patch_offset = ~0; 124 124 struct amdgpu_vm *vm; 125 + int vmid = 0, old_vmid = ring->vmid; 125 126 struct fence *hwf; 126 127 uint64_t ctx; 127 128 ··· 136 135 if (job) { 137 136 vm = job->vm; 138 137 ctx = job->ctx; 138 + vmid = job->vm_id; 139 139 } else { 140 140 vm = NULL; 141 141 ctx = 0; 142 + vmid = 0; 142 143 } 143 144 144 145 if (!ring->ready) { ··· 166 163 r = amdgpu_vm_flush(ring, job->vm_id, job->vm_pd_addr, 167 164 job->gds_base, job->gds_size, 168 165 job->gws_base, job->gws_size, 169 - job->oa_base, job->oa_size); 166 + job->oa_base, job->oa_size, 167 + (ring->current_ctx == ctx) && (old_vmid != vmid)); 170 168 if (r) { 171 169 amdgpu_ring_undo(ring); 172 170 return r; ··· 184 180 need_ctx_switch = ring->current_ctx != ctx; 185 181 for (i = 0; i < num_ibs; ++i) { 186 182 ib = &ibs[i]; 187 - 188 183 /* drop preamble IBs if we don't have a context switch */ 189 184 if ((ib->flags & AMDGPU_IB_FLAG_PREAMBLE) && skip_preamble) 190 185 continue; ··· 191 188 amdgpu_ring_emit_ib(ring, ib, job ? job->vm_id : 0, 192 189 need_ctx_switch); 193 190 need_ctx_switch = false; 191 + ring->vmid = vmid; 194 192 } 195 193 196 194 if (ring->funcs->emit_hdp_invalidate) ··· 202 198 dev_err(adev->dev, "failed to emit fence (%d)\n", r); 203 199 if (job && job->vm_id) 204 200 amdgpu_vm_reset_id(adev, job->vm_id); 201 + ring->vmid = old_vmid; 205 202 amdgpu_ring_undo(ring); 206 203 return r; 207 204 }
+3 -3
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
··· 298 298 unsigned vm_id, uint64_t pd_addr, 299 299 uint32_t gds_base, uint32_t gds_size, 300 300 uint32_t gws_base, uint32_t gws_size, 301 - uint32_t oa_base, uint32_t oa_size) 301 + uint32_t oa_base, uint32_t oa_size, 302 + bool vmid_switch) 302 303 { 303 304 struct amdgpu_device *adev = ring->adev; 304 305 struct amdgpu_vm_id *id = &adev->vm_manager.ids[vm_id]; ··· 313 312 int r; 314 313 315 314 if (ring->funcs->emit_pipeline_sync && ( 316 - pd_addr != AMDGPU_VM_NO_FLUSH || gds_switch_needed || 317 - ring->type == AMDGPU_RING_TYPE_COMPUTE)) 315 + pd_addr != AMDGPU_VM_NO_FLUSH || gds_switch_needed || vmid_switch)) 318 316 amdgpu_ring_emit_pipeline_sync(ring); 319 317 320 318 if (ring->funcs->emit_vm_flush &&