+static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
+ union drm_amdgpu_cs *cs)
+{
+ struct amdgpu_ring * ring = p->ibs->ring;
+ struct amd_sched_fence *fence;
+ struct amdgpu_job *job;
+
+ job = kzalloc(sizeof(struct amdgpu_job), GFP_KERNEL);
+ if (!job)
+ return -ENOMEM;
+
+ job->base.sched = &ring->sched;
+ job->base.s_entity = &p->ctx->rings[ring->idx].entity;
+ job->adev = p->adev;
+ job->owner = p->filp;
+ job->free_job = amdgpu_cs_free_job;
+
+ job->ibs = p->ibs;
+ job->num_ibs = p->num_ibs;
+ p->ibs = NULL;
+ p->num_ibs = 0;
+
+ if (job->ibs[job->num_ibs - 1].user) {
+ job->uf = p->uf;
+ job->ibs[job->num_ibs - 1].user = &job->uf;
+ p->uf.bo = NULL;
+ }
+
+ fence = amd_sched_fence_create(job->base.s_entity, p->filp);
+ if (!fence) {
+ amdgpu_cs_free_job(job);
+ kfree(job);
+ return -ENOMEM;
+ }
+
+ job->base.s_fence = fence;
+ p->fence = fence_get(&fence->base);
+
+ cs->out.handle = amdgpu_ctx_add_fence(p->ctx, ring,
+ &fence->base);
+ job->ibs[job->num_ibs - 1].sequence = cs->out.handle;
+
+ trace_amdgpu_cs_ioctl(job);
+ amd_sched_entity_push_job(&job->base);
+
+ return 0;
+}
+