Intel-XE Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Raag Jadav" <raag.jadav@intel.com>, intel-xe@lists.freedesktop.org
Subject: Re: [PATCH v12 1/9] drm/xe/gt: Use GT ordered workqueue for wedging
Date: Mon, 19 Oct 2026 03:18:13 +0000	[thread overview]
Message-ID: <sashiko-outbox-176560@kernel.org> (raw)
In-Reply-To: <20261019023708.128835-2-raag.jadav@intel.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] drm/xe/gt: deadlock on gt->ordered_wq by deferring xe_guc_reset_prepare()
- [High] drm/xe/gt: race in xe_gt_init() leaves GT unwedged on early device wedge
--

commit 2f995deb3d90153d398aa4de2fcfe846b423203b
Author: Raag Jadav <raag.jadav@intel.com>

drm/xe/gt: Use GT ordered workqueue for wedging

This commit defers GT wedge teardown to a worker queued on the GT ordered
workqueue and introduces for_each_initialized_gt() to skip uninitialized
GTs when wedging the device.

> diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c
> index bc9bf6f0b5a79..2ed67fe929e34 100644
> --- a/drivers/gpu/drm/xe/xe_gt.c
> +++ b/drivers/gpu/drm/xe/xe_gt.c

[ ... ]

> @@ -768,7 +774,7 @@ int xe_gt_init(struct xe_gt *gt)
>  
>  	err = gt_init_with_all_forcewake(gt);
>  	if (err) {
> -		gt_reset_worker_disable(gt);
> +		gt_worker_disable(gt);
>  		return err;
>  	}
>  
> @@ -784,6 +790,8 @@ int xe_gt_init(struct xe_gt *gt)
>  			return err;
>  	}
>  
> +	/* Must be last */
> +	WRITE_ONCE(gt->initialized, true);
>  	return 0;
>  }

[Severity: High]
Can setting gt->initialized only at the end of xe_gt_init() cause a GT to
be left unwedged if xe_device_declare_wedged() runs while xe_gt_init() is
still in progress?

In xe_device_probe(), xe_irq_install() runs before the xe_gt_init() loop,
enabling top-level interrupts (such as xe_mert_irq_handler(),
xe_hw_error_irq_handler(), and xe_sysctrl_irq_handler()) and error workers
like csc_hw_error_work. Inside xe_gt_init(), gt_init_with_gt_forcewake()
and gt_init_with_all_forcewake() initialize GuC CT, GuC submission,
gt->tlb_inval, and the migration exec queue, enable GuC communication, and
submit GPU jobs via emit_job_sync() in xe_gt_record_default_lrcs(), all
while gt->initialized is still false.

If xe_device_declare_wedged() is called during this window (from an IRQ or
error worker, from another GT on a multi-GT device, or from a job timeout
or reset failure during xe_gt_record_default_lrcs()):

    xe_device_declare_wedged()
        atomic_xchg(&xe->wedged.flag, 1);
        for_each_initialized_gt(gt, xe, id)
            xe_gt_declare_wedged(gt);

for_each_initialized_gt() skips the GT currently inside xe_gt_init()
because gt->initialized is still false. Once xe->wedged.flag is set,
g2h_read() and __guc_ct_send_locked() reject all GuC CT traffic with
-ENOTRECOVERABLE, but xe_gt_declare_wedged() is never queued for this GT to
abort pending GuC CT requests, TLB invalidation fences, or kernel exec
queues. Furthermore, if xe_gt_init() finishes concurrently with an
asynchronous wedge event, it sets gt->initialized = true without checking
xe_device_wedged(xe), leaving the GT active and unwedged on a wedged
device.

> @@ -1204,6 +1212,15 @@ struct xe_hw_engine *xe_gt_any_hw_engine(struct xe_gt *gt)
>  	return NULL;
>  }
>  
> +static void gt_wedge_worker(struct work_struct *w)
> +{
> +	struct xe_gt *gt = container_of(w, typeof(*gt), wedge.worker);
> +
> +	xe_uc_declare_wedged(&gt->uc);
> +	xe_tlb_inval_reset(&gt->tlb_inval);
> +	xe_pm_runtime_put(gt_to_xe(gt));
> +}
> +
>  /**
>   * xe_gt_declare_wedged() - Declare GT wedged
>   * @gt: the GT object
> @@ -1213,8 +1230,11 @@ struct xe_hw_engine *xe_gt_any_hw_engine(struct xe_gt *gt)
>   */
>  void xe_gt_declare_wedged(struct xe_gt *gt)
>  {
> -	xe_gt_assert(gt, gt_to_xe(gt)->wedged.mode);
> +	struct xe_device *xe = gt_to_xe(gt);
>  
> -	xe_uc_declare_wedged(&gt->uc);
> -	xe_tlb_inval_reset(&gt->tlb_inval);
> +	xe_gt_assert(gt, xe->wedged.mode);
> +
> +	xe_pm_runtime_get_noresume(xe);
> +	if (!queue_work(gt->ordered_wq, &gt->wedge.worker))
> +		xe_pm_runtime_put(xe);
>  }

[Severity: High]
Does deferring xe_uc_reset_prepare() to gt_wedge_worker() risk a deadlock
and 5-second TDR timeouts on gt->ordered_wq?

