[PATCH] drm/xe/guc: Silently discard stale G2H reply during overlap
Nishit Sharma <[email protected]>
| Newsgroups | org.freedesktop.lists.intel-xe |
|---|---|
| Message-ID | <[email protected]> |
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 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. 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 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) || + 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