Cleanup work in the preceding commit added locking to
drm_sched_entity_pop_job(). This cleanup causes a slightly sub-optimal
lock cycle with drm_sched_rq_pop_entity().

sched_entity also utilizes the lockless spsc_queue (partially already
used simultaneously with locks), which was marked for removal in

commit 6e7eb171ac96 ("Documentation: drm: Add entry for removing spsc_queue to 
TODO list")

To remove the lock-cycle mentioned above, the unlock must be moved
downwards, also locking the lockless queue.

Guard spsc_queue_pop() in drm_sched_entity_pop_job() with the lock and
document why that is being done.

Signed-off-by: Philipp Stanner <[email protected]>
---
 drivers/gpu/drm/scheduler/sched_entity.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/scheduler/sched_entity.c 
b/drivers/gpu/drm/scheduler/sched_entity.c
index 91aec20611ad..5cf0af91faf2 100644
--- a/drivers/gpu/drm/scheduler/sched_entity.c
+++ b/drivers/gpu/drm/scheduler/sched_entity.c
@@ -529,9 +529,17 @@ struct drm_sched_job *drm_sched_entity_pop_job(struct 
drm_sched_entity *entity)
        spin_lock(&entity->lock);
        prev_last_scheduled = entity->last_scheduled;
        entity->last_scheduled = dma_fence_get(&sched_job->s_fence->finished);
-       spin_unlock(&entity->lock);
 
+       /* Preceding cleanup work made it necessary to add the spinlock
+        * to this function. spsc_queue, a lockless queue, is now
+        * counterintuitively guarded by the lock as well. spsc_queue is queued
+        * for removal (see DRM TODO list), so this somewhat serves as a
+        * preparational step.
+        *
+        * TODO: Replace spsc_queue completely with a locked (h)list.
+        */
        spsc_queue_pop(&entity->job_queue);
+       spin_unlock(&entity->lock);
 
        dma_fence_put(prev_last_scheduled);
        drm_sched_rq_pop_entity(entity);
-- 
2.54.0

Reply via email to