[PATCH v4 11/13] drm/xe/hw_engine_group: Resume exec queues suspended by dma fence jobs
Matthew Brost
matthew.brost at intel.com
Mon Aug 5 20:32:55 UTC 2024
On Thu, Aug 01, 2024 at 02:56:52PM +0200, Francois Dugast wrote:
> Submission of a dma fence job leads to suspending the faulting long
> running exec queues of the hw engine group. Work is queued in the resume
> worker for this group and execution is resumed on the attached exec queues
> in faulting long running mode.
>
> This is another entry point for execution on the hw engine group so the
> execution mode is updated.
>
> v2: Kick the resume worker from exec IOCTL, switch to unordered workqueue,
> destroy it after use (Matt Brost)
>
> Signed-off-by: Francois Dugast <francois.dugast at intel.com>
> ---
> drivers/gpu/drm/xe/xe_exec.c | 3 ++
> drivers/gpu/drm/xe/xe_hw_engine_group.c | 46 ++++++++++++++++++++++++-
> drivers/gpu/drm/xe/xe_hw_engine_group.h | 1 +
> 3 files changed, 49 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/xe/xe_exec.c b/drivers/gpu/drm/xe/xe_exec.c
> index 2169fbf766d3..484acfbe0e61 100644
> --- a/drivers/gpu/drm/xe/xe_exec.c
> +++ b/drivers/gpu/drm/xe/xe_exec.c
> @@ -324,6 +324,9 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
> spin_unlock(&xe->ttm.lru_lock);
> }
>
> + if (mode == EXEC_MODE_LR)
> + xe_hw_engine_group_resume_faulting_lr_jobs(group);
> +
> err_repin:
> if (!xe_vm_in_lr_mode(vm))
> up_read(&vm->userptr.notifier_lock);
> diff --git a/drivers/gpu/drm/xe/xe_hw_engine_group.c b/drivers/gpu/drm/xe/xe_hw_engine_group.c
> index 16635f00c5f0..ca8b06df63f6 100644
> --- a/drivers/gpu/drm/xe/xe_hw_engine_group.c
> +++ b/drivers/gpu/drm/xe/xe_hw_engine_group.c
> @@ -17,9 +17,36 @@ hw_engine_group_free(struct drm_device *drm, void *arg)
> {
> struct xe_hw_engine_group *group = arg;
>
> + destroy_workqueue(group->resume_wq);
> kfree(group);
> }
>
> +static void
> +hw_engine_group_resume_lr_jobs_func(struct work_struct *w)
> +{
> + struct xe_exec_queue *q;
> + struct xe_hw_engine_group *group = container_of(w, struct xe_hw_engine_group, resume_work);
> + int err;
> + enum xe_hw_engine_group_execution_mode previous_mode;
> +
> + err = xe_hw_engine_group_get_mode(group, EXEC_MODE_LR, &previous_mode);
> + if (err)
> + return;
> +
> + if (previous_mode == EXEC_MODE_LR)
> + goto put;
> +
> + list_for_each_entry(q, &group->exec_queue_list, hw_engine_group_link) {
> + if (!xe_vm_in_fault_mode(q->vm))
> + continue;
> +
> + q->ops->resume(q);
> + }
> +
> +put:
> + xe_hw_engine_group_put(group);
> +}
> +
> static struct xe_hw_engine_group *
> hw_engine_group_alloc(struct xe_device *xe)
> {
> @@ -30,7 +57,12 @@ hw_engine_group_alloc(struct xe_device *xe)
> if (!group)
> return ERR_PTR(-ENOMEM);
>
> + group->resume_wq = alloc_workqueue("xe-resume-lr-jobs-wq", 0, 0);
> + if (!group->resume_wq)
> + return ERR_PTR(-ENOMEM);
> +
> init_rwsem(&group->mode_sem);
> + INIT_WORK(&group->resume_work, hw_engine_group_resume_lr_jobs_func);
> INIT_LIST_HEAD(&group->exec_queue_list);
>
> err = drmm_add_action_or_reset(&xe->drm, hw_engine_group_free, group);
> @@ -125,7 +157,7 @@ int xe_hw_engine_group_add_exec_queue(struct xe_hw_engine_group *group, struct x
> if (xe_vm_in_fault_mode(q->vm) && group->cur_mode == EXEC_MODE_DMA_FENCE) {
> q->ops->suspend(q);
> q->ops->suspend_wait(q);
> - queue_work(group->resume_wq, &group->resume_work);
> + xe_hw_engine_group_resume_faulting_lr_jobs(group);
> }
>
> list_add(&q->hw_engine_group_link, &group->exec_queue_list);
> @@ -151,6 +183,16 @@ void xe_hw_engine_group_del_exec_queue(struct xe_hw_engine_group *group, struct
> up_write(&group->mode_sem);
> }
>
> +/**
> + * xe_hw_engine_group_resume_faulting_lr_jobs() - Asynchronously resume the hw engine group's
> + * faulting LR jobs
> + * @group: The hw engine group
> + */
> +void xe_hw_engine_group_resume_faulting_lr_jobs(struct xe_hw_engine_group *group)
> +{
> + queue_work(group->resume_wq, &group->resume_work);
> +}
> +
> /**
> * xe_hw_engine_group_suspend_faulting_lr_jobs() - Suspend the faulting LR jobs of this group
> * @group: The hw engine group
> @@ -174,6 +216,8 @@ static void xe_hw_engine_group_suspend_faulting_lr_jobs(struct xe_hw_engine_grou
>
> q->ops->suspend_wait(q);
> }
> +
> + xe_hw_engine_group_resume_faulting_lr_jobs(group);
You are going to want to skip this call if none of the queues in the
group are in LR mode as this would needlessly queue the worker which
waits on dma-fences under a lock, serializing all dma-fence jovs in the
group. This is source of CI failure [1] too.
Matt
[1] https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-136192v5/bat-bmg-1/igt@xe_vm@bind-execqueues-independent.html
> }
>
> /**
> diff --git a/drivers/gpu/drm/xe/xe_hw_engine_group.h b/drivers/gpu/drm/xe/xe_hw_engine_group.h
> index 0f196c0ad98d..797ee81acbf2 100644
> --- a/drivers/gpu/drm/xe/xe_hw_engine_group.h
> +++ b/drivers/gpu/drm/xe/xe_hw_engine_group.h
> @@ -24,5 +24,6 @@ void xe_hw_engine_group_put(struct xe_hw_engine_group *group);
>
> enum xe_hw_engine_group_execution_mode
> xe_hw_engine_group_find_exec_mode(struct xe_exec_queue *q);
> +void xe_hw_engine_group_resume_faulting_lr_jobs(struct xe_hw_engine_group *group);
>
> #endif
> --
> 2.43.0
>
More information about the Intel-xe
mailing list