mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [RESEND RFC PATCH 0/1] drm: ensure that vblank diff is never negative
@ 2026-01-08 16:51 Aaron Erhardt
  2026-01-08 16:51 ` [RESEND RFC PATCH 1/1] " Aaron Erhardt
  0 siblings, 1 reply; 3+ messages in thread
From: Aaron Erhardt @ 2026-01-08 16:51 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	David Airlie, Simona Vetter
  Cc: Aaron Erhardt, dri-devel, linux-kernel

This was probably lost due to inconvenient timing ahead of the holidays,
so I resend it now.

I observed a rare freeze on a device and was able to track the cause down
to incorrect reporting of timestamps in the vblank code. The
drm_vlank_restore code expects that one timestamp is always larger than the
other, but not all drivers fulfill this assumption. This allows the
difference between the two timestamps to become negative. Most of the time,
this is not fatal, because the value is rounded after dividing through the
frame duration. Therefore, small negative values are converted into zeros.
However, if the value is sufficiently negative, the calculation might end
up reporting that -1 frames were missed. The negative result is stored in
an unsigned integer, causing a wrap-around.

So far, this behavior has been observed on some newer Intel devices (e.g.
using the Intel Core Ultra 7 155H) with the i915 driver and the patch has
been tested successfully as a fix. While the root cause is in the driver, I
think that handling this case with drm_WARN_ON_ONCE is a good idea. Without
the warning, driver issues can remain unnoticed for a long time because
they only cause problems under very specific (seemingly random)
cirucumstances.

Normal (expected) log example:
i915 0000:00:02.0: [drm:drm_vblank_restore] missed 1 vblanks in 4165983 ns, frame duration=4166666 ns, hw_diff=1

Abnormal (but non-fatal) log example:
i915 0000:00:02.0: [drm:drm_vblank_restore] missed 0 vblanks in -1135 ns, frame duration=4166666 ns, hw_diff=0

Abnormal and fatal log example:
i915 0000:00:02.0: [drm:drm_vblank_restore] missed -891996132 vblanks in -4118209 ns, frame duration=4166666 ns, hw_diff=0

Aaron Erhardt (1):
  drm: ensure that vblank diff is never negative

 drivers/gpu/drm/drm_vblank.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

-- 
2.43.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [RESEND RFC PATCH 1/1] drm: ensure that vblank diff is never negative
  2026-01-08 16:51 [RESEND RFC PATCH 0/1] drm: ensure that vblank diff is never negative Aaron Erhardt
@ 2026-01-08 16:51 ` Aaron Erhardt
  2026-01-09  8:18   ` Jani Nikula
  0 siblings, 1 reply; 3+ messages in thread
From: Aaron Erhardt @ 2026-01-08 16:51 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	David Airlie, Simona Vetter
  Cc: Aaron Erhardt, dri-devel, linux-kernel

Handle cases, where drivers report incorrect timestamps and negative
time differences are calculated. If the negative difference is large
enough, negative missed vblanks are reported, but stored in an unsigned
integer which can causes freezes. This patch prevents this case.

This fix has been verified to fix problems with the i915 driver on
modern Intel CPUs (e.g. Intel Core Ultra 7 155H).

Signed-off-by: Aaron Erhardt <aer@tuxedocomputers.com>
---
 drivers/gpu/drm/drm_vblank.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c
index 94e45ed6869d..1022b6d61e4e 100644
--- a/drivers/gpu/drm/drm_vblank.c
+++ b/drivers/gpu/drm/drm_vblank.c
@@ -1563,7 +1563,14 @@ static void drm_vblank_restore(struct drm_device *dev, unsigned int pipe)
 	} while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0);
 
 	diff_ns = ktime_to_ns(ktime_sub(t_vblank, vblank->time));
-	if (framedur_ns)
+
+	/*
+	 * Make sure no bogus diffs result from negative differences
+	 * when incorrect timestamps are reported by a driver.
+	 */
+	if (drm_WARN_ON_ONCE(dev, t_vblank < vblank->time))
+		diff = 0;
+	else if (framedur_ns)
 		diff = DIV_ROUND_CLOSEST_ULL(diff_ns, framedur_ns);
 
 
-- 
2.43.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [RESEND RFC PATCH 1/1] drm: ensure that vblank diff is never negative
  2026-01-08 16:51 ` [RESEND RFC PATCH 1/1] " Aaron Erhardt
@ 2026-01-09  8:18   ` Jani Nikula
  0 siblings, 0 replies; 3+ messages in thread
From: Jani Nikula @ 2026-01-09  8:18 UTC (permalink / raw)
  To: Aaron Erhardt, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter
  Cc: Aaron Erhardt, dri-devel, linux-kernel

On Thu, 08 Jan 2026, Aaron Erhardt <aer@tuxedocomputers.com> wrote:
> Handle cases, where drivers report incorrect timestamps and negative
> time differences are calculated. If the negative difference is large
> enough, negative missed vblanks are reported, but stored in an unsigned
> integer which can causes freezes. This patch prevents this case.
>
> This fix has been verified to fix problems with the i915 driver on
> modern Intel CPUs (e.g. Intel Core Ultra 7 155H).

Is there a reported bug about this, preferrably with logs? If not,
please file one as instructed at [1], and reference the patch.


BR,
Jani.


[1] https://drm.pages.freedesktop.org/intel-docs/how-to-file-i915-bugs.html


>
> Signed-off-by: Aaron Erhardt <aer@tuxedocomputers.com>
> ---
>  drivers/gpu/drm/drm_vblank.c | 9 ++++++++-
>  1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c
> index 94e45ed6869d..1022b6d61e4e 100644
> --- a/drivers/gpu/drm/drm_vblank.c
> +++ b/drivers/gpu/drm/drm_vblank.c
> @@ -1563,7 +1563,14 @@ static void drm_vblank_restore(struct drm_device *dev, unsigned int pipe)
>  	} while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0);
>  
>  	diff_ns = ktime_to_ns(ktime_sub(t_vblank, vblank->time));
> -	if (framedur_ns)
> +
> +	/*
> +	 * Make sure no bogus diffs result from negative differences
> +	 * when incorrect timestamps are reported by a driver.
> +	 */
> +	if (drm_WARN_ON_ONCE(dev, t_vblank < vblank->time))
> +		diff = 0;
> +	else if (framedur_ns)
>  		diff = DIV_ROUND_CLOSEST_ULL(diff_ns, framedur_ns);

-- 
Jani Nikula, Intel

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-01-09  8:18 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-01-08 16:51 [RESEND RFC PATCH 0/1] drm: ensure that vblank diff is never negative Aaron Erhardt
2026-01-08 16:51 ` [RESEND RFC PATCH 1/1] " Aaron Erhardt
2026-01-09  8:18   ` Jani Nikula

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®