This fixes accessing the last_scheduled fence from multiple threads as
well as makes it easier to move entities between schedulers.

Signed-off-by: Christian König <christian.koe...@amd.com>
---
 drivers/gpu/drm/scheduler/gpu_scheduler.c | 34 +++++++++++++++++++++++++------
 1 file changed, 28 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/scheduler/gpu_scheduler.c 
b/drivers/gpu/drm/scheduler/gpu_scheduler.c
index 029863726c99..e4b71a543481 100644
--- a/drivers/gpu/drm/scheduler/gpu_scheduler.c
+++ b/drivers/gpu/drm/scheduler/gpu_scheduler.c
@@ -523,6 +523,29 @@ static bool drm_sched_entity_add_dependency_cb(struct 
drm_sched_entity *entity)
        return false;
 }
 
+static bool drm_sched_entity_last_scheduled_dep(struct drm_sched_entity 
*entity)
+{
+       struct drm_sched_fence *s_fence;
+
+       if (!entity->last_scheduled)
+               return false;
+
+       /*
+        * Check if the last submission was handled by a different scheduler
+        */
+       s_fence = to_drm_sched_fence(entity->last_scheduled);
+       if (s_fence && s_fence->sched != entity->rq->sched) {
+               entity->dependency = dma_fence_get(entity->last_scheduled);
+               if (!dma_fence_add_callback(entity->dependency, &entity->cb,
+                                           drm_sched_entity_wakeup))
+                       return true;
+
+               dma_fence_put(entity->dependency);
+               entity->dependency = NULL;
+       }
+       return false;
+}
+
 static struct drm_sched_job *
 drm_sched_entity_pop_job(struct drm_sched_entity *entity)
 {
@@ -537,6 +560,9 @@ drm_sched_entity_pop_job(struct drm_sched_entity *entity)
                if (drm_sched_entity_add_dependency_cb(entity))
                        return NULL;
 
+       if (drm_sched_entity_last_scheduled_dep(entity))
+               return NULL;
+
        /* skip jobs from entity that marked guilty */
        if (entity->guilty && atomic_read(entity->guilty))
                dma_fence_set_error(&sched_job->s_fence->finished, -ECANCELED);
@@ -564,14 +590,10 @@ void drm_sched_entity_push_job(struct drm_sched_job 
*sched_job,
                               struct drm_sched_entity *entity)
 {
        struct drm_sched_rq *rq = entity->rq;
-       bool first, reschedule, idle;
+       bool first;
 
-       idle = entity->last_scheduled == NULL ||
-               dma_fence_is_signaled(entity->last_scheduled);
        first = spsc_queue_count(&entity->job_queue) == 0;
-       reschedule = idle && first && (entity->num_rq_list > 1);
-
-       if (reschedule) {
+       if (first && (entity->num_rq_list > 1)) {
                rq = drm_sched_entity_get_free_sched(entity);
                spin_lock(&entity->rq_lock);
                drm_sched_rq_remove_entity(entity->rq, entity);
-- 
2.14.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to