linux-rt-devel.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
From: "Ville Syrjälä" <ville.syrjala@linux.intel.com>
To: Maarten Lankhorst <dev@lankhorst.se>
Cc: intel-gfx@lists.freedesktop.org, intel-xe@lists.freedesktop.org,
	linux-rt-devel@lists.linux.dev,
	Mario Kleiner <mario.kleiner.de@gmail.com>,
	Mike Galbraith <umgwanakikbuti@gmail.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	Sebastian Andrzej Siewior <bigeasy@linutronix.de>,
	Clark Williams <clrkwllms@kernel.org>,
	Steven Rostedt <rostedt@goodmis.org>
Subject: Re: [PATCH v2 4/7] drm/i915/display: Remove locking from intel_vblank_evade critical section
Date: Wed, 26 Nov 2025 23:17:39 +0200	[thread overview]
Message-ID: <aSduc2bC343FF3rk@intel.com> (raw)
In-Reply-To: <20251104083634.670753-5-dev@lankhorst.se>

On Tue, Nov 04, 2025 at 09:36:28AM +0100, Maarten Lankhorst wrote:
> finish_wait() may take a lock, which means that it can take any amount
> of time. On PREEMPT-RT we should not be taking any lock after disabling
> preemption, so ensure that the completion is done before disabling
> interrupts.
> 
> This also has the benefit of making vblank evasion more deterministic,
> by performing the final vblank check after all locking is done.
> 
> Signed-off-by: Maarten Lankhorst <dev@lankhorst.se>
> ---
>  drivers/gpu/drm/i915/display/intel_vblank.c | 35 ++++++++++-----------
>  1 file changed, 17 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_vblank.c b/drivers/gpu/drm/i915/display/intel_vblank.c
> index 2b106ffa3f5f5..3628d2a1b8f38 100644
> --- a/drivers/gpu/drm/i915/display/intel_vblank.c
> +++ b/drivers/gpu/drm/i915/display/intel_vblank.c
> @@ -708,6 +708,13 @@ void intel_vblank_evade_init(const struct intel_crtc_state *old_crtc_state,
>  		evade->min -= vblank_delay;
>  }
>  
> +static inline int vblank_evadable(struct intel_vblank_evade_ctx *evade, int *scanline)

The name is confusing. But having a function
would be nice since we need two checks I guess.
scanline_is_safe() or something?

Also type should be bool, and inline looks pointless.

