drm/amdgpu: update the PASID mapping only on demand
authorChristian König <christian.koenig@amd.com>
Mon, 5 Feb 2018 16:38:01 +0000 (17:38 +0100)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 19 Feb 2018 19:20:18 +0000 (14:20 -0500)
Updating the PASID is rather heavyweight and shouldn't be done all the
time.

Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c

index 563e74755aabf3a630e880e3ed395b1c085072ee..a1c78f90eadffe6b719b822e0ed19c49bd0b4aa8 100644 (file)
@@ -607,6 +607,7 @@ void amdgpu_vmid_mgr_fini(struct amdgpu_device *adev)
                        amdgpu_sync_free(&id->active);
                        dma_fence_put(id->flushed_updates);
                        dma_fence_put(id->last_flush);
+                       dma_fence_put(id->pasid_mapping);
                }
        }
 }
index 20d4eca6cd6ae5652555691845b53a422a2dcb97..7625419f0fc25d38b63e320df058560e527057cd 100644 (file)
@@ -57,6 +57,9 @@ struct amdgpu_vmid {
        uint32_t                gws_size;
        uint32_t                oa_base;
        uint32_t                oa_size;
+
+       unsigned                pasid;
+       struct dma_fence        *pasid_mapping;
 };
 
 struct amdgpu_vmid_mgr {
index afa16a862eaabb128472770dc5886e63bcda5894..0b237e027cab2be5e539c15588ed53e27c01e572 100644 (file)
@@ -591,14 +591,24 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, bool need_
                id->oa_base != job->oa_base ||
                id->oa_size != job->oa_size);
        bool vm_flush_needed = job->vm_needs_flush;
+       bool pasid_mapping_needed = id->pasid != job->pasid ||
+               !id->pasid_mapping ||
+               !dma_fence_is_signaled(id->pasid_mapping);
+       struct dma_fence *fence = NULL;
        unsigned patch_offset = 0;
        int r;
 
        if (amdgpu_vmid_had_gpu_reset(adev, id)) {
                gds_switch_needed = true;
                vm_flush_needed = true;
+               pasid_mapping_needed = true;
        }
 
+       gds_switch_needed &= !!ring->funcs->emit_gds_switch;
+       vm_flush_needed &= !!ring->funcs->emit_vm_flush;
+       pasid_mapping_needed &= adev->gmc.gmc_funcs->emit_pasid_mapping &&
+               ring->funcs->emit_wreg;
+
        if (!vm_flush_needed && !gds_switch_needed && !need_pipe_sync)
                return 0;
 
@@ -608,27 +618,36 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, bool need_
        if (need_pipe_sync)
                amdgpu_ring_emit_pipeline_sync(ring);
 
-       if (ring->funcs->emit_vm_flush && vm_flush_needed) {
-               struct dma_fence *fence;
-
+       if (vm_flush_needed) {
                trace_amdgpu_vm_flush(ring, job->vmid, job->vm_pd_addr);
                amdgpu_ring_emit_vm_flush(ring, job->vmid, job->vm_pd_addr);
-               if (adev->gmc.gmc_funcs->emit_pasid_mapping &&
-                   ring->funcs->emit_wreg)
-                       amdgpu_gmc_emit_pasid_mapping(ring, job->vmid,
-                                                     job->pasid);
+       }
 
+       if (pasid_mapping_needed)
+               amdgpu_gmc_emit_pasid_mapping(ring, job->vmid, job->pasid);
+
+       if (vm_flush_needed || pasid_mapping_needed) {
                r = amdgpu_fence_emit(ring, &fence);
                if (r)
                        return r;
+       }
 
+       if (vm_flush_needed) {
                mutex_lock(&id_mgr->lock);
                dma_fence_put(id->last_flush);
-               id->last_flush = fence;
-               id->current_gpu_reset_count = atomic_read(&adev->gpu_reset_counter);
+               id->last_flush = dma_fence_get(fence);
+               id->current_gpu_reset_count =
+                       atomic_read(&adev->gpu_reset_counter);
                mutex_unlock(&id_mgr->lock);
        }
 
+       if (pasid_mapping_needed) {
+               id->pasid = job->pasid;
+               dma_fence_put(id->pasid_mapping);
+               id->pasid_mapping = dma_fence_get(fence);
+       }
+       dma_fence_put(fence);
+
        if (ring->funcs->emit_gds_switch && gds_switch_needed) {
                id->gds_base = job->gds_base;
                id->gds_size = job->gds_size;