drm/amdgpu: require a job to schedule an IB

Remove the old direct submit path.  This simplifies
the code.

v2: remove more local variables

Reviewed-by: Jesse Zhang <jesse.zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Alex Deucher 2026-01-07 15:30:37 -05:00
parent 451bfc778a
commit c06d09d09c
4 changed files with 49 additions and 85 deletions

View File

@ -727,7 +727,7 @@ int amdgpu_amdkfd_submit_ib(struct amdgpu_device *adev,
job->vmid = vmid;
job->num_ibs = 1;
ret = amdgpu_ib_schedule(ring, 1, ib, job, &f);
ret = amdgpu_ib_schedule(ring, job, &f);
if (ret) {
drm_err(adev_to_drm(adev), "failed to schedule IB.\n");

View File

@ -27,8 +27,6 @@
* Christian König
*/
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <drm/amdgpu_drm.h>
#include "amdgpu.h"
@ -102,11 +100,9 @@ void amdgpu_ib_free(struct amdgpu_ib *ib, struct dma_fence *f)
/**
* amdgpu_ib_schedule - schedule an IB (Indirect Buffer) on the ring
*
* @ring: ring index the IB is associated with
* @num_ibs: number of IBs to schedule
* @ibs: IB objects to schedule
* @ring: ring structure the IB is associated with
* @job: job to schedule
* @f: fence created during this submission
* @f: fence referenced during this submission
*
* Schedule an IB on the associated ring (all asics).
* Returns 0 on success, error on failure.
@ -121,92 +117,71 @@ void amdgpu_ib_free(struct amdgpu_ib *ib, struct dma_fence *f)
* a CONST_IB), it will be put on the ring prior to the DE IB. Prior
* to SI there was just a DE IB.
*/
int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
struct amdgpu_ib *ibs, struct amdgpu_job *job,
int amdgpu_ib_schedule(struct amdgpu_ring *ring, struct amdgpu_job *job,
struct dma_fence **f)
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_ib *ib = &ibs[0];
struct amdgpu_ib *ib;
struct dma_fence *tmp = NULL;
struct amdgpu_fence *af;
struct amdgpu_fence *vm_af;
bool need_ctx_switch;
bool emit_spm_needed = false;
bool emit_gds_needed = false;
struct amdgpu_vm *vm;
uint64_t fence_ctx;
uint32_t status = 0, alloc_size;
unsigned int fence_flags = 0;
bool secure, init_shadow;
u64 shadow_va, csa_va, gds_va;
int vmid = AMDGPU_JOB_GET_VMID(job);
bool secure;
unsigned int vmid;
bool need_pipe_sync = false;
unsigned int cond_exec;
unsigned int i;
int r = 0;
int r;
if (num_ibs == 0)
if (!job || !job->num_ibs)
return -EINVAL;
/* ring tests don't use a job */
if (job) {
vm = job->vm;
fence_ctx = job->base.s_fence ?
job->base.s_fence->finished.context : 0;
shadow_va = job->shadow_va;
csa_va = job->csa_va;
gds_va = job->gds_va;
init_shadow = job->init_shadow;
af = job->hw_fence;
/* Save the context of the job for reset handling.
* The driver needs this so it can skip the ring
* contents for guilty contexts.
*/
af->context = fence_ctx;
/* the vm fence is also part of the job's context */
job->hw_vm_fence->context = fence_ctx;
} else {
vm = NULL;
fence_ctx = 0;
shadow_va = 0;
csa_va = 0;
gds_va = 0;
init_shadow = false;
af = kzalloc_obj(*af, GFP_ATOMIC);
if (!af)
return -ENOMEM;
}
vmid = AMDGPU_JOB_GET_VMID(job);
ib = &job->ibs[0];
fence_ctx = job->base.s_fence ?
job->base.s_fence->finished.context : 0;
af = job->hw_fence;
vm_af = job->hw_vm_fence;
/* Save the context of the job for reset handling.
* The driver needs this so it can skip the ring
* contents for guilty contexts.
*/
af->context = fence_ctx;
/* the vm fence is also part of the job's context */
vm_af->context = fence_ctx;
if (!ring->sched.ready) {
dev_err(adev->dev, "couldn't schedule ib on ring <%s>\n", ring->name);
r = -EINVAL;
goto free_fence;
return -EINVAL;
}
if (vm && !job->vmid) {
if (job->vm && !job->vmid) {
dev_err(adev->dev, "VM IB without ID\n");
r = -EINVAL;
goto free_fence;
return -EINVAL;
}
if ((ib->flags & AMDGPU_IB_FLAGS_SECURE) &&
(!ring->funcs->secure_submission_supported)) {
dev_err(adev->dev, "secure submissions not supported on ring <%s>\n", ring->name);
r = -EINVAL;
goto free_fence;
return -EINVAL;
}
alloc_size = ring->funcs->emit_frame_size + num_ibs *
alloc_size = ring->funcs->emit_frame_size + job->num_ibs *
ring->funcs->emit_ib_size;
r = amdgpu_ring_alloc(ring, alloc_size);
if (r) {
dev_err(adev->dev, "scheduling IB failed (%d).\n", r);
goto free_fence;
return r;
}
need_ctx_switch = ring->current_ctx != fence_ctx;
if (ring->funcs->emit_pipeline_sync && job &&
if (ring->funcs->emit_pipeline_sync &&
((tmp = amdgpu_sync_get_fence(&job->explicit_sync)) ||
need_ctx_switch || amdgpu_vm_need_pipeline_sync(ring, job))) {
@ -218,15 +193,12 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
dma_fence_put(tmp);
}
if (job) {
vm_af = job->hw_vm_fence;
/* VM sequence */
vm_af->ib_wptr = ring->wptr;
amdgpu_vm_flush(ring, job, &need_pipe_sync, &emit_spm_needed,
&emit_gds_needed);
vm_af->ib_dw_size =
amdgpu_ring_get_dw_distance(ring, vm_af->ib_wptr, ring->wptr);
}
/* VM sequence */
vm_af->ib_wptr = ring->wptr;
amdgpu_vm_flush(ring, job, &need_pipe_sync, &emit_spm_needed,
&emit_gds_needed);
vm_af->ib_dw_size =
amdgpu_ring_get_dw_distance(ring, vm_af->ib_wptr, ring->wptr);
/* IB sequence */
af->ib_wptr = ring->wptr;
@ -256,8 +228,8 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
ring->funcs->emit_wave_limit(ring, true);
if (ring->funcs->emit_gfx_shadow && adev->gfx.cp_gfx_shadow)
amdgpu_ring_emit_gfx_shadow(ring, shadow_va, csa_va, gds_va,
init_shadow, vmid);
amdgpu_ring_emit_gfx_shadow(ring, job->shadow_va, job->csa_va, job->gds_va,
job->init_shadow, vmid);
if (ring->funcs->init_cond_exec)
cond_exec = amdgpu_ring_init_cond_exec(ring,
@ -271,7 +243,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
if (need_ctx_switch)
status |= AMDGPU_HAVE_CTX_SWITCH;
if (job && ring->funcs->emit_cntxcntl) {
if (ring->funcs->emit_cntxcntl) {
status |= job->preamble_status;
status |= job->preemption_status;
amdgpu_ring_emit_cntxcntl(ring, status);
@ -280,15 +252,15 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
/* Setup initial TMZiness and send it off.
*/
secure = false;
if (job && ring->funcs->emit_frame_cntl) {
if (ring->funcs->emit_frame_cntl) {
secure = ib->flags & AMDGPU_IB_FLAGS_SECURE;
amdgpu_ring_emit_frame_cntl(ring, true, secure);
}
for (i = 0; i < num_ibs; ++i) {
ib = &ibs[i];
for (i = 0; i < job->num_ibs; ++i) {
ib = &job->ibs[i];
if (job && ring->funcs->emit_frame_cntl) {
if (ring->funcs->emit_frame_cntl) {
if (secure != !!(ib->flags & AMDGPU_IB_FLAGS_SECURE)) {
amdgpu_ring_emit_frame_cntl(ring, false, secure);
secure = !secure;
@ -300,7 +272,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
status &= ~AMDGPU_HAVE_CTX_SWITCH;
}
if (job && ring->funcs->emit_frame_cntl)
if (ring->funcs->emit_frame_cntl)
amdgpu_ring_emit_frame_cntl(ring, false, secure);
amdgpu_device_invalidate_hdp(adev, ring);
@ -312,7 +284,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
fence_flags |= AMDGPU_FENCE_FLAG_TC_WB_ONLY;
/* wrap the last IB with fence */
if (job && job->uf_addr) {
if (job->uf_addr) {
amdgpu_ring_emit_fence(ring, job->uf_addr, job->uf_sequence,
fence_flags | AMDGPU_FENCE_FLAG_64BIT);
}
@ -326,8 +298,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
amdgpu_fence_emit(ring, af, fence_flags);
*f = &af->base;
/* get a ref for the job */
if (job)
dma_fence_get(*f);
dma_fence_get(*f);
if (ring->funcs->insert_end)
ring->funcs->insert_end(ring);
@ -335,7 +306,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
amdgpu_ring_patch_cond_exec(ring, cond_exec);
ring->current_ctx = fence_ctx;
if (job && ring->funcs->emit_switch_buffer)
if (ring->funcs->emit_switch_buffer)
amdgpu_ring_emit_switch_buffer(ring);
if (ring->funcs->emit_wave_limit &&
@ -349,11 +320,6 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
amdgpu_ring_commit(ring);
return 0;
free_fence:
if (!job)
kfree(af);
return r;
}
/**

View File

@ -387,7 +387,7 @@ int amdgpu_job_submit_direct(struct amdgpu_job *job, struct amdgpu_ring *ring,
int r;
job->base.sched = &ring->sched;
r = amdgpu_ib_schedule(ring, job->num_ibs, job->ibs, job, fence);
r = amdgpu_ib_schedule(ring, job, fence);
if (r)
return r;
@ -457,8 +457,7 @@ static struct dma_fence *amdgpu_job_run(struct drm_sched_job *sched_job)
dev_dbg(adev->dev, "Skip scheduling IBs in ring(%s)",
ring->name);
} else {
r = amdgpu_ib_schedule(ring, job->num_ibs, job->ibs, job,
&fence);
r = amdgpu_ib_schedule(ring, job, &fence);
if (r)
dev_err(adev->dev,
"Error scheduling IBs (%d) in ring(%s)", r,

View File

@ -578,8 +578,7 @@ int amdgpu_ib_get(struct amdgpu_device *adev, struct amdgpu_vm *vm,
enum amdgpu_ib_pool_type pool,
struct amdgpu_ib *ib);
void amdgpu_ib_free(struct amdgpu_ib *ib, struct dma_fence *f);
int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
struct amdgpu_ib *ibs, struct amdgpu_job *job,
int amdgpu_ib_schedule(struct amdgpu_ring *ring, struct amdgpu_job *job,
struct dma_fence **f);
int amdgpu_ib_pool_init(struct amdgpu_device *adev);
void amdgpu_ib_pool_fini(struct amdgpu_device *adev);