From 69bd5bf13a8eccb4db5f26de608556416a56d973 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 26 Aug 2015 11:31:23 +0200 Subject: [PATCH 0507/1050] drm/amdgpu: let the scheduler work more with jobs v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v2: fix another race condition Signed-off-by: Christian König Reviewed-by: Chunming Zhou Reviewed-by: Jammy Zhou --- drivers/gpu/drm/amd/scheduler/gpu_scheduler.c | 61 ++++++++++++++++----------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c index d99fe90..205cb88 100644 --- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c +++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c @@ -27,6 +27,8 @@ #include #include "gpu_scheduler.h" +static struct amd_sched_job * +amd_sched_entity_pop_job(struct amd_sched_entity *entity); static void amd_sched_wakeup(struct amd_gpu_scheduler *sched); /* Initialize a given run queue struct */ @@ -56,34 +58,36 @@ static void amd_sched_rq_remove_entity(struct amd_sched_rq *rq, } /** - * Select next entity from a specified run queue with round robin policy. - * It could return the same entity as current one if current is the only - * available one in the queue. Return NULL if nothing available. + * Select next job from a specified run queue with round robin policy. + * Return NULL if nothing available. */ -static struct amd_sched_entity * -amd_sched_rq_select_entity(struct amd_sched_rq *rq) +static struct amd_sched_job * +amd_sched_rq_select_job(struct amd_sched_rq *rq) { struct amd_sched_entity *entity; + struct amd_sched_job *job; spin_lock(&rq->lock); entity = rq->current_entity; if (entity) { list_for_each_entry_continue(entity, &rq->entities, list) { - if (!kfifo_is_empty(&entity->job_queue)) { + job = amd_sched_entity_pop_job(entity); + if (job) { rq->current_entity = entity; spin_unlock(&rq->lock); - return rq->current_entity; + return job; } } } list_for_each_entry(entity, &rq->entities, list) { - if (!kfifo_is_empty(&entity->job_queue)) { + job = amd_sched_entity_pop_job(entity); + if (job) { rq->current_entity = entity; spin_unlock(&rq->lock); - return rq->current_entity; + return job; } if (entity == rq->current_entity) @@ -188,6 +192,17 @@ void amd_sched_entity_fini(struct amd_gpu_scheduler *sched, kfifo_free(&entity->job_queue); } +static struct amd_sched_job * +amd_sched_entity_pop_job(struct amd_sched_entity *entity) +{ + struct amd_sched_job *job; + + if (!kfifo_out_peek(&entity->job_queue, &job, sizeof(job))) + return NULL; + + return job; +} + /** * Helper to submit a job to the job queue * @@ -260,22 +275,22 @@ static void amd_sched_wakeup(struct amd_gpu_scheduler *sched) } /** - * Select next entity containing real IB submissions + * Select next to run */ -static struct amd_sched_entity * -amd_sched_select_context(struct amd_gpu_scheduler *sched) +static struct amd_sched_job * +amd_sched_select_job(struct amd_gpu_scheduler *sched) { - struct amd_sched_entity *tmp; + struct amd_sched_job *job; if (!amd_sched_ready(sched)) return NULL; /* Kernel run queue has higher priority than normal run queue*/ - tmp = amd_sched_rq_select_entity(&sched->kernel_rq); - if (tmp == NULL) - tmp = amd_sched_rq_select_entity(&sched->sched_rq); + job = amd_sched_rq_select_job(&sched->kernel_rq); + if (job == NULL) + job = amd_sched_rq_select_job(&sched->sched_rq); - return tmp; + return job; } static void amd_sched_process_job(struct fence *f, struct fence_cb *cb) @@ -301,22 +316,19 @@ static int amd_sched_main(void *param) sched_setscheduler(current, SCHED_FIFO, &sparam); while (!kthread_should_stop()) { - struct amd_sched_entity *c_entity = NULL; + struct amd_sched_entity *entity; struct amd_sched_job *job; struct fence *fence; wait_event_interruptible(sched->wake_up_worker, kthread_should_stop() || - (c_entity = amd_sched_select_context(sched))); + (job = amd_sched_select_job(sched))); - if (!c_entity) + if (!job) continue; - r = kfifo_out(&c_entity->job_queue, &job, sizeof(void *)); - if (r != sizeof(void *)) - continue; + entity = job->s_entity; atomic_inc(&sched->hw_rq_count); - fence = sched->ops->run_job(job); if (fence) { r = fence_add_callback(fence, &job->cb, @@ -328,6 +340,7 @@ static int amd_sched_main(void *param) fence_put(fence); } + kfifo_out(&entity->job_queue, &job, sizeof(job)); wake_up(&sched->job_scheduled); } return 0; -- 1.9.1