From: Christian König Date: Wed, 5 Aug 2015 19:22:10 +0000 (+0200) Subject: drm/amdgpu: cleanup and fix scheduler fence handling v2 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=6f0e54a964932d3d5252ac1ff7ab153c984a5d51;p=linux-beck.git drm/amdgpu: cleanup and fix scheduler fence handling v2 v2: rebased Signed-off-by: Christian König Reviewed-by: Alex Deucher (v1) Reviewed-by: Chunming Zhou --- diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c index 787b93db6796..039bd1f748f0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c @@ -43,16 +43,9 @@ static int amdgpu_sched_prepare_job(struct amd_gpu_scheduler *sched, return r; } -static void amdgpu_fence_sched_cb(struct fence *f, struct fence_cb *cb) -{ - struct amd_sched_job *sched_job = - container_of(cb, struct amd_sched_job, cb); - amd_sched_process_job(sched_job); -} - -static void amdgpu_sched_run_job(struct amd_gpu_scheduler *sched, - struct amd_sched_entity *entity, - struct amd_sched_job *job) +static struct fence *amdgpu_sched_run_job(struct amd_gpu_scheduler *sched, + struct amd_sched_entity *entity, + struct amd_sched_job *job) { int r = 0; struct amdgpu_cs_parser *sched_job; @@ -60,7 +53,7 @@ static void amdgpu_sched_run_job(struct amd_gpu_scheduler *sched, if (!job || !job->job) { DRM_ERROR("job is null\n"); - return; + return NULL; } sched_job = (struct amdgpu_cs_parser *)job->job; mutex_lock(&sched_job->job_lock); @@ -70,12 +63,7 @@ static void amdgpu_sched_run_job(struct amd_gpu_scheduler *sched, sched_job->filp); if (r) goto err; - fence = sched_job->ibs[sched_job->num_ibs - 1].fence; - if (fence_add_callback(&fence->base, - &job->cb, amdgpu_fence_sched_cb)) { - DRM_ERROR("fence add callback failed\n"); - goto err; - } + fence = amdgpu_fence_ref(sched_job->ibs[sched_job->num_ibs - 1].fence); if (sched_job->run_job) { r = sched_job->run_job(sched_job); @@ -86,11 +74,13 @@ static void amdgpu_sched_run_job(struct amd_gpu_scheduler *sched, amd_sched_emit(entity, sched_job->ibs[sched_job->num_ibs - 1].sequence); mutex_unlock(&sched_job->job_lock); - return; + return &fence->base; + err: DRM_ERROR("Run job error\n"); mutex_unlock(&sched_job->job_lock); schedule_work(&sched_job->job_work); + return NULL; } static void amdgpu_sched_process_job(struct amd_gpu_scheduler *sched, void *job) diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c index eb3b0993a8cd..438dc23f4bb3 100644 --- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c +++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c @@ -175,9 +175,9 @@ exit: * return 0 if succeed. negative error code on failure */ int amd_sched_entity_init(struct amd_gpu_scheduler *sched, - struct amd_sched_entity *entity, - struct amd_run_queue *rq, - uint32_t jobs) + struct amd_sched_entity *entity, + struct amd_run_queue *rq, + uint32_t jobs) { uint64_t seq_ring = 0; @@ -353,6 +353,24 @@ int amd_sched_wait_emit(struct amd_sched_entity *c_entity, return 0; } +static void amd_sched_process_job(struct fence *f, struct fence_cb *cb) +{ + struct amd_sched_job *sched_job = + container_of(cb, struct amd_sched_job, cb); + struct amd_gpu_scheduler *sched; + unsigned long flags; + + sched = sched_job->sched; + spin_lock_irqsave(&sched->queue_lock, flags); + list_del(&sched_job->list); + atomic64_dec(&sched->hw_rq_count); + spin_unlock_irqrestore(&sched->queue_lock, flags); + + sched->ops->process_job(sched, sched_job->job); + kfree(sched_job); + wake_up_interruptible(&sched->wait_queue); +} + static int amd_sched_main(void *param) { int r; @@ -365,6 +383,8 @@ static int amd_sched_main(void *param) while (!kthread_should_stop()) { struct amd_sched_job *sched_job = NULL; + struct fence *fence; + wait_event_interruptible(sched->wait_queue, is_scheduler_ready(sched) && (c_entity = select_context(sched))); @@ -388,36 +408,21 @@ static int amd_sched_main(void *param) spin_unlock_irqrestore(&sched->queue_lock, flags); } mutex_lock(&sched->sched_lock); - sched->ops->run_job(sched, c_entity, sched_job); + fence = sched->ops->run_job(sched, c_entity, sched_job); + if (fence) { + r = fence_add_callback(fence, &sched_job->cb, + amd_sched_process_job); + if (r == -ENOENT) + amd_sched_process_job(fence, &sched_job->cb); + else if (r) + DRM_ERROR("fence add callback failed (%d)\n", r); + fence_put(fence); + } mutex_unlock(&sched->sched_lock); } return 0; } -/** - * ISR to handle EOP inetrrupts - * - * @sched: gpu scheduler - * -*/ -void amd_sched_process_job(struct amd_sched_job *sched_job) -{ - unsigned long flags; - struct amd_gpu_scheduler *sched; - - if (!sched_job) - return; - sched = sched_job->sched; - spin_lock_irqsave(&sched->queue_lock, flags); - list_del(&sched_job->list); - atomic64_dec(&sched->hw_rq_count); - spin_unlock_irqrestore(&sched->queue_lock, flags); - - sched->ops->process_job(sched, sched_job->job); - kfree(sched_job); - wake_up_interruptible(&sched->wait_queue); -} - /** * Create a gpu scheduler * diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h index a3e29df957fc..e7cc40a6993b 100644 --- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h +++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h @@ -87,9 +87,9 @@ struct amd_sched_backend_ops { int (*prepare_job)(struct amd_gpu_scheduler *sched, struct amd_sched_entity *c_entity, void *job); - void (*run_job)(struct amd_gpu_scheduler *sched, - struct amd_sched_entity *c_entity, - struct amd_sched_job *job); + struct fence *(*run_job)(struct amd_gpu_scheduler *sched, + struct amd_sched_entity *c_entity, + struct amd_sched_job *job); void (*process_job)(struct amd_gpu_scheduler *sched, void *job); }; @@ -132,7 +132,6 @@ int amd_sched_wait_emit(struct amd_sched_entity *c_entity, bool intr, long timeout); -void amd_sched_process_job(struct amd_sched_job *sched_job); uint64_t amd_sched_get_handled_seq(struct amd_gpu_scheduler *sched); int amd_sched_entity_init(struct amd_gpu_scheduler *sched,