diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 100 |
1 files changed, 61 insertions, 39 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c index 8443cea6821a..7a0b1e50f293 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c @@ -74,9 +74,6 @@ int amdgpu_ib_get(struct amdgpu_device *adev, struct amdgpu_vm *vm, ib->gpu_addr = amdgpu_sa_bo_gpu_addr(ib->sa_bo); } - ib->vm = vm; - ib->vm_id = 0; - return 0; } @@ -89,7 +86,8 @@ int amdgpu_ib_get(struct amdgpu_device *adev, struct amdgpu_vm *vm, * * Free an IB (all asics). */ -void amdgpu_ib_free(struct amdgpu_device *adev, struct amdgpu_ib *ib, struct fence *f) +void amdgpu_ib_free(struct amdgpu_device *adev, struct amdgpu_ib *ib, + struct fence *f) { amdgpu_sa_bo_free(adev, &ib->sa_bo, f); } @@ -117,28 +115,40 @@ void amdgpu_ib_free(struct amdgpu_device *adev, struct amdgpu_ib *ib, struct fen */ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, struct amdgpu_ib *ibs, struct fence *last_vm_update, - struct fence **f) + struct amdgpu_job *job, struct fence **f) { struct amdgpu_device *adev = ring->adev; struct amdgpu_ib *ib = &ibs[0]; - struct amdgpu_ctx *ctx, *old_ctx; + bool skip_preamble, need_ctx_switch; + unsigned patch_offset = ~0; struct amdgpu_vm *vm; + int vmid = 0, old_vmid = ring->vmid; struct fence *hwf; + uint64_t ctx; + unsigned i; int r = 0; if (num_ibs == 0) return -EINVAL; - ctx = ibs->ctx; - vm = ibs->vm; + /* ring tests don't use a job */ + if (job) { + vm = job->vm; + ctx = job->ctx; + vmid = job->vm_id; + } else { + vm = NULL; + ctx = 0; + vmid = 0; + } if (!ring->ready) { dev_err(adev->dev, "couldn't schedule ib\n"); return -EINVAL; } - if (vm && !ibs->vm_id) { + if (vm && !job->vm_id) { dev_err(adev->dev, "VM IB without ID\n"); return -EINVAL; } @@ -149,58 +159,70 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, return r; } + if (ring->type == AMDGPU_RING_TYPE_SDMA && ring->funcs->init_cond_exec) + patch_offset = amdgpu_ring_init_cond_exec(ring); + if (vm) { - /* do context switch */ - amdgpu_vm_flush(ring, ib->vm_id, ib->vm_pd_addr, - ib->gds_base, ib->gds_size, - ib->gws_base, ib->gws_size, - ib->oa_base, ib->oa_size); - - if (ring->funcs->emit_hdp_flush) - amdgpu_ring_emit_hdp_flush(ring); + r = amdgpu_vm_flush(ring, job->vm_id, job->vm_pd_addr, + job->gds_base, job->gds_size, + job->gws_base, job->gws_size, + job->oa_base, job->oa_size, + (ring->current_ctx == ctx) && (old_vmid != vmid)); + if (r) { + amdgpu_ring_undo(ring); + return r; + } } - old_ctx = ring->current_ctx; + if (ring->funcs->emit_hdp_flush) + amdgpu_ring_emit_hdp_flush(ring); + + /* always set cond_exec_polling to CONTINUE */ + *ring->cond_exe_cpu_addr = 1; + + skip_preamble = ring->current_ctx == ctx; + need_ctx_switch = ring->current_ctx != ctx; for (i = 0; i < num_ibs; ++i) { ib = &ibs[i]; + /* drop preamble IBs if we don't have a context switch */ + if ((ib->flags & AMDGPU_IB_FLAG_PREAMBLE) && skip_preamble) + continue; - if (ib->ctx != ctx || ib->vm != vm) { - ring->current_ctx = old_ctx; - if (ib->vm_id) - amdgpu_vm_reset_id(adev, ib->vm_id); - amdgpu_ring_undo(ring); - return -EINVAL; - } - amdgpu_ring_emit_ib(ring, ib); - ring->current_ctx = ctx; + amdgpu_ring_emit_ib(ring, ib, job ? job->vm_id : 0, + need_ctx_switch); + need_ctx_switch = false; + ring->vmid = vmid; } - if (vm) { - if (ring->funcs->emit_hdp_invalidate) - amdgpu_ring_emit_hdp_invalidate(ring); - } + if (ring->funcs->emit_hdp_invalidate) + amdgpu_ring_emit_hdp_invalidate(ring); r = amdgpu_fence_emit(ring, &hwf); if (r) { dev_err(adev->dev, "failed to emit fence (%d)\n", r); - ring->current_ctx = old_ctx; - if (ib->vm_id) - amdgpu_vm_reset_id(adev, ib->vm_id); + if (job && job->vm_id) + amdgpu_vm_reset_id(adev, job->vm_id); + ring->vmid = old_vmid; amdgpu_ring_undo(ring); return r; } /* wrap the last IB with fence */ - if (ib->user) { - uint64_t addr = amdgpu_bo_gpu_offset(ib->user->bo); - addr += ib->user->offset; - amdgpu_ring_emit_fence(ring, addr, ib->sequence, + if (job && job->uf_bo) { + uint64_t addr = amdgpu_bo_gpu_offset(job->uf_bo); + + addr += job->uf_offset; + amdgpu_ring_emit_fence(ring, addr, job->uf_sequence, AMDGPU_FENCE_FLAG_64BIT); } if (f) *f = fence_get(hwf); + if (patch_offset != ~0 && ring->funcs->patch_cond_exec) + amdgpu_ring_patch_cond_exec(ring, patch_offset); + + ring->current_ctx = ctx; amdgpu_ring_commit(ring); return 0; } @@ -315,7 +337,7 @@ static int amdgpu_debugfs_sa_info(struct seq_file *m, void *data) } -static struct drm_info_list amdgpu_debugfs_sa_list[] = { +static const struct drm_info_list amdgpu_debugfs_sa_list[] = { {"amdgpu_sa_info", &amdgpu_debugfs_sa_info, 0, NULL}, }; |