When xe_device_declare_wedged() sets xe->wedged.flag, g2h_read() and
__guc_ct_send_locked() immediately begin returning -ENOTRECOVERABLE:

drivers/gpu/drm/xe/xe_guc_ct.c:g2h_read() {
    ...
    if (xe_device_wedged(xe))
        return -ENOTRECOVERABLE;
    ...
}

Unlike xe_gt_reset_async(), which calls xe_uc_reset_prepare(&gt->uc) ->
xe_guc_reset_prepare(guc) synchronously before queueing gt->reset.worker on
gt->ordered_wq, xe_gt_declare_wedged() now defers
xe_uc_declare_wedged(&gt->uc) -> xe_guc_declare_wedged(&uc->guc) ->
xe_guc_reset_prepare(guc) (which sets guc->submission_state.stopped and
wakes guc->ct.wq) to gt_wedge_worker() on gt->ordered_wq.

If an exec queue is processing a SUSPEND message on sched->work_process_msg
while q->guc->resume_time == RESUME_PENDING or exec_queue_pending_disable(q)
is true, __guc_exec_queue_process_msg_suspend() blocks in an unbounded
wait:

drivers/gpu/drm/xe/xe_guc_submit.c:__guc_exec_queue_process_msg_suspend() {
    ...
    wait_event(guc->ct.wq, vf_recovery(guc) ||
               ((q->guc->resume_time != RESUME_PENDING ||
               xe_guc_read_stopped(guc)) && !exec_queue_pending_disable(q)));
    ...
}

Because g2h_read() is blocked by xe_device_wedged(xe), handle_sched_done()
cannot run to clear RESUME_PENDING or PENDING_DISABLE, so work_process_msg
can only wake when xe_guc_read_stopped(guc) becomes true. If
guc_exec_queue_timedout_job() is running on gt->ordered_wq ahead of
gt->wedge.worker, it calls:

    guc_exec_queue_timedout_job()
        xe_sched_submission_stop(sched)
            cancel_work_sync(&sched->work_process_msg);

This blocks gt->ordered_wq waiting for work_process_msg, while
work_process_msg waits on guc->ct.wq for gt_wedge_worker() to set
xe_guc_read_stopped(guc), and gt_wedge_worker() cannot run because it is
queued behind guc_exec_queue_timedout_job() on the single-threaded
gt->ordered_wq.

Even without a concurrent SUSPEND message, when
guc_exec_queue_timedout_job() runs on gt->ordered_wq while xe->wedged.flag
is set, its wait_event_timeout(guc->ct.wq, ..., HZ * 5) calls for pending
enable/disable or G2H receive neither G2H nor xe_guc_read_stopped(guc),
stalling gt->ordered_wq for 5 seconds before taking a spurious devcoredump
and scheduling a GT reset.

Should xe_gt_declare_wedged() call xe_uc_reset_prepare(&gt->uc)
synchronously before queueing gt->wedge.worker, matching
xe_gt_reset_async()?

([ ... ])

 base-commit: 2efb7a11f1aa4d2dc285fe2680cca22cb9f72f64
-- 
2.51.2

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261019023708.128835-1-raag.jadav@intel.com?part=1

  reply	other threads:[~2026-10-19  3:18 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-19  2:36 [PATCH v12 0/9] Introduce xe_wedge Raag Jadav
2026-10-19  2:36 ` [PATCH v12 1/9] drm/xe/gt: Use GT ordered workqueue for wedging Raag Jadav
2026-10-19  3:18   ` sashiko-bot [this message]
2026-10-19  2:36 ` [PATCH v12 2/9] drm/xe: Drop xe_device_set_wedged_method() Raag Jadav
2026-10-19  2:36 ` [PATCH v12 3/9] drm/xe/hw_error: Guard csc_hw_error_work() with runtime PM Raag Jadav
2026-10-19  2:36 ` [PATCH v12 4/9] drm/xe: Move xe_device_wedged_fini() registration to xe_device_probe_early() Raag Jadav
2026-10-19  2:36 ` [PATCH v12 5/9] drm/xe: Make xe_device_declare_wedged() IRQ safe Raag Jadav
2026-10-19  2:36 ` [PATCH v12 6/9] drm/xe/pci_error: Flush GT wedge worker before bus reset Raag Jadav
2026-10-19  2:36 ` [PATCH v12 7/9] drm/xe/amc: Guard xe_amc_work() with runtime PM Raag Jadav
2026-10-19  2:36 ` [PATCH v12 8/9] drm/xe: Introduce xe_wedge Raag Jadav
2026-10-19  2:36 ` [PATCH v12 9/9] drm/xe/ras: Move xe_ras_process_errors() to xe_ras Raag Jadav
2026-10-19  2:48   ` sashiko-bot
2026-10-19  7:18 ` ✗ CI.checkpatch: warning for Introduce xe_wedge (rev11) Patchwork
2026-10-19  7:20 ` ✓ CI.KUnit: success " Patchwork
2026-10-19  8:01 ` ✓ Xe.CI.BAT: " Patchwork
2026-10-19  9:27 ` ✗ Xe.CI.FULL: failure " Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-176560@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=intel-xe@lists.freedesktop.org \
    --cc=raag.jadav@intel.com \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox