Skip to content

Commit fc40e5e

Browse files
committed
drm/msm: Utilize gpu scheduler priorities
The drm/scheduler provides additional prioritization on top of that provided by however many number of ringbuffers (each with their own priority level) is supported on a given generation. Expose the additional levels of priority to userspace and map the userspace priority back to ring (first level of priority) and schedular priority (additional priority levels within the ring). Signed-off-by: Rob Clark <[email protected]> Acked-by: Christian König <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Rob Clark <[email protected]>
1 parent e3e24ee commit fc40e5e

File tree

5 files changed

+88
-27
lines changed

5 files changed

+88
-27
lines changed

drivers/gpu/drm/msm/adreno/adreno_gpu.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,8 +261,8 @@ int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value)
261261
return ret;
262262
}
263263
return -EINVAL;
264-
case MSM_PARAM_NR_RINGS:
265-
*value = gpu->nr_rings;
264+
case MSM_PARAM_PRIORITIES:
265+
*value = gpu->nr_rings * NR_SCHED_PRIORITIES;
266266
return 0;
267267
case MSM_PARAM_PP_PGTABLE:
268268
*value = 0;

drivers/gpu/drm/msm/msm_gem_submit.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev,
5959
submit->gpu = gpu;
6060
submit->cmd = (void *)&submit->bos[nr_bos];
6161
submit->queue = queue;
62-
submit->ring = gpu->rb[queue->prio];
62+
submit->ring = gpu->rb[queue->ring_nr];
6363
submit->fault_dumped = false;
6464

6565
INIT_LIST_HEAD(&submit->node);
@@ -749,7 +749,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
749749
/* Get a unique identifier for the submission for logging purposes */
750750
submitid = atomic_inc_return(&ident) - 1;
751751

752-
ring = gpu->rb[queue->prio];
752+
ring = gpu->rb[queue->ring_nr];
753753
trace_msm_gpu_submit(pid_nr(pid), ring->id, submitid,
754754
args->nr_bos, args->nr_cmds);
755755

drivers/gpu/drm/msm/msm_gpu.h

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,14 +250,68 @@ struct msm_gpu_perfcntr {
250250
const char *name;
251251
};
252252

