[PATCH 5/8] drm/msm: Fix sched_prio inversion within a ring

From: Akhil P Oommen

Date: Sat Oct 24 2026 - 06:34:21 EST


From: Jie Zhang <jie.zhang@xxxxxxxxxxxxxxxx>

Commit 38f922a563aa ("drm/sched: Reverse run-queue priority enumeration")
reversed the values of each sched priority. But it didn't update
msm_gpu_convert_priority() to match the new order. This results in
incorrect sched priorities within a ring.

To fix this, remove the inversion logic and add an offset of
DRM_SCHED_PRIORITY_HIGH to keep the range within [HIGH..LOW], reserving
KERNEL for internal submissions.

Fixes: 38f922a563aa ("drm/sched: Reverse run-queue priority enumeration")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Jie Zhang <jie.zhang@xxxxxxxxxxxxxxxx>
Signed-off-by: Akhil P Oommen <akhilpo@xxxxxxxxxxxxxxxx>
---
drivers/gpu/drm/msm/msm_gpu.h | 24 ++++++++++--------------
drivers/gpu/drm/msm/msm_submitqueue.c | 2 +-
2 files changed, 11 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index d27d54bdb7a7..bc5b31eb1eca 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -522,17 +522,18 @@ msm_context_is_vmbind(struct msm_context *ctx)
* @sched_prio: [out] the gpu scheduler priority level which the userspace
* priority maps to
*
- * With drm/scheduler providing it's own level of prioritization, our total
+ * With drm/scheduler providing its own level of prioritization, our total
* number of available priority levels is (nr_rings * NR_SCHED_PRIORITIES).
- * Each ring is associated with it's own scheduler instance. However, our
- * UABI is that lower numerical values are higher priority. So mapping the
- * single userspace priority level into ring_nr and sched_prio takes some
- * care. The userspace provided priority (when a submitqueue is created)
- * is mapped to ring nr and scheduler priority as such:
+ * Each ring is associated with its own scheduler instance. Both the MSM
+ * UABI and drm/scheduler use lower-numeric = higher-priority, so the mapping
+ * from a single userspace priority level into ring_nr and sched_prio is:
*
* ring_nr = userspace_prio / NR_SCHED_PRIORITIES
- * sched_prio = NR_SCHED_PRIORITIES -
- * (userspace_prio % NR_SCHED_PRIORITIES) - 1
+ * sched_prio = (userspace_prio % NR_SCHED_PRIORITIES) + DRM_SCHED_PRIORITY_HIGH
+ *
+ * The offset by DRM_SCHED_PRIORITY_HIGH keeps the range within [HIGH..LOW],
+ * intentionally excluding DRM_SCHED_PRIORITY_KERNEL which is reserved for
+ * kernel-internal submissions.
*
* This allows generations without preemption (nr_rings==1) to have some
* amount of prioritization, and provides more priority levels for gens
@@ -547,16 +548,11 @@ static inline int msm_gpu_convert_priority(struct msm_gpu *gpu, int prio,

rn = div_u64_rem(prio, NR_SCHED_PRIORITIES, &sp);

- /* invert sched priority to map to higher-numeric-is-higher-
- * priority convention
- */
- sp = NR_SCHED_PRIORITIES - sp - 1;
-
if (rn >= gpu->nr_rings)
return -EINVAL;

*ring_nr = rn;
- *sched_prio = sp;
+ *sched_prio = sp + DRM_SCHED_PRIORITY_HIGH;

return 0;
}
diff --git a/drivers/gpu/drm/msm/msm_submitqueue.c b/drivers/gpu/drm/msm/msm_submitqueue.c
index d307cdd17d90..8d550d281704 100644
--- a/drivers/gpu/drm/msm/msm_submitqueue.c
+++ b/drivers/gpu/drm/msm/msm_submitqueue.c
@@ -136,7 +136,7 @@ get_sched_entity(struct msm_context *ctx, struct msm_ringbuffer *ring,
unsigned ring_nr, enum drm_sched_priority sched_prio)
{
static DEFINE_MUTEX(entity_lock);
- unsigned idx = (ring_nr * NR_SCHED_PRIORITIES) + sched_prio;
+ unsigned idx = (ring_nr * NR_SCHED_PRIORITIES) + (sched_prio - DRM_SCHED_PRIORITY_HIGH);

/* We should have already validated that the requested priority is
* valid by the time we get here.

--
2.55.0