Re: [PATCH] drm/xe/guc: Silently discard stale G2H reply during overlap

Matthew Brost <[email protected]>
Newsgroups org.freedesktop.lists.intel-xe
Message-ID <[email protected]>
On Fri, Aug 07, 2026 at 07:04:21AM +0000, Nishit Sharma wrote:
> When xe_force_gt_reset_async() fires a second reset before the first
> reset's post-recovery drain has completed, GuC may still be processing
> H2G requests (SCHED_CONTEXT_MODE_SET / DEREGISTER_CONTEXT) that were
> issued by the first reset. The G2H replies SCHED_DONE and DEREGISTER_DONE

We don't issue H2G as part of a GT reset. We stop the CTs, fixup
anything which is missing, and blow away anything in CTs when we
restart.

The relavent functions here are:

xe_guc_ct_stop()
guc_exec_queue_stop()
xe_guc_ct_start() 

> can then arrive after the KMD has already marked those exec queues as
> banned, killed, or wedged in response to the second reset.

> At that point the state flags that the reply handlers assert on
> have already been cleared, and the handlers treat this as a protocol
> violation, emitting an *ERROR* and returning -EPROTO.

We should not be recieving G2H after xe_guc_ct_stop() and then after we
internally mess the with the queue state in guc_exec_queue_stop().

> 
> This is not a real error. The reset path tears down exec queues
> independently of any in-flight G2H traffic, so a stale reply for a dead

No. G2H traffic is stopped in xe_guc_ct_stop() and any remaining
commands are squashed in xe_guc_ct_start().

Can you give an example of the failure you're trying to fix? This seems
to be a misdiagnosis.

> queue is harmless. The proper response is to discard it silently and let
> the reset-driven teardown proceed undisturbed.
> 
> Detect this condition by checking whether the queue is already in a
> terminal state (banned, killed, or wedged) before treating an unexpected
> G2H as a protocol error. If so, log at debug level and return success.
> 
> Signed-off-by: Nishit Sharma <[email protected]>
> ---
>  drivers/gpu/drm/xe/xe_guc_submit.c | 25 +++++++++++++++++++++++++
>  1 file changed, 25 insertions(+)
> 
> diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
> index 8aaed4fd13ea..988c236c6a03 100644
> --- a/drivers/gpu/drm/xe/xe_guc_submit.c
> +++ b/drivers/gpu/drm/xe/xe_guc_submit.c
> @@ -3149,6 +3149,19 @@ int xe_guc_sched_done_handler(struct xe_guc *guc, u32 *msg, u32 len)
>  
>  	if (unlikely(!exec_queue_pending_enable(q) &&
>  		     !exec_queue_pending_disable(q))) {
> +		/*
> +		 * Stale SCHED_DONE from a prior reset cycle: the reset marked
> +		 * the queue banned/killed (clearing the pending flags) before
> +		 * GuC's reply landed. Discard silently
> +		 */
> +		if (exec_queue_banned(q) || exec_queue_killed(q) ||

"Killed" is 100% the wrong term here. We kill queues during a user queue
close or FD close without triggering a GT reset, and the normal firmware
protocol flows are expected to continue working with 100% accuracy or a
bunch of things leak.

wedged, banned also look wrong too - see above.

Matt

> +		    exec_queue_wedged(q)) {
> +			xe_gt_dbg(guc_to_gt(guc),
> +				  "SCHED_DONE: Stale G2H guc_id=%d, state=0x%04x\n",
> +				  q->guc->id, atomic_read(&q->guc->state));
> +			return 0;
> +		}
> +
>  		xe_gt_err(guc_to_gt(guc),
>  			  "SCHED_DONE: Unexpected engine state 0x%04x, guc_id=%d, runnable_state=%u",
>  			  atomic_read(&q->guc->state), q->guc->id,
> @@ -3185,6 +3198,18 @@ int xe_guc_deregister_done_handler(struct xe_guc *guc, u32 *msg, u32 len)
>  
>  	if (!exec_queue_destroyed(q) || exec_queue_pending_disable(q) ||
>  	    exec_queue_pending_enable(q) || exec_queue_enabled(q)) {
> +		 /*
> +		  * DEREGISTER_DONE from a prior reset cycle
> +		  * Discard silently
> +		  */
> +		if (exec_queue_banned(q) || exec_queue_killed(q) ||
> +		    exec_queue_wedged(q)) {
> +			xe_gt_dbg(guc_to_gt(guc),
> +				  "DEREGISTER_DONE: Stale G2H guc_id=%d, state=0x%04x\n",
> +				  q->guc->id, atomic_read(&q->guc->state));
> +			return 0;
> +		}
> +
>  		xe_gt_err(guc_to_gt(guc),
>  			  "DEREGISTER_DONE: Unexpected engine state 0x%04x, guc_id=%d",
>  			  atomic_read(&q->guc->state), q->guc->id);
> -- 
> 2.43.0
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.