Skip to content

Commit 3bd68b3

Browse files
drm/amdgpu: fix pipeline sync v2
This fixes a potential memory leak of dma_fence objects in the CS code as well as glitches in firefox because of missing pipeline sync. v2: use the scheduler instead of the fence context Signed-off-by: Christian König <[email protected]> Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/2323 Tested-by: Michal Kubecek [email protected] Tested-by: Vlastimil Babka <[email protected]> Acked-by: Alex Deucher <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent a309c71 commit 3bd68b3

File tree

1 file changed

+30
-16
lines changed

1 file changed

+30
-16
lines changed

drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p,
6161
amdgpu_ctx_put(p->ctx);
6262
return -ECANCELED;
6363
}
64+
65+
amdgpu_sync_create(&p->sync);
6466
return 0;
6567
}
6668

@@ -452,18 +454,6 @@ static int amdgpu_syncobj_lookup_and_add(struct amdgpu_cs_parser *p,
452454
}
453455

454456
r = amdgpu_sync_fence(&p->sync, fence);
455-
if (r)
456-
goto error;
457-
458-
/*
459-
* When we have an explicit dependency it might be necessary to insert a
460-
* pipeline sync to make sure that all caches etc are flushed and the
461-
* next job actually sees the results from the previous one.
462-
*/
463-
if (fence->context == p->gang_leader->base.entity->fence_context)
464-
r = amdgpu_sync_fence(&p->gang_leader->explicit_sync, fence);
465-
466-
error:
467457
dma_fence_put(fence);
468458
return r;
469459
}
@@ -1188,10 +1178,19 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
11881178
static int amdgpu_cs_sync_rings(struct amdgpu_cs_parser *p)
11891179
{
11901180
struct amdgpu_fpriv *fpriv = p->filp->driver_priv;
1181+
struct drm_gpu_scheduler *sched;
11911182
struct amdgpu_bo_list_entry *e;
1183+
struct dma_fence *fence;
11921184
unsigned int i;
11931185
int r;
11941186

1187+
r = amdgpu_ctx_wait_prev_fence(p->ctx, p->entities[p->gang_leader_idx]);
1188+
if (r) {
1189+
if (r != -ERESTARTSYS)
1190+
DRM_ERROR("amdgpu_ctx_wait_prev_fence failed.\n");
1191+
return r;
1192+
}
1193+
11951194
list_for_each_entry(e, &p->validated, tv.head) {
11961195
struct amdgpu_bo *bo = ttm_to_amdgpu_bo(e->tv.bo);
11971196
struct dma_resv *resv = bo->tbo.base.resv;
@@ -1211,10 +1210,24 @@ static int amdgpu_cs_sync_rings(struct amdgpu_cs_parser *p)
12111210
return r;
12121211
}
12131212

1214-
r = amdgpu_ctx_wait_prev_fence(p->ctx, p->entities[p->gang_leader_idx]);
1215-
if (r && r != -ERESTARTSYS)
1216-
DRM_ERROR("amdgpu_ctx_wait_prev_fence failed.\n");
1217-
return r;
1213+
sched = p->gang_leader->base.entity->rq->sched;
1214+
while ((fence = amdgpu_sync_get_fence(&p->sync))) {
1215+
struct drm_sched_fence *s_fence = to_drm_sched_fence(fence);
1216+
1217+
/*
1218+
* When we have an dependency it might be necessary to insert a
1219+
* pipeline sync to make sure that all caches etc are flushed and the
1220+
* next job actually sees the results from the previous one
1221+
* before we start executing on the same scheduler ring.
1222+
*/
1223+
if (!s_fence || s_fence->sched != sched)
1224+
continue;
1225+
1226+
r = amdgpu_sync_fence(&p->gang_leader->explicit_sync, fence);
1227+
if (r)
1228+
return r;
1229+
}
1230+
return 0;
12181231
}
12191232

12201233
static void amdgpu_cs_post_dependencies(struct amdgpu_cs_parser *p)
@@ -1347,6 +1360,7 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser)
13471360
{
13481361
unsigned i;
13491362

1363+
amdgpu_sync_free(&parser->sync);
13501364
for (i = 0; i < parser->num_post_deps; i++) {
13511365
drm_syncobj_put(parser->post_deps[i].syncobj);
13521366
kfree(parser->post_deps[i].chain);

0 commit comments

Comments
 (0)