mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git
synced 2026-04-25 00:52:45 -04:00
drm/sched: Document run_job() refcount hazard
drm_sched_backend_ops.run_job() returns a dma_fence for the scheduler. That fence is signalled by the driver once the hardware completed the associated job. The scheduler does not increment the reference count on that fence, but implicitly expects to inherit this fence from run_job(). This is relatively subtle and prone to misunderstandings. This implies that, to keep a reference for itself, a driver needs to call dma_fence_get() in addition to dma_fence_init() in that callback. It's further complicated by the fact that the scheduler even decrements the refcount in drm_sched_run_job_work() since it created a new reference in drm_sched_fence_scheduled(). It does, however, still use its pointer to the fence after calling dma_fence_put() - which is safe because of the aforementioned new reference, but actually still violates the refcounting rules. Move the call to dma_fence_put() to the position behind the last usage of the fence. Suggested-by: Danilo Krummrich <dakr@kernel.org> Signed-off-by: Philipp Stanner <pstanner@redhat.com> Reviewed-by: Danilo Krummrich <dakr@kernel.org> Signed-off-by: Philipp Stanner <phasta@kernel.org> Link: https://patchwork.freedesktop.org/patch/msgid/20250305130551.136682-4-phasta@kernel.org
This commit is contained in:
committed by
Philipp Stanner
parent
87edca6261
commit
72ebc18b34
@@ -1220,20 +1220,23 @@ static void drm_sched_run_job_work(struct work_struct *w)
|
||||
drm_sched_job_begin(sched_job);
|
||||
|
||||
trace_drm_run_job(sched_job, entity);
|
||||
/*
|
||||
* The run_job() callback must by definition return a fence whose
|
||||
* refcount has been incremented for the scheduler already.
|
||||
*/
|
||||
fence = sched->ops->run_job(sched_job);
|
||||
complete_all(&entity->entity_idle);
|
||||
drm_sched_fence_scheduled(s_fence, fence);
|
||||
|
||||
if (!IS_ERR_OR_NULL(fence)) {
|
||||
/* Drop for original kref_init of the fence */
|
||||
dma_fence_put(fence);
|
||||
|
||||
r = dma_fence_add_callback(fence, &sched_job->cb,
|
||||
drm_sched_job_done_cb);
|
||||
if (r == -ENOENT)
|
||||
drm_sched_job_done(sched_job, fence->error);
|
||||
else if (r)
|
||||
DRM_DEV_ERROR(sched->dev, "fence add callback failed (%d)\n", r);
|
||||
|
||||
dma_fence_put(fence);
|
||||
} else {
|
||||
drm_sched_job_done(sched_job, IS_ERR(fence) ?
|
||||
PTR_ERR(fence) : 0);
|
||||
|
||||
Reference in New Issue
Block a user