drm/amdgpu: cleanup and fix scheduler fence handling v2
authorChristian König <christian.koenig@amd.com>
Wed, 5 Aug 2015 19:22:10 +0000 (21:22 +0200)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 17 Aug 2015 20:51:05 +0000 (16:51 -0400)
v2: rebased

Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com> (v1)
Reviewed-by: Chunming Zhou <david1.zhou@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c
drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
drivers/gpu/drm/amd/scheduler/gpu_scheduler.h

index 787b93db67968fc99d480c3e934a86a6c9d97e92..039bd1f748f0cfe78ead8df4485c0ed88a17673d 100644 (file)
@@ -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)
index eb3b0993a8cdb0324b571391f0f7feb45785c2b1..438dc23f4bb38ec7a3ccd6f8ddb7923c04280039 100644 (file)
@@ -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
  *
index a3e29df957fcbf98cf22973ccbbbe86cb57bb2f1..e7cc40a6993b2371d57710a81b06dcdf1411a9c8 100644 (file)
@@ -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,