1*0856cab1SChristian König /* 2*0856cab1SChristian König * Copyright 2015 Advanced Micro Devices, Inc. 3*0856cab1SChristian König * 4*0856cab1SChristian König * Permission is hereby granted, free of charge, to any person obtaining a 5*0856cab1SChristian König * copy of this software and associated documentation files (the "Software"), 6*0856cab1SChristian König * to deal in the Software without restriction, including without limitation 7*0856cab1SChristian König * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8*0856cab1SChristian König * and/or sell copies of the Software, and to permit persons to whom the 9*0856cab1SChristian König * Software is furnished to do so, subject to the following conditions: 10*0856cab1SChristian König * 11*0856cab1SChristian König * The above copyright notice and this permission notice shall be included in 12*0856cab1SChristian König * all copies or substantial portions of the Software. 13*0856cab1SChristian König * 14*0856cab1SChristian König * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15*0856cab1SChristian König * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16*0856cab1SChristian König * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17*0856cab1SChristian König * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18*0856cab1SChristian König * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19*0856cab1SChristian König * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20*0856cab1SChristian König * OTHER DEALINGS IN THE SOFTWARE. 21*0856cab1SChristian König * 22*0856cab1SChristian König * 23*0856cab1SChristian König */ 24*0856cab1SChristian König #include <linux/kthread.h> 25*0856cab1SChristian König #include <linux/wait.h> 26*0856cab1SChristian König #include <linux/sched.h> 27*0856cab1SChristian König #include <drm/drmP.h> 28*0856cab1SChristian König #include "amdgpu.h" 29*0856cab1SChristian König #include "amdgpu_trace.h" 30*0856cab1SChristian König 31*0856cab1SChristian König int amdgpu_job_alloc(struct amdgpu_device *adev, unsigned num_ibs, 32*0856cab1SChristian König struct amdgpu_job **job) 33*0856cab1SChristian König { 34*0856cab1SChristian König size_t size = sizeof(struct amdgpu_job); 35*0856cab1SChristian König 36*0856cab1SChristian König if (num_ibs == 0) 37*0856cab1SChristian König return -EINVAL; 38*0856cab1SChristian König 39*0856cab1SChristian König size += sizeof(struct amdgpu_ib) * num_ibs; 40*0856cab1SChristian König 41*0856cab1SChristian König *job = kzalloc(size, GFP_KERNEL); 42*0856cab1SChristian König if (!*job) 43*0856cab1SChristian König return -ENOMEM; 44*0856cab1SChristian König 45*0856cab1SChristian König (*job)->adev = adev; 46*0856cab1SChristian König (*job)->ibs = (void *)&(*job)[1]; 47*0856cab1SChristian König (*job)->num_ibs = num_ibs; 48*0856cab1SChristian König 49*0856cab1SChristian König return 0; 50*0856cab1SChristian König } 51*0856cab1SChristian König 52*0856cab1SChristian König int amdgpu_job_alloc_with_ib(struct amdgpu_device *adev, unsigned size, 53*0856cab1SChristian König struct amdgpu_job **job) 54*0856cab1SChristian König { 55*0856cab1SChristian König int r; 56*0856cab1SChristian König 57*0856cab1SChristian König r = amdgpu_job_alloc(adev, 1, job); 58*0856cab1SChristian König if (r) 59*0856cab1SChristian König return r; 60*0856cab1SChristian König 61*0856cab1SChristian König r = amdgpu_ib_get(adev, NULL, size, &(*job)->ibs[0]); 62*0856cab1SChristian König if (r) 63*0856cab1SChristian König kfree(*job); 64*0856cab1SChristian König 65*0856cab1SChristian König return r; 66*0856cab1SChristian König } 67*0856cab1SChristian König 68*0856cab1SChristian König void amdgpu_job_free(struct amdgpu_job *job) 69*0856cab1SChristian König { 70*0856cab1SChristian König unsigned i; 71*0856cab1SChristian König 72*0856cab1SChristian König for (i = 0; i < job->num_ibs; ++i) 73*0856cab1SChristian König amdgpu_ib_free(job->adev, &job->ibs[i]); 74*0856cab1SChristian König 75*0856cab1SChristian König amdgpu_bo_unref(&job->uf.bo); 76*0856cab1SChristian König kfree(job); 77*0856cab1SChristian König } 78*0856cab1SChristian König 79*0856cab1SChristian König int amdgpu_job_submit(struct amdgpu_job *job, struct amdgpu_ring *ring, 80*0856cab1SChristian König void *owner, struct fence **f) 81*0856cab1SChristian König { 82*0856cab1SChristian König struct amdgpu_device *adev = job->adev; 83*0856cab1SChristian König 84*0856cab1SChristian König job->ring = ring; 85*0856cab1SChristian König job->base.sched = &ring->sched; 86*0856cab1SChristian König job->base.s_entity = &adev->kernel_ctx.rings[ring->idx].entity; 87*0856cab1SChristian König job->base.s_fence = amd_sched_fence_create(job->base.s_entity, owner); 88*0856cab1SChristian König if (!job->base.s_fence) 89*0856cab1SChristian König return -ENOMEM; 90*0856cab1SChristian König 91*0856cab1SChristian König *f = fence_get(&job->base.s_fence->base); 92*0856cab1SChristian König 93*0856cab1SChristian König job->owner = owner; 94*0856cab1SChristian König amd_sched_entity_push_job(&job->base); 95*0856cab1SChristian König 96*0856cab1SChristian König return 0; 97*0856cab1SChristian König } 98*0856cab1SChristian König 99*0856cab1SChristian König static struct fence *amdgpu_job_dependency(struct amd_sched_job *sched_job) 100*0856cab1SChristian König { 101*0856cab1SChristian König struct amdgpu_job *job = to_amdgpu_job(sched_job); 102*0856cab1SChristian König struct amdgpu_sync *sync = &job->ibs->sync; 103*0856cab1SChristian König struct amdgpu_vm *vm = job->ibs->vm; 104*0856cab1SChristian König 105*0856cab1SChristian König struct fence *fence = amdgpu_sync_get_fence(sync); 106*0856cab1SChristian König 107*0856cab1SChristian König if (fence == NULL && vm && !job->ibs->grabbed_vmid) { 108*0856cab1SChristian König struct amdgpu_ring *ring = job->ring; 109*0856cab1SChristian König int r; 110*0856cab1SChristian König 111*0856cab1SChristian König r = amdgpu_vm_grab_id(vm, ring, sync, 112*0856cab1SChristian König &job->base.s_fence->base); 113*0856cab1SChristian König if (r) 114*0856cab1SChristian König DRM_ERROR("Error getting VM ID (%d)\n", r); 115*0856cab1SChristian König else 116*0856cab1SChristian König job->ibs->grabbed_vmid = true; 117*0856cab1SChristian König 118*0856cab1SChristian König fence = amdgpu_sync_get_fence(sync); 119*0856cab1SChristian König } 120*0856cab1SChristian König 121*0856cab1SChristian König return fence; 122*0856cab1SChristian König } 123*0856cab1SChristian König 124*0856cab1SChristian König static struct fence *amdgpu_job_run(struct amd_sched_job *sched_job) 125*0856cab1SChristian König { 126*0856cab1SChristian König struct fence *fence = NULL; 127*0856cab1SChristian König struct amdgpu_job *job; 128*0856cab1SChristian König int r; 129*0856cab1SChristian König 130*0856cab1SChristian König if (!sched_job) { 131*0856cab1SChristian König DRM_ERROR("job is null\n"); 132*0856cab1SChristian König return NULL; 133*0856cab1SChristian König } 134*0856cab1SChristian König job = to_amdgpu_job(sched_job); 135*0856cab1SChristian König trace_amdgpu_sched_run_job(job); 136*0856cab1SChristian König r = amdgpu_ib_schedule(job->ring, job->num_ibs, job->ibs, 137*0856cab1SChristian König job->owner, &fence); 138*0856cab1SChristian König if (r) { 139*0856cab1SChristian König DRM_ERROR("Error scheduling IBs (%d)\n", r); 140*0856cab1SChristian König goto err; 141*0856cab1SChristian König } 142*0856cab1SChristian König 143*0856cab1SChristian König err: 144*0856cab1SChristian König amdgpu_job_free(job); 145*0856cab1SChristian König return fence; 146*0856cab1SChristian König } 147*0856cab1SChristian König 148*0856cab1SChristian König struct amd_sched_backend_ops amdgpu_sched_ops = { 149*0856cab1SChristian König .dependency = amdgpu_job_dependency, 150*0856cab1SChristian König .run_job = amdgpu_job_run, 151*0856cab1SChristian König }; 152