]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/sched: Move run queue related code into a separate file
authorTvrtko Ursulin <tvrtko.ursulin@igalia.com>
Fri, 17 Apr 2026 10:37:18 +0000 (11:37 +0100)
committerPhilipp Stanner <phasta@kernel.org>
Fri, 17 Apr 2026 12:43:28 +0000 (14:43 +0200)
Lets move all the code dealing with struct drm_sched_rq into a separate
compilation unit. Advantage being sched_main.c is left with a clearer set
of responsibilities.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: Danilo Krummrich <dakr@kernel.org>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Philipp Stanner <phasta@kernel.org>
Reviewed-by: Matthew Brost <matthew.brost@intel.com> # v1
Acked-by: Danilo Krummrich <dakr@kernel.org>
Tested-by: Vitaly Prosyak <vitaly.prosyak@amd.com>
Signed-off-by: Philipp Stanner <phasta@kernel.org>
Link: https://patch.msgid.link/20260417103744.76020-4-tvrtko.ursulin@igalia.com
drivers/gpu/drm/scheduler/Makefile
drivers/gpu/drm/scheduler/sched_internal.h
drivers/gpu/drm/scheduler/sched_main.c
drivers/gpu/drm/scheduler/sched_rq.c [new file with mode: 0644]

index 6e13e4c63e9d871d4d2f773fc6d46526ad2644dd..74e75eff6df50c23f39de450a9d5390471a5aba9 100644 (file)
@@ -20,7 +20,7 @@
 # OTHER DEALINGS IN THE SOFTWARE.
 #
 #
-gpu-sched-y := sched_main.o sched_fence.o sched_entity.o
+gpu-sched-y := sched_main.o sched_fence.o sched_entity.o sched_rq.o
 
 obj-$(CONFIG_DRM_SCHED) += gpu-sched.o
 
index 8269c5392a827b20bf87cb8563c83f2b50498748..aab63a8721d94f86115880474acb3e1b6af0450c 100644 (file)
@@ -10,14 +10,26 @@ extern int drm_sched_policy;
 #define DRM_SCHED_POLICY_RR    0
 #define DRM_SCHED_POLICY_FIFO  1
 
+bool drm_sched_can_queue(struct drm_gpu_scheduler *sched,
+                        struct drm_sched_entity *entity);
 void drm_sched_wakeup(struct drm_gpu_scheduler *sched);
 
+void drm_sched_rq_init(struct drm_gpu_scheduler *sched,
+                      struct drm_sched_rq *rq);
+
 struct drm_gpu_scheduler *
 drm_sched_rq_add_entity(struct drm_sched_entity *entity, ktime_t ts);
 void drm_sched_rq_remove_entity(struct drm_sched_rq *rq,
                                struct drm_sched_entity *entity);
 void drm_sched_rq_pop_entity(struct drm_sched_entity *entity);
 
+struct drm_sched_entity *
+drm_sched_rq_select_entity_rr(struct drm_gpu_scheduler *sched,
+                             struct drm_sched_rq *rq);
+struct drm_sched_entity *
+drm_sched_rq_select_entity_fifo(struct drm_gpu_scheduler *sched,
+                               struct drm_sched_rq *rq);
+
 void drm_sched_entity_select_rq(struct drm_sched_entity *entity);
 struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity);
 
index f4aab2915df8d6dcda1bb1406f58599ee278dc05..298509e40d695a05d98a6f5c8c472d20579efcdd 100644 (file)
@@ -112,8 +112,8 @@ static u32 drm_sched_available_credits(struct drm_gpu_scheduler *sched)
  * Return true if we can push at least one more job from @entity, false
  * otherwise.
  */
