Skip to content

Commit 6800246

Browse files
committed
drm/msm: One sched entity per process per priority
Some userspace apps make assumptions that rendering against multiple contexts within the same process (from the same thread, with appropriate MakeCurrent() calls) provides sufficient synchronization without any external synchronization (ie. glFenceSync()/glWaitSync()). Since a submitqueue maps to a gl/vk context, having multiple sched entities of the same priority only works with implicit sync enabled. To fix this, limit things to a single sched entity per priority level per process. An alternative would be sharing submitqueues between contexts in userspace, but tracking of per-context faults (ie. GL_EXT_robustness) is already done at the submitqueue level, so this is not an option. Signed-off-by: Rob Clark <robdclark@chromium.org>
1 parent 4cd82aa commit 6800246

3 files changed

Lines changed: 75 additions & 21 deletions

File tree

drivers/gpu/drm/msm/msm_gem_submit.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev,
4646
if (!submit)
4747
return ERR_PTR(-ENOMEM);
4848

49-
ret = drm_sched_job_init(&submit->base, &queue->entity, queue);
49+
ret = drm_sched_job_init(&submit->base, queue->entity, queue);
5050
if (ret) {
5151
kfree(submit);
5252
return ERR_PTR(ret);
@@ -907,7 +907,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
907907
/* The scheduler owns a ref now: */
908908
msm_gem_submit_get(submit);
909909

910-
drm_sched_entity_push_job(&submit->base, &queue->entity);
910+
drm_sched_entity_push_job(&submit->base, queue->entity);
911911

912912
args->fence = submit->fence_id;
913913

drivers/gpu/drm/msm/msm_gpu.h

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,19 @@ struct msm_file_private {
275275
struct msm_gem_address_space *aspace;
276276
struct kref ref;
277277
int seqno;
278+
279+
/**
280+
* entities:
281+
*
282+
* Table of per-priority-level sched entities used by submitqueues
283+
* associated with this &drm_file. Because some userspace apps
284+
* make assumptions about rendering from multiple gl contexts
285+
* (of the same priority) within the process happening in FIFO
286+
* order without requiring any fencing beyond MakeCurrent(), we
287+
* create at most one &drm_sched_entity per-process per-priority-
288+
* level.
289+
*/
290+
struct drm_sched_entity *entities[NR_SCHED_PRIORITIES * MSM_GPU_MAX_RINGS];
278291
};
279292

280293
/**
@@ -355,7 +368,7 @@ struct msm_gpu_submitqueue {
355368
struct idr fence_idr;
356369
struct mutex lock;
357370
struct kref ref;
358-
struct drm_sched_entity entity;
371+
struct drm_sched_entity *entity;
359372
};
360373

361374
struct msm_gpu_state_bo {
@@ -456,14 +469,7 @@ void msm_submitqueue_close(struct msm_file_private *ctx);
456469

457470
void msm_submitqueue_destroy(struct kref *kref);
458471

459-
static inline void __msm_file_private_destroy(struct kref *kref)
460-
{
461-
struct msm_file_private *ctx = container_of(kref,
462-
struct msm_file_private, ref);
463-
464-
msm_gem_address_space_put(ctx->aspace);
465-
kfree(ctx);
466-
}
472+
void __msm_file_private_destroy(struct kref *kref);
467473

468474
static inline void msm_file_private_put(struct msm_file_private *ctx)
469475
{

drivers/gpu/drm/msm/msm_submitqueue.c

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,31 @@
77

88
#include "msm_gpu.h"
99

10+
void __msm_file_private_destroy(struct kref *kref)
11+
{
12+
struct msm_file_private *ctx = container_of(kref,
13+
struct msm_file_private, ref);
14+
int i;
15+
16+
for (i = 0; i < ARRAY_SIZE(ctx->entities); i++) {
17+
if (!ctx->entities[i])
18+
continue;
19+
20+
drm_sched_entity_destroy(ctx->entities[i]);
21+
kfree(ctx->entities[i]);
22+
}
23+
24+
msm_gem_address_space_put(ctx->aspace);
25+
kfree(ctx);
26+
}
27+
1028
void msm_submitqueue_destroy(struct kref *kref)
1129
{
1230
struct msm_gpu_submitqueue *queue = container_of(kref,
1331
struct msm_gpu_submitqueue, ref);
1432

1533
idr_destroy(&queue->fence_idr);
1634

17-
drm_sched_entity_destroy(&queue->entity);
18-
1935
msm_file_private_put(queue->ctx);
2036

2137
kfree(queue);
@@ -61,13 +77,47 @@ void msm_submitqueue_close(struct msm_file_private *ctx)
6177
}
6278
}
6379

80+
static struct drm_sched_entity *
81+
get_sched_entity(struct msm_file_private *ctx, struct msm_ringbuffer *ring,
82+
unsigned ring_nr, enum drm_sched_priority sched_prio)
83+
{
84+
static DEFINE_MUTEX(entity_lock);
85+
unsigned idx = (ring_nr * NR_SCHED_PRIORITIES) + sched_prio;
86+
87+
/* We should have already validated that the requested priority is
88+
* valid by the time we get here.
89+
*/
90+
if (WARN_ON(idx >= ARRAY_SIZE(ctx->entities)))
91+
return ERR_PTR(-EINVAL);
92+
93+
mutex_lock(&entity_lock);
94+
95+
if (!ctx->entities[idx]) {
96+
struct drm_sched_entity *entity;
97+
struct drm_gpu_scheduler *sched = &ring->sched;
98+
int ret;
99+
100+
entity = kzalloc(sizeof(*ctx->entities[idx]), GFP_KERNEL);
101+
102+
ret = drm_sched_entity_init(entity, sched_prio, &sched, 1, NULL);
103+
if (ret) {
104+
kfree(entity);
105+
return ERR_PTR(ret);
106+
}
107+
108+
ctx->entities[idx] = entity;
109+
}
110+
111+
mutex_unlock(&entity_lock);
112+
113+
return ctx->entities[idx];
114+
}
115+
64116
int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx,
65117
u32 prio, u32 flags, u32 *id)
66118
{
67119
struct msm_drm_private *priv = drm->dev_private;
68120
struct msm_gpu_submitqueue *queue;
69-
struct msm_ringbuffer *ring;
70-
struct drm_gpu_scheduler *sched;
71121
enum drm_sched_priority sched_prio;
72122
unsigned ring_nr;
73123
int ret;
@@ -91,12 +141,10 @@ int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx,
91141
queue->flags = flags;
92142
queue->ring_nr = ring_nr;
93143

94-
ring = priv->gpu->rb[ring_nr];
95-
sched = &ring->sched;
96-
97-
ret = drm_sched_entity_init(&queue->entity,
98-
sched_prio, &sched, 1, NULL);
99-
if (ret) {
144+
queue->entity = get_sched_entity(ctx, priv->gpu->rb[ring_nr],
145+
ring_nr, sched_prio);
146+
if (IS_ERR(queue->entity)) {
147+
ret = PTR_ERR(queue->entity);
100148
kfree(queue);
101149
return ret;
102150
}

0 commit comments

Comments
 (0)