> +{
> +	*scanline = intel_get_crtc_scanline(evade->crtc);
> +
> +	return *scanline < evade->min || *scanline > evade->max;
> +}
> +
>  /* must be called with vblank interrupt already enabled! */
>  int intel_vblank_evade(struct intel_vblank_evade_ctx *evade)
>  {
> @@ -715,23 +722,22 @@ int intel_vblank_evade(struct intel_vblank_evade_ctx *evade)
>  	struct intel_display *display = to_intel_display(crtc);
>  	long timeout = msecs_to_jiffies_timeout(1);
>  	wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
> -	DEFINE_WAIT(wait);
>  	int scanline;
>  
>  	if (evade->min <= 0 || evade->max <= 0)
>  		return 0;
>  
> -	for (;;) {
> -		/*
> -		 * prepare_to_wait() has a memory barrier, which guarantees
> -		 * other CPUs can see the task state update by the time we
> -		 * read the scanline.
> -		 */
> -		prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
> +	while (!vblank_evadable(evade, &scanline)) {
> +		local_irq_enable();
>  
> -		scanline = intel_get_crtc_scanline(crtc);
> -		if (scanline < evade->min || scanline > evade->max)
> -			break;
> +		DEFINE_WAIT(wait);
> +		while (!vblank_evadable(evade, &scanline) && timeout > 0) {
> +			prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
> +			timeout = schedule_timeout(timeout);
> +		}
> +		finish_wait(wq, &wait);
> +
> +		local_irq_disable();
>  
>  		if (!timeout) {

This looks to introduce the classic "didn't check the
condition after timeout" race.

I guess what you're going for is something like this (done
through a somewhat less intrusive reordering of the current
code):

for (;;) {
	if (scanline_is_safe(evade, &scanline))
		break;

	if (!timeout) {
		drm_dbg_kms(display->drm,
			    "Potential atomic update failure on pipe %c\n",
			    pipe_name(crtc->pipe));
		break;
	}

	local_irq_enable();

	prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);

	if (!scanline_is_safe(evade, &scanline))
		timeout = schedule_timeout(timeout);

	finish_wait(wq, &wait);

	local_irq_disable();
}

And then maybe the whole prepare+wait+finish thing there
could be a simple wait_event_timeout(). That would make
that inner thing a loop though. We might not want that
just because jiffies is so coarse and we don't really
want to wait multiple times there.

>  			drm_dbg_kms(display->drm,
> @@ -740,15 +746,8 @@ int intel_vblank_evade(struct intel_vblank_evade_ctx *evade)
>  			break;
>  		}
>  
> -		local_irq_enable();
> -
> -		timeout = schedule_timeout(timeout);
> -
> -		local_irq_disable();
>  	}
>  
> -	finish_wait(wq, &wait);
> -
>  	/*
>  	 * On VLV/CHV DSI the scanline counter would appear to
>  	 * increment approx. 1/3 of a scanline before start of vblank.
> -- 
> 2.51.0

-- 
Ville Syrjälä
Intel

  parent reply	other threads:[~2025-11-26 21:17 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-11-04  8:36 [PATCH v2 0/7] drm/i915/display: Handle vblank evasion with CONFIG_PREEMPT_RT Maarten Lankhorst
2025-11-04  8:36 ` [PATCH v2 1/7] drm/i915/display: Make get_vblank_counter use intel_de_read_fw() Maarten Lankhorst
2025-11-04  8:36 ` [PATCH v2 2/7] drm/i915/display: Use intel_de_write_fw in intel_pipe_fastset Maarten Lankhorst
2025-11-26 19:19   ` Shankar, Uma
2025-11-26 19:42     ` Ville Syrjälä
2025-11-26 19:56       ` Shankar, Uma
2025-12-01 17:43         ` Maarten Lankhorst
2025-12-11 14:35       ` Maarten Lankhorst
2025-11-04  8:36 ` [PATCH v2 3/7] drm/i915/display: Move vblank put until after critical section Maarten Lankhorst
2025-11-26 19:25   ` Shankar, Uma
2025-11-04  8:36 ` [PATCH v2 4/7] drm/i915/display: Remove locking from intel_vblank_evade " Maarten Lankhorst
2025-11-26 20:03   ` Shankar, Uma
2025-12-01 14:13     ` Maarten Lankhorst
2025-11-26 21:17   ` Ville Syrjälä [this message]
2025-12-11  9:59     ` Maarten Lankhorst
2025-11-04  8:36 ` [PATCH v2 5/7] drm/i915/display: Make icl_dsi_frame_update use _fw too Maarten Lankhorst
2025-11-04  8:36 ` [PATCH v2 6/7] drm/i915/display: Enable interrupts earlier on PREEMPT_RT Maarten Lankhorst
2025-11-26 20:45   ` Shankar, Uma
2025-11-26 22:57     ` Ville Syrjälä
2025-12-01 17:39       ` Maarten Lankhorst
2025-11-04  8:36 ` [PATCH v2 7/7] drm/i915: Use preempt_disable/enable_rt() where recommended Maarten Lankhorst
2025-11-05 13:47 ` [PATCH v2 0/7] drm/i915/display: Handle vblank evasion with CONFIG_PREEMPT_RT Sebastian Andrzej Siewior
2025-11-05 20:42   ` Maarten Lankhorst
2025-11-10 16:09     ` Sebastian Andrzej Siewior
2025-11-10 18:17       ` Maarten Lankhorst
2025-11-11  9:47         ` Sebastian Andrzej Siewior

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=aSduc2bC343FF3rk@intel.com \
    --to=ville.syrjala@linux.intel.com \
    --cc=bigeasy@linutronix.de \
    --cc=clrkwllms@kernel.org \
    --cc=dev@lankhorst.se \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=intel-xe@lists.freedesktop.org \
    --cc=linux-rt-devel@lists.linux.dev \
    --cc=mario.kleiner.de@gmail.com \
    --cc=rostedt@goodmis.org \
    --cc=tglx@linutronix.de \
    --cc=umgwanakikbuti@gmail.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;
as well as URLs for NNTP newsgroup(s).