-static bool drm_sched_can_queue(struct drm_gpu_scheduler *sched,
-                               struct drm_sched_entity *entity)
+bool drm_sched_can_queue(struct drm_gpu_scheduler *sched,
+                        struct drm_sched_entity *entity)
 {
        struct drm_sched_job *s_job;
 
@@ -133,263 +133,6 @@ static bool drm_sched_can_queue(struct drm_gpu_scheduler *sched,
        return drm_sched_available_credits(sched) >= s_job->credits;
 }
 
-static __always_inline bool drm_sched_entity_compare_before(struct rb_node *a,
-                                                           const struct rb_node *b)
-{
-       struct drm_sched_entity *ent_a =  rb_entry((a), struct drm_sched_entity, rb_tree_node);
-       struct drm_sched_entity *ent_b =  rb_entry((b), struct drm_sched_entity, rb_tree_node);
-
-       return ktime_before(ent_a->oldest_job_waiting, ent_b->oldest_job_waiting);
-}
-
-static void drm_sched_rq_remove_fifo_locked(struct drm_sched_entity *entity,
-                                           struct drm_sched_rq *rq)
-{
-       if (!RB_EMPTY_NODE(&entity->rb_tree_node)) {
-               rb_erase_cached(&entity->rb_tree_node, &rq->rb_tree_root);
-               RB_CLEAR_NODE(&entity->rb_tree_node);
-       }
-}
-
-static void drm_sched_rq_update_fifo_locked(struct drm_sched_entity *entity,
-                                           struct drm_sched_rq *rq,
-                                           ktime_t ts)
-{
-       /*
-        * Both locks need to be grabbed, one to protect from entity->rq change
-        * for entity from within concurrent drm_sched_entity_select_rq and the
-        * other to update the rb tree structure.
-        */
-       lockdep_assert_held(&entity->lock);
-       lockdep_assert_held(&rq->lock);
-
-       drm_sched_rq_remove_fifo_locked(entity, rq);
-
-       entity->oldest_job_waiting = ts;
-
-       rb_add_cached(&entity->rb_tree_node, &rq->rb_tree_root,
-                     drm_sched_entity_compare_before);
-}
-
-/**
- * drm_sched_rq_init - initialize a given run queue struct
- *
- * @sched: scheduler instance to associate with this run queue
- * @rq: scheduler run queue
- *
- * Initializes a scheduler runqueue.
- */
-static void drm_sched_rq_init(struct drm_gpu_scheduler *sched,
-                             struct drm_sched_rq *rq)
-{
-       spin_lock_init(&rq->lock);
-       INIT_LIST_HEAD(&rq->entities);
-       rq->rb_tree_root = RB_ROOT_CACHED;
-       rq->current_entity = NULL;
-       rq->sched = sched;
-}
-
-/**
- * drm_sched_rq_add_entity - add an entity
- * @entity: scheduler entity
- * @ts: submission timestamp
- *
- * Adds a scheduler entity to the run queue.
- *
- * Return: DRM scheduler selected to handle this entity or NULL if entity has
- * been stopped and cannot be submitted to.
- */
-struct drm_gpu_scheduler *
-drm_sched_rq_add_entity(struct drm_sched_entity *entity, ktime_t ts)
-{
-       struct drm_gpu_scheduler *sched;
-       struct drm_sched_rq *rq;
-
-       /* Add the entity to the run queue */
-       spin_lock(&entity->lock);
-       if (entity->stopped) {
-               spin_unlock(&entity->lock);
-
-               DRM_ERROR("Trying to push to a killed entity\n");
-               return NULL;
-       }
-
-       rq = entity->rq;
-       spin_lock(&rq->lock);
-       sched = rq->sched;
-
-       if (list_empty(&entity->list)) {
-               atomic_inc(sched->score);
-               list_add_tail(&entity->list, &rq->entities);
-       }
-
-       if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
-               drm_sched_rq_update_fifo_locked(entity, rq, ts);
-
-       spin_unlock(&rq->lock);
-       spin_unlock(&entity->lock);
-
-       return sched;
-}
-
-/**
- * drm_sched_rq_remove_entity - remove an entity
- *
- * @rq: scheduler run queue
- * @entity: scheduler entity
- *
- * Removes a scheduler entity from the run queue.
- */
-void drm_sched_rq_remove_entity(struct drm_sched_rq *rq,
-                               struct drm_sched_entity *entity)
-{
-       lockdep_assert_held(&entity->lock);
-
-       if (list_empty(&entity->list))
-               return;
-
-       spin_lock(&rq->lock);
-
-       atomic_dec(rq->sched->score);
-       list_del_init(&entity->list);
-
-       if (rq->current_entity == entity)
-               rq->current_entity = NULL;
-
-       if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
-               drm_sched_rq_remove_fifo_locked(entity, rq);
-
-       spin_unlock(&rq->lock);
-}
-
-/**
- * drm_sched_rq_pop_entity - pops an entity
- * @entity: scheduler entity
- *
- * To be called every time after a job is popped from the entity.
- */
-void drm_sched_rq_pop_entity(struct drm_sched_entity *entity)
-{
-       /*
-        * Update the entity's location in the min heap according to
-        * the timestamp of the next job, if any.
-        */
-       if (drm_sched_policy == DRM_SCHED_POLICY_FIFO) {
-               struct drm_sched_job *next;
-
-               next = drm_sched_entity_queue_peek(entity);
-               if (next) {
-                       struct drm_sched_rq *rq;
-
-                       spin_lock(&entity->lock);
-                       rq = entity->rq;
-                       spin_lock(&rq->lock);
-                       drm_sched_rq_update_fifo_locked(entity, rq,
-                                                       next->submit_ts);
-                       spin_unlock(&rq->lock);
-                       spin_unlock(&entity->lock);
-               }
-       }
-}
-
-/**
- * drm_sched_rq_select_entity_rr - Select an entity which could provide a job to run
- *
- * @sched: the gpu scheduler
- * @rq: scheduler run queue to check.
- *
- * Try to find the next ready entity.
- *
- * Return an entity if one is found; return an error-pointer (!NULL) if an
- * entity was ready, but the scheduler had insufficient credits to accommodate
- * its job; return NULL, if no ready entity was found.
- */
-static struct drm_sched_entity *
-drm_sched_rq_select_entity_rr(struct drm_gpu_scheduler *sched,
-                             struct drm_sched_rq *rq)
-{
-       struct drm_sched_entity *entity;
-
-       spin_lock(&rq->lock);
-
-       entity = rq->current_entity;
-       if (entity) {
-               list_for_each_entry_continue(entity, &rq->entities, list) {
-                       if (drm_sched_entity_is_ready(entity))
-                               goto found;
-               }
-       }
-
-       list_for_each_entry(entity, &rq->entities, list) {
-               if (drm_sched_entity_is_ready(entity))
-                       goto found;
-
-               if (entity == rq->current_entity)
-                       break;
-       }
-
-       spin_unlock(&rq->lock);
-
-       return NULL;
-
-found:
-       if (!drm_sched_can_queue(sched, entity)) {
-               /*
-                * If scheduler cannot take more jobs signal the caller to not
-                * consider lower priority queues.
-                */
-               entity = ERR_PTR(-ENOSPC);
-       } else {
-               rq->current_entity = entity;
-               reinit_completion(&entity->entity_idle);
-       }
-
-       spin_unlock(&rq->lock);
-
-       return entity;
-}
-
-/**
- * drm_sched_rq_select_entity_fifo - Select an entity which provides a job to run
- *
- * @sched: the gpu scheduler
- * @rq: scheduler run queue to check.
- *
- * Find oldest waiting ready entity.
- *
- * Return an entity if one is found; return an error-pointer (!NULL) if an
- * entity was ready, but the scheduler had insufficient credits to accommodate
- * its job; return NULL, if no ready entity was found.
- */
-static struct drm_sched_entity *
-drm_sched_rq_select_entity_fifo(struct drm_gpu_scheduler *sched,
-                               struct drm_sched_rq *rq)
-{
-       struct rb_node *rb;
-
-       spin_lock(&rq->lock);
-       for (rb = rb_first_cached(&rq->rb_tree_root); rb; rb = rb_next(rb)) {
-               struct drm_sched_entity *entity;
-
-               entity = rb_entry(rb, struct drm_sched_entity, rb_tree_node);
-               if (drm_sched_entity_is_ready(entity)) {
-                       /* If we can't queue yet, preserve the current entity in
-                        * terms of fairness.
-                        */
-                       if (!drm_sched_can_queue(sched, entity)) {
-                               spin_unlock(&rq->lock);
-                               return ERR_PTR(-ENOSPC);
-                       }
-
-                       reinit_completion(&entity->entity_idle);
-                       break;
-               }
-       }
-       spin_unlock(&rq->lock);
-
-       return rb ? rb_entry(rb, struct drm_sched_entity, rb_tree_node) : NULL;
-}
-
 /**
  * drm_sched_run_job_queue - enqueue run-job work
  * @sched: scheduler instance
diff --git a/drivers/gpu/drm/scheduler/sched_rq.c b/drivers/gpu/drm/scheduler/sched_rq.c
new file mode 100644 (file)
index 0000000..a525bb5
--- /dev/null
@@ -0,0 +1,265 @@
+// SPDX-License-Identifier: MIT
+/* Copyright 2015 Advanced Micro Devices, Inc. */
+
+#include <linux/rbtree.h>
+
+#include <drm/drm_print.h>
+#include <drm/gpu_scheduler.h>
+
+#include "sched_internal.h"
+
+static __always_inline bool
+drm_sched_entity_compare_before(struct rb_node *a, const struct rb_node *b)
+{
+       struct drm_sched_entity *ea =
+               rb_entry((a), struct drm_sched_entity, rb_tree_node);
+       struct drm_sched_entity *eb =
+               rb_entry((b), struct drm_sched_entity, rb_tree_node);
+
+       return ktime_before(ea->oldest_job_waiting, eb->oldest_job_waiting);
+}
+
+static void drm_sched_rq_remove_fifo_locked(struct drm_sched_entity *entity,
+                                           struct drm_sched_rq *rq)
+{
+       if (!RB_EMPTY_NODE(&entity->rb_tree_node)) {
+               rb_erase_cached(&entity->rb_tree_node, &rq->rb_tree_root);
+               RB_CLEAR_NODE(&entity->rb_tree_node);
+       }
+}
+
+static void drm_sched_rq_update_fifo_locked(struct drm_sched_entity *entity,
+                                           struct drm_sched_rq *rq,
+                                           ktime_t ts)
+{
+       /*
+        * Both locks need to be grabbed, one to protect from entity->rq change
+        * for entity from within concurrent drm_sched_entity_select_rq and the
+        * other to update the rb tree structure.
+        */
+       lockdep_assert_held(&entity->lock);
+       lockdep_assert_held(&rq->lock);
+
+       drm_sched_rq_remove_fifo_locked(entity, rq);
+
+       entity->oldest_job_waiting = ts;
+
+       rb_add_cached(&entity->rb_tree_node, &rq->rb_tree_root,
+                     drm_sched_entity_compare_before);
+}
+
+/**
+ * drm_sched_rq_init - initialize a given run queue struct
+ * @sched: scheduler instance to associate with this run queue
+ * @rq: scheduler run queue
+ *
+ * Initializes a scheduler runqueue.
+ */
+void drm_sched_rq_init(struct drm_gpu_scheduler *sched,
+                      struct drm_sched_rq *rq)
+{
+       spin_lock_init(&rq->lock);
+       INIT_LIST_HEAD(&rq->entities);
+       rq->rb_tree_root = RB_ROOT_CACHED;
+       rq->sched = sched;
+}
+
+/**
+ * drm_sched_rq_add_entity - add an entity
+ * @entity: scheduler entity
+ * @ts: submission timestamp
+ *
+ * Adds a scheduler entity to the run queue.
+ *
+ * Return: DRM scheduler selected to handle this entity or NULL if entity has
+ * been stopped and cannot be submitted to.
+ */
+struct drm_gpu_scheduler *
+drm_sched_rq_add_entity(struct drm_sched_entity *entity, ktime_t ts)
+{
+       struct drm_gpu_scheduler *sched;
+       struct drm_sched_rq *rq;
+
+       /* Add the entity to the run queue */
+       spin_lock(&entity->lock);
+       if (entity->stopped) {
+               spin_unlock(&entity->lock);
+
+               DRM_ERROR("Trying to push to a killed entity\n");
+               return NULL;
+       }
+
+       rq = entity->rq;
+       spin_lock(&rq->lock);
+       sched = rq->sched;
+
+       if (list_empty(&entity->list)) {
+               atomic_inc(sched->score);
+               list_add_tail(&entity->list, &rq->entities);
+       }
+
+       if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
+               drm_sched_rq_update_fifo_locked(entity, rq, ts);
+
+       spin_unlock(&rq->lock);
+       spin_unlock(&entity->lock);
+
+       return sched;
+}
+
+/**
+ * drm_sched_rq_remove_entity - remove an entity
+ * @rq: scheduler run queue
+ * @entity: scheduler entity
+ *
+ * Removes a scheduler entity from the run queue.
+ */
+void drm_sched_rq_remove_entity(struct drm_sched_rq *rq,
+                               struct drm_sched_entity *entity)
+{
+       lockdep_assert_held(&entity->lock);
+
+       if (list_empty(&entity->list))
+               return;
+
+       spin_lock(&rq->lock);
+
+       atomic_dec(rq->sched->score);
+       list_del_init(&entity->list);
+
+       if (rq->current_entity == entity)
+               rq->current_entity = NULL;
+
+       if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
+               drm_sched_rq_remove_fifo_locked(entity, rq);
+
+       spin_unlock(&rq->lock);
+}
+
+/**
+ * drm_sched_rq_pop_entity - pops an entity
+ * @entity: scheduler entity
+ *
+ * To be called every time after a job is popped from the entity.
+ */
+void drm_sched_rq_pop_entity(struct drm_sched_entity *entity)
+{
+       /*
+        * Update the entity's location in the min heap according to
+        * the timestamp of the next job, if any.
+        */
+       if (drm_sched_policy == DRM_SCHED_POLICY_FIFO) {
+               struct drm_sched_job *next;
+
+               next = drm_sched_entity_queue_peek(entity);
+               if (next) {
+                       struct drm_sched_rq *rq;
+
+                       spin_lock(&entity->lock);
+                       rq = entity->rq;
+                       spin_lock(&rq->lock);
+                       drm_sched_rq_update_fifo_locked(entity, rq,
+                                                       next->submit_ts);
+                       spin_unlock(&rq->lock);
+                       spin_unlock(&entity->lock);
+               }
+       }
+}
+
+/**
+ * drm_sched_rq_select_entity_rr - Select an entity which could provide a job to run
+ *
+ * @sched: the gpu scheduler
+ * @rq: scheduler run queue to check.
+ *
+ * Try to find the next ready entity.
+ *
+ * Return an entity if one is found; return an error-pointer (!NULL) if an
+ * entity was ready, but the scheduler had insufficient credits to accommodate
+ * its job; return NULL, if no ready entity was found.
+ */
+struct drm_sched_entity *
+drm_sched_rq_select_entity_rr(struct drm_gpu_scheduler *sched,
+                             struct drm_sched_rq *rq)
+{
+       struct drm_sched_entity *entity;
+
+       spin_lock(&rq->lock);
+
+       entity = rq->current_entity;
+       if (entity) {
+               list_for_each_entry_continue(entity, &rq->entities, list) {
+                       if (drm_sched_entity_is_ready(entity))
+                               goto found;
+               }
+       }
+
+       list_for_each_entry(entity, &rq->entities, list) {
+               if (drm_sched_entity_is_ready(entity))
+                       goto found;
+
+               if (entity == rq->current_entity)
+                       break;
+       }
+
+       spin_unlock(&rq->lock);
+
+       return NULL;
+
+found:
+       if (!drm_sched_can_queue(sched, entity)) {
+               /*
+                * If scheduler cannot take more jobs signal the caller to not
+                * consider lower priority queues.
+                */
+               entity = ERR_PTR(-ENOSPC);
+       } else {
+               rq->current_entity = entity;
+               reinit_completion(&entity->entity_idle);
+       }
+
+       spin_unlock(&rq->lock);
+
+       return entity;
+}
+
+/**
+ * drm_sched_rq_select_entity_fifo - Select an entity which provides a job to run
+ *
+ * @sched: the gpu scheduler
+ * @rq: scheduler run queue to check.
+ *
+ * Find oldest waiting ready entity.
+ *
+ * Return an entity if one is found; return an error-pointer (!NULL) if an
+ * entity was ready, but the scheduler had insufficient credits to accommodate
+ * its job; return NULL, if no ready entity was found.
+ */
+struct drm_sched_entity *
+drm_sched_rq_select_entity_fifo(struct drm_gpu_scheduler *sched,
+                               struct drm_sched_rq *rq)
+{
+       struct rb_node *rb;
+
+       spin_lock(&rq->lock);
+       for (rb = rb_first_cached(&rq->rb_tree_root); rb; rb = rb_next(rb)) {
+               struct drm_sched_entity *entity;
+
+               entity = rb_entry(rb, struct drm_sched_entity, rb_tree_node);
+               if (drm_sched_entity_is_ready(entity)) {
+                       /* If we can't queue yet, preserve the current entity in
+                        * terms of fairness.
+                        */
+                       if (!drm_sched_can_queue(sched, entity)) {
+                               spin_unlock(&rq->lock);
+                               return ERR_PTR(-ENOSPC);
+                       }
+
+                       reinit_completion(&entity->entity_idle);
+                       break;
+               }
+       }
+       spin_unlock(&rq->lock);
+
+       return rb ? rb_entry(rb, struct drm_sched_entity, rb_tree_node) : NULL;
+}