Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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 <christian.koenig@amd.com>
Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/2323
Tested-by: Michal Kubecek mkubecek@suse.cz
Tested-by: Vlastimil Babka <vbabka@suse.cz>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230109130120.73389-1-christian.koenig@amd.com

+30 -16
+30 -16
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
··· 61 61 amdgpu_ctx_put(p->ctx); 62 62 return -ECANCELED; 63 63 } 64 + 65 + amdgpu_sync_create(&p->sync); 64 66 return 0; 65 67 } 66 68 ··· 454 452 } 455 453 456 454 r = amdgpu_sync_fence(&p->sync, fence); 457 - if (r) 458 - goto error; 459 - 460 - /* 461 - * When we have an explicit dependency it might be necessary to insert a 462 - * pipeline sync to make sure that all caches etc are flushed and the 463 - * next job actually sees the results from the previous one. 464 - */ 465 - if (fence->context == p->gang_leader->base.entity->fence_context) 466 - r = amdgpu_sync_fence(&p->gang_leader->explicit_sync, fence); 467 - 468 - error: 469 455 dma_fence_put(fence); 470 456 return r; 471 457 } ··· 1178 1188 static int amdgpu_cs_sync_rings(struct amdgpu_cs_parser *p) 1179 1189 { 1180 1190 struct amdgpu_fpriv *fpriv = p->filp->driver_priv; 1191 + struct drm_gpu_scheduler *sched; 1181 1192 struct amdgpu_bo_list_entry *e; 1193 + struct dma_fence *fence; 1182 1194 unsigned int i; 1183 1195 int r; 1196 + 1197 + r = amdgpu_ctx_wait_prev_fence(p->ctx, p->entities[p->gang_leader_idx]); 1198 + if (r) { 1199 + if (r != -ERESTARTSYS) 1200 + DRM_ERROR("amdgpu_ctx_wait_prev_fence failed.\n"); 1201 + return r; 1202 + } 1184 1203 1185 1204 list_for_each_entry(e, &p->validated, tv.head) { 1186 1205 struct amdgpu_bo *bo = ttm_to_amdgpu_bo(e->tv.bo); ··· 1210 1211 return r; 1211 1212 } 1212 1213 1213 - r = amdgpu_ctx_wait_prev_fence(p->ctx, p->entities[p->gang_leader_idx]); 1214 - if (r && r != -ERESTARTSYS) 1215 - DRM_ERROR("amdgpu_ctx_wait_prev_fence failed.\n"); 1216 - return r; 1214 + sched = p->gang_leader->base.entity->rq->sched; 1215 + while ((fence = amdgpu_sync_get_fence(&p->sync))) { 1216 + struct drm_sched_fence *s_fence = to_drm_sched_fence(fence); 1217 + 1218 + /* 1219 + * When we have an dependency it might be necessary to insert a 1220 + * pipeline sync to make sure that all caches etc are flushed and the 1221 + * next job actually sees the results from the previous one 1222 + * before we start executing on the same scheduler ring. 1223 + */ 1224 + if (!s_fence || s_fence->sched != sched) 1225 + continue; 1226 + 1227 + r = amdgpu_sync_fence(&p->gang_leader->explicit_sync, fence); 1228 + if (r) 1229 + return r; 1230 + } 1231 + return 0; 1217 1232 } 1218 1233 1219 1234 static void amdgpu_cs_post_dependencies(struct amdgpu_cs_parser *p) ··· 1360 1347 { 1361 1348 unsigned i; 1362 1349 1350 + amdgpu_sync_free(&parser->sync); 1363 1351 for (i = 0; i < parser->num_post_deps; i++) { 1364 1352 drm_syncobj_put(parser->post_deps[i].syncobj); 1365 1353 kfree(parser->post_deps[i].chain);