Intel-XE Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Matthew Brost <matthew.brost@intel.com>
To: "Tales A. Mendonça" <talesam@gmail.com>
Cc: <intel-xe@lists.freedesktop.org>,
	<dri-devel@lists.freedesktop.org>,
	<thomas.hellstrom@linux.intel.com>, <rodrigo.vivi@intel.com>
Subject: Re: [PATCH v1 3/4] drm/xe/guc/ct: Queue G2H worker before flushing it in timeout paths
Date: Wed, 22 Jul 2026 15:03:26 -0700	[thread overview]
Message-ID: <amE+Ltrb8qKNKWd2@gsse-cloud1.jf.intel.com> (raw)
In-Reply-To: <amExusdY0Qhs3LIx@gsse-cloud1.jf.intel.com>

On Wed, Jul 22, 2026 at 02:10:18PM -0700, Matthew Brost wrote:
> On Tue, Jul 21, 2026 at 09:46:53PM -0300, Tales A. Mendonça wrote:
> > Timeout-recovery paths flush the G2H worker to pick up a response that
> > may have been posted by the GuC but not yet processed:
> > 
> >  - guc_ct_send_recv() after the 1s wait for a G2H response fails
> >  - the TLB invalidation backend's .flush() hook, called by
> >    xe_tlb_inval_fence_timeout() before declaring a fence timed out
> > 
> > However flush_work() on a work item that is neither queued nor running
> > is a no-op. If the GUC2HOST interrupt for the response was lost or
> 
> GUC2HOST messages getting lost are a different issue and would be
> catastrophic for a variety of reasons. I'd like to dig into that if it
> occurs on a POR platform (i.e., LNL+).
> 
> > coalesced, the G2H worker was never queued: the flush does not read the
> > G2H CTB and the response sits there unprocessed until an unrelated G2H
> > interrupt arrives. For TLB invalidations this results in
> > 
> >   TLB invalidation fence timeout, seqno=N recv=N-1
> > 
> > with the fence force-signalled with -ETIME even though the ack may
> > already be present in the CTB. Observed sporadically on ARL-H under CPU
> > load, always with recv == seqno - 1 and self-recovering on the next G2H
> > interrupt, which is consistent with a lost wakeup rather than a
> > GuC-side failure.
> > 
> > Add xe_guc_ct_flush_g2h(), which queues the worker before flushing it,
> > guaranteeing the flush always drains the CTB, and use it in both
> > timeout paths. A spurious worker run is safe: g2h_read() returns no
> > data under fast_lock, and receive_g2h() copes with runtime-PM state and
> > disabled CT communication.
> > 
> > After this change the fence-timeout error only fires when the ack is
> > genuinely absent from the CTB, making the message a reliable indicator
> > of a GuC-side stall.
> > 
> > Signed-off-by: Tales A. Mendonça <talesam@gmail.com>
> > ---
> >  drivers/gpu/drm/xe/xe_guc_ct.c        | 23 ++++++++++++++++++++++-
> >  drivers/gpu/drm/xe/xe_guc_ct.h        |  1 +
> >  drivers/gpu/drm/xe/xe_guc_tlb_inval.c |  2 +-
> >  3 files changed, 24 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/xe/xe_guc_ct.c b/drivers/gpu/drm/xe/xe_guc_ct.c
> > index fe70c0fd85c..11a05c2b8c7 100644
> > --- a/drivers/gpu/drm/xe/xe_guc_ct.c
> > +++ b/drivers/gpu/drm/xe/xe_guc_ct.c
> > @@ -1377,7 +1377,7 @@ static int guc_ct_send_recv(struct xe_guc_ct *ct, const u32 *action, u32 len,
> >  wait_again:
> >  	ret = wait_event_timeout(ct->g2h_fence_wq, READ_ONCE(g2h_fence.done), HZ);
> >  	if (!ret) {
> > -		LNL_FLUSH_WORK(&ct->g2h_worker);
> > +		xe_guc_ct_flush_g2h(ct);
> >  		if (READ_ONCE(g2h_fence.done)) {
> >  			xe_gt_warn(gt, "G2H fence %u, action %04x, done\n",
> >  				   g2h_fence.seqno, action[0]);
> > @@ -2046,6 +2046,27 @@ static void g2h_worker_func(struct work_struct *w)
> >  	receive_g2h(ct);
> >  }
> >  
> > +/**
> > + * xe_guc_ct_flush_g2h() - Force processing of pending G2H messages
> > + * @ct: GuC CT object
> > + *
> > + * The GUC2HOST interrupt for a G2H message may be lost or coalesced. When
> > + * that happens the G2H worker is never queued and flushing it is a no-op
> > + * that does not read the G2H CTB, leaving messages the GuC has already
> > + * posted unprocessed until the next interrupt arrives. Queue the worker
> > + * before flushing it so the flush always drains the G2H CTB. A spurious
> > + * worker run is safe: it returns without side effects if the CTB is empty
> > + * or CT communication is disabled.
> > + */
> > +void xe_guc_ct_flush_g2h(struct xe_guc_ct *ct)
> > +{
> > +	if (!xe_guc_ct_enabled(ct))
> > +		return;
> > +
> > +	queue_work(ct->g2h_wq, &ct->g2h_worker);
> 
> If the original queued work gets lost or is never submitted, then there
> is a bug somewhere else in the kernel, as mentioned above.
> 
> As for the flush part, yes, it's possible that this could take a while
> if the scheduler goes out to lunch, but it shouldn't happen with a
> sufficiently large timeout. Have you tried making the GuC CT worker high
> priority? We could also consider making the G2H handlers RT once those
> land upstream.
> 
> In general, I'm quite unhappy with the existing LNL_FLUSH_WORK, and we
> never determined the root cause of the original issue. In retrospect, we
> probably should never have merged that code. Looking at it now, the LNL
> flush code isn't even scoped to LNL, which makes this even worse than I
> initially thought, as it can paper over bugs. I'm going to post a patch
> to scope the existing workaround to LNL and earlier platforms (or maybe
> just removing it completely) and see what happens in our CI over the
> next several months before it makes its way into a kernel release.
> 
> With that said, the patch as proposed is a no from me. If you want to
> pursue my suggestion of scoping this change to LNL and earlier
> platforms, we can discuss that separately.

This is roughly what I had in mind:

https://patchwork.freedesktop.org/series/170939/

Compile tested only, so if you could give it try and see what pops up, I
think that would be helpful. Fell free to use the code in anyway and
give me feedback.

Matt

> 
> Matt
> 
> > +	flush_work(&ct->g2h_worker);
> > +}
> > +
> >  static struct xe_guc_ct_snapshot *guc_ct_snapshot_alloc(struct xe_guc_ct *ct, bool atomic,
> >  							bool want_ctb)
> >  {
> > diff --git a/drivers/gpu/drm/xe/xe_guc_ct.h b/drivers/gpu/drm/xe/xe_guc_ct.h
> > index 767365a33de..4e0338953f1 100644
> > --- a/drivers/gpu/drm/xe/xe_guc_ct.h
> > +++ b/drivers/gpu/drm/xe/xe_guc_ct.h
> > @@ -22,6 +22,7 @@ void xe_guc_ct_runtime_suspend(struct xe_guc_ct *ct);
> >  void xe_guc_ct_stop(struct xe_guc_ct *ct);
> >  void xe_guc_ct_flush_and_stop(struct xe_guc_ct *ct);
> >  void xe_guc_ct_fast_path(struct xe_guc_ct *ct);
> > +void xe_guc_ct_flush_g2h(struct xe_guc_ct *ct);
> >  
> >  struct xe_guc_ct_snapshot *xe_guc_ct_snapshot_capture(struct xe_guc_ct *ct);
> >  void xe_guc_ct_snapshot_print(struct xe_guc_ct_snapshot *snapshot, struct drm_printer *p);
> > diff --git a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
> > index 046d0655122..91960dc4ba9 100644
> > --- a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
> > +++ b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
> > @@ -327,7 +327,7 @@ static void tlb_inval_flush(struct xe_tlb_inval *tlb_inval)
> >  {
> >  	struct xe_guc *guc = tlb_inval->private;
> >  
> > -	LNL_FLUSH_WORK(&guc->ct.g2h_worker);
> > +	xe_guc_ct_flush_g2h(&guc->ct);
> >  }
> >  
> >  static long tlb_inval_timeout_delay(struct xe_tlb_inval *tlb_inval)
> > -- 
> > 2.55.0
> > 

  reply	other threads:[~2026-07-22 22:03 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-22  0:46 [PATCH v1 0/4] drm/xe: MCR semaphore and TLB invalidation timeout fixes for ARL Tales A. Mendonça
2026-07-22  0:46 ` [PATCH v1 1/4] drm/xe/mcr: Keep GT forcewake during MCR steering Tales A. Mendonça
2026-07-22 17:45   ` Tales A. Mendonça
2026-07-22 18:10   ` Matt Roper
2026-07-22 18:39     ` Tales A. Mendonça
2026-07-22  0:46 ` [PATCH v1 2/4] drm/xe/mcr: Sanitize steering semaphore on GT resume Tales A. Mendonça
2026-07-22 17:47   ` Tales A. Mendonça
2026-07-22  0:46 ` [PATCH v1 3/4] drm/xe/guc/ct: Queue G2H worker before flushing it in timeout paths Tales A. Mendonça
2026-07-22 17:48   ` Tales A. Mendonça
2026-07-22 21:10   ` Matthew Brost
2026-07-22 22:03     ` Matthew Brost [this message]
2026-07-22 23:28       ` Tales A. Mendonça
2026-07-22  0:46 ` [PATCH v1 4/4] drm/xe: Raise hw_tlb_timeout to cover observed GuC ack latency Tales A. Mendonça
2026-07-22 17:27 ` ✗ LGCI.VerificationFailed: failure for drm/xe: MCR semaphore and TLB invalidation timeout fixes for ARL 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=amE+Ltrb8qKNKWd2@gsse-cloud1.jf.intel.com \
    --to=matthew.brost@intel.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=intel-xe@lists.freedesktop.org \
    --cc=rodrigo.vivi@intel.com \
    --cc=talesam@gmail.com \
    --cc=thomas.hellstrom@linux.intel.com \
    /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