linux-next: manual merge of the drm tree with the drm-misc-fixes tree
From: Mark Brown
Date: Wed Aug 12 2026 - 08:53:40 EST
Hi all,
Today's linux-next merge of the drm tree got a conflict in:
drivers/gpu/drm/scheduler/sched_entity.c
between commits:
67cf83ac8316a ("Revert "drm/sched: Embed run queue singleton into the scheduler"")
from the drm-misc-fixes tree and commit:
2df5efb45425b ("drm/sched: Remove redundant entity->rq initialization and checks")
from the drm tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
diff --combined drivers/gpu/drm/scheduler/sched_entity.c
index 672b5c57ed8e9,c51101ec70c16..0000000000000
--- a/drivers/gpu/drm/scheduler/sched_entity.c
+++ b/drivers/gpu/drm/scheduler/sched_entity.c
@@@ -129,43 -129,14 +129,42 @@@ int drm_sched_entity_init(struct drm_sc
return -ENOMEM;
INIT_LIST_HEAD(&entity->list);
- entity->rq = NULL;
entity->guilty = guilty;
entity->priority = priority;
entity->last_user = current->group_leader;
+ entity->rq_priority = drm_sched_policy == DRM_SCHED_POLICY_FAIR ?
+ DRM_SCHED_PRIORITY_KERNEL : priority;
entity->num_sched_list = num_sched_list;
entity->sched_list = num_sched_list > 1 ? sched_list : NULL;
- entity->rq = &sched_list[0]->rq;
RCU_INIT_POINTER(entity->last_scheduled, NULL);
RB_CLEAR_NODE(&entity->rb_tree_node);
+
+ if (!sched_list[0]->sched_rq) {
+ /* Since every entry covered by num_sched_list
+ * should be non-NULL and therefore we warn drivers
+ * not to do this and to fix their DRM calling order.
+ */
+ pr_warn("%s: called with uninitialized scheduler\n", __func__);
+ } else {
+ enum drm_sched_priority p = entity->priority;
+
+ /*
+ * The "priority" of an entity cannot exceed the number of
+ * run-queues of a scheduler. Protect against num_rqs being 0,
+ * by converting to signed. Choose the lowest priority
+ * available.
+ */
+ if (p >= sched_list[0]->num_user_rqs) {
+ dev_err(sched_list[0]->dev, "entity with out-of-bounds priority:%u num_user_rqs:%u\n",
+ p, sched_list[0]->num_user_rqs);
+ p = max_t(s32,
+ (s32)sched_list[0]->num_user_rqs - 1,
+ (s32)DRM_SCHED_PRIORITY_KERNEL);
+ entity->priority = p;
+ }
+ entity->rq = sched_list[0]->sched_rq[entity->rq_priority];
+ }
+
init_completion(&entity->entity_idle);
/* We start in an idle state. */
@@@ -308,9 -279,6 +307,6 @@@ void drm_sched_entity_kill(struct drm_s
struct drm_sched_job *job;
struct dma_fence *prev;
- if (!entity->rq)
- return;
-
spin_lock(&entity->lock);
entity->stopped = true;
drm_sched_rq_remove_entity(entity->rq, entity);
@@@ -357,14 -325,11 +353,11 @@@ EXPORT_SYMBOL(drm_sched_entity_kill)
*/
long drm_sched_entity_flush(struct drm_sched_entity *entity, long timeout)
{
- struct drm_gpu_scheduler *sched;
+ struct drm_gpu_scheduler *sched =
+ container_of(entity->rq, typeof(*sched), rq);
struct task_struct *last_user;
long ret = timeout;
- if (!entity->rq)
- return 0;
-
- sched = entity->rq->sched;
/*
* The client will not queue more jobs during this fini - consume
* existing queued ones, or discard them on SIGKILL.
@@@ -445,10 -410,12 +438,10 @@@ static void drm_sched_entity_wakeup(str
{
struct drm_sched_entity *entity =
container_of(cb, struct drm_sched_entity, cb);
- struct drm_gpu_scheduler *sched =
- container_of(entity->rq, typeof(*sched), rq);
entity->dependency = NULL;
dma_fence_put(f);
- drm_sched_wakeup(sched);
+ drm_sched_wakeup(entity->rq->sched);
}
/**
@@@ -475,7 -442,8 +468,7 @@@ EXPORT_SYMBOL(drm_sched_entity_set_prio
static bool drm_sched_entity_add_dependency_cb(struct drm_sched_entity *entity,
struct drm_sched_job *sched_job)
{
- struct drm_gpu_scheduler *sched =
- container_of(entity->rq, typeof(*sched), rq);
+ struct drm_gpu_scheduler *sched = entity->rq->sched;
struct dma_fence *fence = entity->dependency;
struct drm_sched_fence *s_fence;
@@@ -609,7 -577,7 +602,7 @@@ void drm_sched_entity_select_rq(struct
spin_lock(&entity->lock);
sched = drm_sched_pick_best(entity->sched_list, entity->num_sched_list);
- rq = sched ? &sched->rq : NULL;
+ rq = sched ? sched->sched_rq[entity->rq_priority] : NULL;
if (rq != entity->rq) {
drm_sched_rq_remove_entity(entity->rq, entity);
entity->rq = rq;
@@@ -633,8 -601,9 +626,8 @@@
void drm_sched_entity_push_job(struct drm_sched_job *sched_job)
{
struct drm_sched_entity *entity = sched_job->entity;
- struct drm_gpu_scheduler *sched =
- container_of(entity->rq, typeof(*sched), rq);
bool first;
+ ktime_t submit_ts;
trace_drm_sched_job_queue(sched_job, entity);
@@@ -645,22 -614,18 +638,22 @@@
xa_for_each(&sched_job->dependencies, index, entry)
trace_drm_sched_job_add_dep(sched_job, entry);
}
- atomic_inc(sched->score);
+ atomic_inc(entity->rq->sched->score);
WRITE_ONCE(entity->last_user, current->group_leader);
/*
* After the sched_job is pushed into the entity queue, it may be
* completed and freed up at any time. We can no longer access it.
+ * Make sure to set the submit_ts first, to avoid a race.
*/
+ sched_job->submit_ts = submit_ts = ktime_get();
first = spsc_queue_push(&entity->job_queue, &sched_job->queue_node);
/* first job wakes up scheduler */
if (first) {
- sched = drm_sched_rq_add_entity(entity);
+ struct drm_gpu_scheduler *sched;
+
+ sched = drm_sched_rq_add_entity(entity, submit_ts);
if (sched)
drm_sched_wakeup(sched);
}
Attachment:
signature.asc
Description: PGP signature