253+
/*
254+
* The number of priority levels provided by drm gpu scheduler. The
255+
* DRM_SCHED_PRIORITY_KERNEL priority level is treated specially in some
256+
* cases, so we don't use it (no need for kernel generated jobs).
257+
*/
258+
#define NR_SCHED_PRIORITIES (1 + DRM_SCHED_PRIORITY_HIGH - DRM_SCHED_PRIORITY_MIN)
259+
260+
/**
261+
* msm_gpu_convert_priority - Map userspace priority to ring # and sched priority
262+
*
263+
* @gpu: the gpu instance
264+
* @prio: the userspace priority level
265+
* @ring_nr: [out] the ringbuffer the userspace priority maps to
266+
* @sched_prio: [out] the gpu scheduler priority level which the userspace
267+
* priority maps to
268+
*
269+
* With drm/scheduler providing it's own level of prioritization, our total
270+
* number of available priority levels is (nr_rings * NR_SCHED_PRIORITIES).
271+
* Each ring is associated with it's own scheduler instance. However, our
272+
* UABI is that lower numerical values are higher priority. So mapping the
273+
* single userspace priority level into ring_nr and sched_prio takes some
274+
* care. The userspace provided priority (when a submitqueue is created)
275+
* is mapped to ring nr and scheduler priority as such:
276+
*
277+
* ring_nr = userspace_prio / NR_SCHED_PRIORITIES
278+
* sched_prio = NR_SCHED_PRIORITIES -
279+
* (userspace_prio % NR_SCHED_PRIORITIES) - 1
280+
*
281+
* This allows generations without preemption (nr_rings==1) to have some
282+
* amount of prioritization, and provides more priority levels for gens
283+
* that do have preemption.
284+
*/
285+
static inline int msm_gpu_convert_priority(struct msm_gpu *gpu, int prio,
286+
unsigned *ring_nr, enum drm_sched_priority *sched_prio)
287+
{
288+
unsigned rn, sp;
289+
290+
rn = div_u64_rem(prio, NR_SCHED_PRIORITIES, &sp);
291+
292+
/* invert sched priority to map to higher-numeric-is-higher-
293+
* priority convention
294+
*/
295+
sp = NR_SCHED_PRIORITIES - sp - 1;
296+
297+
if (rn >= gpu->nr_rings)
298+
return -EINVAL;
299+
300+
*ring_nr = rn;
301+
*sched_prio = sp;
302+
303+
return 0;
304+
}
305+
253306
/**
254307
* A submitqueue is associated with a gl context or vk queue (or equiv)
255308
* in userspace.
256309
*
257310
* @id: userspace id for the submitqueue, unique within the drm_file
258311
* @flags: userspace flags for the submitqueue, specified at creation
259312
* (currently unusued)
260-
* @prio: the submitqueue priority
313+
* @ring_nr: the ringbuffer used by this submitqueue, which is determined
314+
* by the submitqueue's priority
261315
* @faults: the number of GPU hangs associated with this submitqueue
262316
* @ctx: the per-drm_file context associated with the submitqueue (ie.
263317
* which set of pgtables do submits jobs associated with the
@@ -272,7 +326,7 @@ struct msm_gpu_perfcntr {
272326
struct msm_gpu_submitqueue {
273327
int id;
274328
u32 flags;
275-
u32 prio;
329+
u32 ring_nr;
276330
int faults;
277331
struct msm_file_private *ctx;
278332
struct list_head node;

drivers/gpu/drm/msm/msm_submitqueue.c

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx,
6868
struct msm_gpu_submitqueue *queue;
6969
struct msm_ringbuffer *ring;
7070
struct drm_gpu_scheduler *sched;
71+
enum drm_sched_priority sched_prio;
72+
unsigned ring_nr;
7173
int ret;
7274

7375
if (!ctx)
@@ -76,8 +78,9 @@ int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx,
7678
if (!priv->gpu)
7779
return -ENODEV;
7880

79-
if (prio >= priv->gpu->nr_rings)
80-
return -EINVAL;
81+
ret = msm_gpu_convert_priority(priv->gpu, prio, &ring_nr, &sched_prio);
82+
if (ret)
83+
return ret;
8184

8285
queue = kzalloc(sizeof(*queue), GFP_KERNEL);
8386

@@ -86,24 +89,13 @@ int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx,
8689

8790
kref_init(&queue->ref);
8891
queue->flags = flags;
89-
queue->prio = prio;
92+
queue->ring_nr = ring_nr;
9093

91-
ring = priv->gpu->rb[prio];
94+
ring = priv->gpu->rb[ring_nr];
9295
sched = &ring->sched;
9396

94-
/*
95-
* TODO we can allow more priorities than we have ringbuffers by
96-
* mapping:
97-
*
98-
* ring = prio / 3;
99-
* ent_prio = DRM_SCHED_PRIORITY_MIN + (prio % 3);
100-
*
101-
* Probably avoid using DRM_SCHED_PRIORITY_KERNEL as that is
102-
* treated specially in places.
103-
*/
10497
ret = drm_sched_entity_init(&queue->entity,
105-
DRM_SCHED_PRIORITY_NORMAL,
106-
&sched, 1, NULL);
98+
sched_prio, &sched, 1, NULL);
10799
if (ret) {
108100
kfree(queue);
109101
return ret;
@@ -134,16 +126,19 @@ int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx,
134126
int msm_submitqueue_init(struct drm_device *drm, struct msm_file_private *ctx)
135127
{
136128
struct msm_drm_private *priv = drm->dev_private;
137-
int default_prio;
129+
int default_prio, max_priority;
138130

139131
if (!priv->gpu)
140132
return -ENODEV;
141133

134+
max_priority = (priv->gpu->nr_rings * NR_SCHED_PRIORITIES) - 1;
135+
142136
/*
143-
* Select priority 2 as the "default priority" unless nr_rings is less
144-
* than 2 and then pick the lowest priority
137+
* Pick a medium priority level as default. Lower numeric value is
138+
* higher priority, so round-up to pick a priority that is not higher
139+
* than the middle priority level.
145140
*/
146-
default_prio = clamp_t(uint32_t, 2, 0, priv->gpu->nr_rings - 1);
141+
default_prio = DIV_ROUND_UP(max_priority, 2);
147142

148143
INIT_LIST_HEAD(&ctx->submitqueues);
149144

include/uapi/drm/msm_drm.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,19 @@ struct drm_msm_timespec {
7373
#define MSM_PARAM_MAX_FREQ 0x04
7474
#define MSM_PARAM_TIMESTAMP 0x05
7575
#define MSM_PARAM_GMEM_BASE 0x06
76-
#define MSM_PARAM_NR_RINGS 0x07
76+
#define MSM_PARAM_PRIORITIES 0x07 /* The # of priority levels */
7777
#define MSM_PARAM_PP_PGTABLE 0x08 /* => 1 for per-process pagetables, else 0 */
7878
#define MSM_PARAM_FAULTS 0x09
7979
#define MSM_PARAM_SUSPENDS 0x0a
8080

81+
/* For backwards compat. The original support for preemption was based on
82+
* a single ring per priority level so # of priority levels equals the #
83+
* of rings. With drm/scheduler providing additional levels of priority,
84+
* the number of priorities is greater than the # of rings. The param is
85+
* renamed to better reflect this.
86+
*/
87+
#define MSM_PARAM_NR_RINGS MSM_PARAM_PRIORITIES
88+
8189
struct drm_msm_param {
8290
__u32 pipe; /* in, MSM_PIPE_x */
8391
__u32 param; /* in, MSM_PARAM_x */
@@ -304,6 +312,10 @@ struct drm_msm_gem_madvise {
304312

305313
#define MSM_SUBMITQUEUE_FLAGS (0)
306314

315+
/*
316+
* The submitqueue priority should be between 0 and MSM_PARAM_PRIORITIES-1,
317+
* a lower numeric value is higher priority.
318+
*/
307319
struct drm_msm_submitqueue {
308320
__u32 flags; /* in, MSM_SUBMITQUEUE_x */
309321
__u32 prio; /* in, Priority level */

0 commit comments

Comments
 (0)