Re: [PATCH v2 1/4] drm/xe: split VF pause into prepare and revert phases

Matthew Brost <[email protected]> Mon, 3 Aug 2026 09:55:19 -0700
Newsgroups org.freedesktop.lists.intel-xe
Message-ID <[email protected]>
On Fri, Jul 31, 2026 at 04:26:24PM -0700, Niranjana Vishwanathapura wrote:
> Extract xe_sched_submission_stop() + cancel_delayed_work_sync() into a
> new guc_exec_queue_pause_prepare() helper, then call it in a first pass
> over all queues before the existing revert loop in
> xe_guc_submit_pause_vf().
> 
> In a multi-queue group a secondary's run_job() can register the primary
> queue, which must not race an in-progress revert of a sibling queue.
> Stopping every scheduler before reverting any queue prevents that race.
> 
> No functional change outside the VF migration path.
> 
> Assisted-by: Github-Copilot:Claude-opus-4.8
> Signed-off-by: Niranjana Vishwanathapura <[email protected]>

Reviewed-by: Matthew Brost <[email protected]>

> ---
>  drivers/gpu/drm/xe/xe_guc_submit.c | 26 +++++++++++++++++++++++---
>  1 file changed, 23 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
> index 8aaed4fd13ea..314747336fb9 100644
> --- a/drivers/gpu/drm/xe/xe_guc_submit.c
> +++ b/drivers/gpu/drm/xe/xe_guc_submit.c
> @@ -2737,17 +2737,24 @@ static void lrc_parallel_clear(struct xe_lrc *lrc)
>   * during VF resume flows. The function scans the queue state, make adjustments
>   * as needed, and queues jobs / messages which replayed upon unpause.
>   */
> -static void guc_exec_queue_pause(struct xe_guc *guc, struct xe_exec_queue *q)
> +static void guc_exec_queue_pause_prepare(struct xe_guc *guc, struct xe_exec_queue *q)
>  {
>  	struct xe_gpu_scheduler *sched = &q->guc->sched;
> -	struct xe_sched_job *job;
> -	int i;
>  
>  	lockdep_assert_held(&guc->submission_state.lock);
>  
>  	/* Stop scheduling + flush any DRM scheduler operations */
>  	xe_sched_submission_stop(sched);
>  	cancel_delayed_work_sync(&sched->base.work_tdr);
> +}
> +
> +static void guc_exec_queue_pause(struct xe_guc *guc, struct xe_exec_queue *q)
> +{
> +	struct xe_gpu_scheduler *sched = &q->guc->sched;
> +	struct xe_sched_job *job;
> +	int i;
> +
> +	lockdep_assert_held(&guc->submission_state.lock);
>  
>  	guc_exec_queue_revert_pending_state_change(guc, q);
>  
> @@ -2806,6 +2813,19 @@ void xe_guc_submit_pause_vf(struct xe_guc *guc)
>  	xe_gt_assert(guc_to_gt(guc), vf_recovery(guc));
>  
>  	mutex_lock(&guc->submission_state.lock);
> +	/*
> +	 * Stop all schedulers before reverting any queue: in a multi-queue
> +	 * group a secondary's run_job() can register the primary, which must
> +	 * not race an in-progress revert.
> +	 */
> +	xa_for_each(&guc->submission_state.exec_queue_lookup, index, q) {
> +		/* Prevent redundant attempts to stop parallel queues */
> +		if (q->guc->id != index)
> +			continue;
> +
> +		guc_exec_queue_pause_prepare(guc, q);
> +	}
> +
>  	xa_for_each(&guc->submission_state.exec_queue_lookup, index, q) {
>  		/* Prevent redundant attempts to stop parallel queues */
>  		if (q->guc->id != index)
> -- 
> 2.43.0
>