Sometimes drivers need to be able to submit multiple jobs which depend on each other to different schedulers at the same time, but using drm_sched_job_add_dependency() can't fail any more after the first job is initialized.
This function preallocate memory for dependency slots so that no ENOMEM can come later while adding dependencies. v2: rework implementation an documentation v3: rework from scratch, use separate function to add preallocated deps Signed-off-by: Christian König <christian.koe...@amd.com> --- drivers/gpu/drm/scheduler/sched_main.c | 45 ++++++++++++++++++++++++++ include/drm/gpu_scheduler.h | 4 +++ 2 files changed, 49 insertions(+) diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c index f7118497e47a..b95e7089aa70 100644 --- a/drivers/gpu/drm/scheduler/sched_main.c +++ b/drivers/gpu/drm/scheduler/sched_main.c @@ -858,6 +858,51 @@ void drm_sched_job_arm(struct drm_sched_job *job) } EXPORT_SYMBOL(drm_sched_job_arm); +/** + * drm_sched_job_prealloc_dependency_slot - avoid ENOMEM on adding dependencies + * @job: scheduler job where dependencies will be added + * @id: id for the allocated slot + * + * Sometimes drivers need to be able to submit multiple jobs which depend on + * each other to different schedulers at the same time, but using + * drm_sched_job_add_dependency() can't fail any more after the first job is + * initialized. + * + * This function preallocate memory for a dependency slot so that no ENOMEM can + * come later while adding dependencies. The index of the preallocated slot is + * returned in @id. + * + * Return: + * 0 on success, or an error on failing to expand the array. + */ +int drm_sched_job_prealloc_dependency_slot(struct drm_sched_job *job, + u32 *id) +{ + return xa_alloc(&job->dependencies, id, NULL, xa_limit_32b, GFP_KERNEL); +} +EXPORT_SYMBOL(drm_sched_job_prealloc_dependency_slot); + +/** + * drm_sched_job_add_prealloc_dep - add dependency to preallocated slot + * @job: scheduler job where dependencies will be added + * @id: the preallocated slot index + * @fence: the dependency to add + * + * Consumes @fence and adds it to the preallocated slot dependency. + */ +void drm_sched_job_add_prealloc_dep(struct drm_sched_job *job, u32 id, + struct dma_fence *fence) +{ + fence = xa_store(&job->dependencies, id, fence, GFP_ATOMIC); + /* + * Be defensive just in case driver messed it up and used preallocated + * slot twice. + */ + if (WARN_ON(fence)) + dma_fence_put(fence); +} +EXPORT_SYMBOL(drm_sched_job_add_prealloc_dep); + /** * drm_sched_job_add_dependency - adds the fence as a job dependency * @job: scheduler job to add the dependencies to diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h index d860db087ea5..0286e0934317 100644 --- a/include/drm/gpu_scheduler.h +++ b/include/drm/gpu_scheduler.h @@ -632,6 +632,10 @@ int drm_sched_job_init(struct drm_sched_job *job, u32 credits, void *owner); void drm_sched_job_arm(struct drm_sched_job *job); void drm_sched_entity_push_job(struct drm_sched_job *sched_job); +int drm_sched_job_prealloc_dependency_slot(struct drm_sched_job *job, + u32 *id); +void drm_sched_job_add_prealloc_dep(struct drm_sched_job *job, u32 id, + struct dma_fence *fence); int drm_sched_job_add_dependency(struct drm_sched_job *job, struct dma_fence *fence); int drm_sched_job_add_syncobj_dependency(struct drm_sched_job *job, -- 2.34.1