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/nouveau: Add new callback for scheduler teardown

There is a new callback for always tearing the scheduler down in a
leak-free, deadlock-free manner.

Port Nouveau as its first user by providing the scheduler with a
callback that ensures the fence context gets killed in drm_sched_fini().

Acked-by: Danilo Krummrich <dakr@kernel.org>
Signed-off-by: Philipp Stanner <phasta@kernel.org>
Link: https://lore.kernel.org/r/20250710125412.128476-9-phasta@kernel.org

+30 -1
+15
drivers/gpu/drm/nouveau/nouveau_fence.c
··· 240 240 return ret; 241 241 } 242 242 243 + void 244 + nouveau_fence_cancel(struct nouveau_fence *fence) 245 + { 246 + struct nouveau_fence_chan *fctx = nouveau_fctx(fence); 247 + unsigned long flags; 248 + 249 + spin_lock_irqsave(&fctx->lock, flags); 250 + if (!dma_fence_is_signaled_locked(&fence->base)) { 251 + dma_fence_set_error(&fence->base, -ECANCELED); 252 + if (nouveau_fence_signal(fence)) 253 + nvif_event_block(&fctx->event); 254 + } 255 + spin_unlock_irqrestore(&fctx->lock, flags); 256 + } 257 + 243 258 bool 244 259 nouveau_fence_done(struct nouveau_fence *fence) 245 260 {
+1
drivers/gpu/drm/nouveau/nouveau_fence.h
··· 29 29 30 30 int nouveau_fence_emit(struct nouveau_fence *); 31 31 bool nouveau_fence_done(struct nouveau_fence *); 32 + void nouveau_fence_cancel(struct nouveau_fence *fence); 32 33 int nouveau_fence_wait(struct nouveau_fence *, bool lazy, bool intr); 33 34 int nouveau_fence_sync(struct nouveau_bo *, struct nouveau_channel *, bool exclusive, bool intr); 34 35
+14 -1
drivers/gpu/drm/nouveau/nouveau_sched.c
··· 11 11 #include "nouveau_exec.h" 12 12 #include "nouveau_abi16.h" 13 13 #include "nouveau_sched.h" 14 + #include "nouveau_chan.h" 14 15 15 16 #define NOUVEAU_SCHED_JOB_TIMEOUT_MS 10000 16 17 ··· 394 393 nouveau_job_fini(job); 395 394 } 396 395 396 + static void 397 + nouveau_sched_cancel_job(struct drm_sched_job *sched_job) 398 + { 399 + struct nouveau_fence *fence; 400 + struct nouveau_job *job; 401 + 402 + job = to_nouveau_job(sched_job); 403 + fence = to_nouveau_fence(job->done_fence); 404 + 405 + nouveau_fence_cancel(fence); 406 + } 407 + 397 408 static const struct drm_sched_backend_ops nouveau_sched_ops = { 398 409 .run_job = nouveau_sched_run_job, 399 410 .timedout_job = nouveau_sched_timedout_job, 400 411 .free_job = nouveau_sched_free_job, 412 + .cancel_job = nouveau_sched_cancel_job, 401 413 }; 402 414 403 415 static int ··· 495 481 496 482 return 0; 497 483 } 498 - 499 484 500 485 static void 501 486 nouveau_sched_fini(struct nouveau_sched *sched)