* [PATCH 6.18.y 1/5] drm/vblank: Add vblank timer
2026-05-25 13:16 ` [PATCH 6.18.y 0/5] drm/vkms: Backport generic vblank timer to fix ABBA deadlock w15303746062
@ 2026-05-25 13:16 ` w15303746062
2026-05-25 13:16 ` [PATCH 6.18.y 2/5] drm/vblank: Add CRTC helpers for simple use cases w15303746062
` (4 subsequent siblings)
5 siblings, 0 replies; 18+ messages in thread
From: w15303746062 @ 2026-05-25 13:16 UTC (permalink / raw)
To: stable, gregkh
Cc: tzimmermann, maarten.lankhorst, mripard, louis.chauvet, dri-devel,
linux-kernel, Javier Martinez Canillas, Michael Kelley
From: Thomas Zimmermann <tzimmermann@suse.de>
The vblank timer simulates a vblank interrupt for hardware without
support. Rate-limits the display update frequency.
DRM drivers for hardware without vblank support apply display updates
ASAP. A vblank event informs DRM clients of the completed update.
Userspace compositors immediately schedule the next update, which
creates significant load on virtualization outputs. Display updates
are usually fast on virtualization outputs, as their framebuffers are
in regular system memory and there's no hardware vblank interrupt to
throttle the update rate.
The vblank timer is a HR timer that signals the vblank in software.
It limits the update frequency of a DRM driver similar to a hardware
vblank interrupt. The timer is not synchronized to the actual vblank
interval of the display.
The code has been adopted from vkms, which added the funtionality
in commit 3a0709928b17 ("drm/vkms: Add vblank events simulated by
hrtimers").
The new implementation is part of the existing vblank support,
which sets up the timer automatically. Drivers only have to start
and cancel the vblank timer as part of enabling and disabling the
CRTC. The new vblank helper library provides callbacks for struct
drm_crtc_funcs.
The standard way for handling vblank is to call drm_crtc_handle_vblank().
Drivers that require additional processing, such as vkms, can init
handle_vblank_timeout in struct drm_crtc_helper_funcs to refer to
their timeout handler.
There's a possible deadlock between drm_crtc_handle_vblank() and
hrtimer_cancel(). [1] The implementation avoids to call hrtimer_cancel()
directly and instead signals to the timer function to not restart
itself.
v4:
- fix possible race condition between timeout and atomic commit (Michael)
v3:
- avoid deadlock when cancelling timer (Ville, Lyude)
v2:
- implement vblank timer entirely in vblank helpers
- downgrade overrun warning to debug
- fix docs
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Tested-by: Louis Chauvet <louis.chauvet@bootlin.com>
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
Tested-by: Michael Kelley <mhklinux@outlook.com>
Link: https://lore.kernel.org/all/20250510094757.4174662-1-zengheng4@huawei.com/ # [1]
Link: https://lore.kernel.org/r/20250916083816.30275-2-tzimmermann@suse.de
(cherry picked from commit 74afeb8128502a529041a2566febd26053a7be11)
---
Documentation/gpu/drm-kms-helpers.rst | 12 ++
drivers/gpu/drm/Makefile | 3 +-
drivers/gpu/drm/drm_vblank.c | 172 ++++++++++++++++++++++-
drivers/gpu/drm/drm_vblank_helper.c | 96 +++++++++++++
include/drm/drm_modeset_helper_vtables.h | 12 ++
include/drm/drm_vblank.h | 32 +++++
include/drm/drm_vblank_helper.h | 33 +++++
7 files changed, 357 insertions(+), 3 deletions(-)
create mode 100644 drivers/gpu/drm/drm_vblank_helper.c
create mode 100644 include/drm/drm_vblank_helper.h
diff --git a/Documentation/gpu/drm-kms-helpers.rst b/Documentation/gpu/drm-kms-helpers.rst
index 5139705089f2..781129f78b06 100644
--- a/Documentation/gpu/drm-kms-helpers.rst
+++ b/Documentation/gpu/drm-kms-helpers.rst
@@ -92,6 +92,18 @@ GEM Atomic Helper Reference
.. kernel-doc:: drivers/gpu/drm/drm_gem_atomic_helper.c
:export:
+VBLANK Helper Reference
+-----------------------
+
+.. kernel-doc:: drivers/gpu/drm/drm_vblank_helper.c
+ :doc: overview
+
+.. kernel-doc:: include/drm/drm_vblank_helper.h
+ :internal:
+
+.. kernel-doc:: drivers/gpu/drm/drm_vblank_helper.c
+ :export:
+
Simple KMS Helper Reference
===========================
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index da2565e6de71..7789f42027ff 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -150,7 +150,8 @@ drm_kms_helper-y := \
drm_plane_helper.o \
drm_probe_helper.o \
drm_self_refresh_helper.o \
- drm_simple_kms_helper.o
+ drm_simple_kms_helper.o \
+ drm_vblank_helper.o
drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o
drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c
index 46f59883183d..61e211fd3c9c 100644
--- a/drivers/gpu/drm/drm_vblank.c
+++ b/drivers/gpu/drm/drm_vblank.c
@@ -136,8 +136,17 @@
* vblanks after a timer has expired, which can be configured through the
* ``vblankoffdelay`` module parameter.
*
- * Drivers for hardware without support for vertical-blanking interrupts
- * must not call drm_vblank_init(). For such drivers, atomic helpers will
+ * Drivers for hardware without support for vertical-blanking interrupts can
+ * use DRM vblank timers to send vblank events at the rate of the current
+ * display mode's refresh. While not synchronized to the hardware's
+ * vertical-blanking regions, the timer helps DRM clients and compositors to
+ * adapt their update cycle to the display output. Drivers should set up
+ * vblanking as usual, but call drm_crtc_vblank_start_timer() and
+ * drm_crtc_vblank_cancel_timer() as part of their atomic mode setting.
+ * See also DRM vblank helpers for more information.
+ *
+ * Drivers without support for vertical-blanking interrupts nor timers must
+ * not call drm_vblank_init(). For these drivers, atomic helpers will
* automatically generate fake vblank events as part of the display update.
* This functionality also can be controlled by the driver by enabling and
* disabling struct drm_crtc_state.no_vblank.
@@ -508,6 +517,9 @@ static void drm_vblank_init_release(struct drm_device *dev, void *ptr)
drm_WARN_ON(dev, READ_ONCE(vblank->enabled) &&
drm_core_check_feature(dev, DRIVER_MODESET));
+ if (vblank->vblank_timer.crtc)
+ hrtimer_cancel(&vblank->vblank_timer.timer);
+
drm_vblank_destroy_worker(vblank);
timer_delete_sync(&vblank->disable_timer);
}
@@ -2162,3 +2174,159 @@ int drm_crtc_queue_sequence_ioctl(struct drm_device *dev, void *data,
return ret;
}
+/*
+ * VBLANK timer
+ */
+
+static enum hrtimer_restart drm_vblank_timer_function(struct hrtimer *timer)
+{
+ struct drm_vblank_crtc_timer *vtimer =
+ container_of(timer, struct drm_vblank_crtc_timer, timer);
+ struct drm_crtc *crtc = vtimer->crtc;
+ const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+ struct drm_device *dev = crtc->dev;
+ unsigned long flags;
+ ktime_t interval;
+ u64 ret_overrun;
+ bool succ;
+
+ spin_lock_irqsave(&vtimer->interval_lock, flags);
+ interval = vtimer->interval;
+ spin_unlock_irqrestore(&vtimer->interval_lock, flags);
+
+ if (!interval)
+ return HRTIMER_NORESTART;
+
+ ret_overrun = hrtimer_forward_now(&vtimer->timer, interval);
+ if (ret_overrun != 1)
+ drm_dbg_vbl(dev, "vblank timer overrun\n");
+
+ if (crtc_funcs->handle_vblank_timeout)
+ succ = crtc_funcs->handle_vblank_timeout(crtc);
+ else
+ succ = drm_crtc_handle_vblank(crtc);
+ if (!succ)
+ return HRTIMER_NORESTART;
+
+ return HRTIMER_RESTART;
+}
+
+/**
+ * drm_crtc_vblank_start_timer - Starts the vblank timer on the given CRTC
+ * @crtc: the CRTC
+ *
+ * Drivers should call this function from their CRTC's enable_vblank
+ * function to start a vblank timer. The timer will fire after the duration
+ * of a full frame. drm_crtc_vblank_cancel_timer() disables a running timer.
+ *
+ * Returns:
+ * 0 on success, or a negative errno code otherwise.
+ */
+int drm_crtc_vblank_start_timer(struct drm_crtc *crtc)
+{
+ struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
+ struct drm_vblank_crtc_timer *vtimer = &vblank->vblank_timer;
+ unsigned long flags;
+
+ if (!vtimer->crtc) {
+ /*
+ * Set up the data structures on the first invocation.
+ */
+ vtimer->crtc = crtc;
+ spin_lock_init(&vtimer->interval_lock);
+ hrtimer_setup(&vtimer->timer, drm_vblank_timer_function,
+ CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ } else {
+ /*
+ * Timer should not be active. If it is, wait for the
+ * previous cancel operations to finish.
+ */
+ while (hrtimer_active(&vtimer->timer))
+ hrtimer_try_to_cancel(&vtimer->timer);
+ }
+
+ drm_calc_timestamping_constants(crtc, &crtc->mode);
+
+ spin_lock_irqsave(&vtimer->interval_lock, flags);
+ vtimer->interval = ns_to_ktime(vblank->framedur_ns);
+ spin_unlock_irqrestore(&vtimer->interval_lock, flags);
+
+ hrtimer_start(&vtimer->timer, vtimer->interval, HRTIMER_MODE_REL);
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_crtc_vblank_start_timer);
+
+/**
+ * drm_crtc_vblank_start_timer - Cancels the given CRTC's vblank timer
+ * @crtc: the CRTC
+ *
+ * Drivers should call this function from their CRTC's disable_vblank
+ * function to stop a vblank timer.
+ */
+void drm_crtc_vblank_cancel_timer(struct drm_crtc *crtc)
+{
+ struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
+ struct drm_vblank_crtc_timer *vtimer = &vblank->vblank_timer;
+ unsigned long flags;
+
+ /*
+ * Calling hrtimer_cancel() can result in a deadlock with DRM's
+ * vblank_time_lime_lock and hrtimers' softirq_expiry_lock. So
+ * clear interval and indicate cancellation. The timer function
+ * will cancel itself on the next invocation.
+ */
+
+ spin_lock_irqsave(&vtimer->interval_lock, flags);
+ vtimer->interval = 0;
+ spin_unlock_irqrestore(&vtimer->interval_lock, flags);
+
+ hrtimer_try_to_cancel(&vtimer->timer);
+}
+EXPORT_SYMBOL(drm_crtc_vblank_cancel_timer);
+
+/**
+ * drm_crtc_vblank_get_vblank_timeout - Returns the vblank timeout
+ * @crtc: The CRTC
+ * @vblank_time: Returns the next vblank timestamp
+ *
+ * The helper drm_crtc_vblank_get_vblank_timeout() returns the next vblank
+ * timestamp of the CRTC's vblank timer according to the timer's expiry
+ * time.
+ */
+void drm_crtc_vblank_get_vblank_timeout(struct drm_crtc *crtc, ktime_t *vblank_time)
+{
+ struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
+ struct drm_vblank_crtc_timer *vtimer = &vblank->vblank_timer;
+ u64 cur_count;
+ ktime_t cur_time;
+
+ if (!READ_ONCE(vblank->enabled)) {
+ *vblank_time = ktime_get();
+ return;
+ }
+
+ /*
+ * A concurrent vblank timeout could update the expires field before
+ * we compare it with the vblank time. Hence we'd compare the old
+ * expiry time to the new vblank time; deducing the timer had already
+ * expired. Reread until we get consistent values from both fields.
+ */
+ do {
+ cur_count = drm_crtc_vblank_count_and_time(crtc, &cur_time);
+ *vblank_time = READ_ONCE(vtimer->timer.node.expires);
+ } while (cur_count != drm_crtc_vblank_count_and_time(crtc, &cur_time));
+
+ if (drm_WARN_ON(crtc->dev, !ktime_compare(*vblank_time, cur_time)))
+ return; /* Already expired */
+
+ /*
+ * To prevent races we roll the hrtimer forward before we do any
+ * interrupt processing - this is how real hw works (the interrupt
+ * is only generated after all the vblank registers are updated)
+ * and what the vblank core expects. Therefore we need to always
+ * correct the timestamp by one frame.
+ */
+ *vblank_time = ktime_sub(*vblank_time, vtimer->interval);
+}
+EXPORT_SYMBOL(drm_crtc_vblank_get_vblank_timeout);
diff --git a/drivers/gpu/drm/drm_vblank_helper.c b/drivers/gpu/drm/drm_vblank_helper.c
new file mode 100644
index 000000000000..f94d1e706191
--- /dev/null
+++ b/drivers/gpu/drm/drm_vblank_helper.c
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: MIT
+
+#include <drm/drm_crtc.h>
+#include <drm/drm_managed.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_print.h>
+#include <drm/drm_vblank.h>
+#include <drm/drm_vblank_helper.h>
+
+/**
+ * DOC: overview
+ *
+ * The vblank helper library provides functions for supporting vertical
+ * blanking in DRM drivers.
+ *
+ * For vblank timers, several callback implementations are available.
+ * Drivers enable support for vblank timers by setting the vblank callbacks
+ * in struct &drm_crtc_funcs to the helpers provided by this library. The
+ * initializer macro DRM_CRTC_VBLANK_TIMER_FUNCS does this conveniently.
+ *
+ * Once the driver enables vblank support with drm_vblank_init(), each
+ * CRTC's vblank timer fires according to the programmed display mode. By
+ * default, the vblank timer invokes drm_crtc_handle_vblank(). Drivers with
+ * more specific requirements can set their own handler function in
+ * struct &drm_crtc_helper_funcs.handle_vblank_timeout.
+ */
+
+/*
+ * VBLANK timer
+ */
+
+/**
+ * drm_crtc_vblank_helper_enable_vblank_timer - Implements struct &drm_crtc_funcs.enable_vblank
+ * @crtc: The CRTC
+ *
+ * The helper drm_crtc_vblank_helper_enable_vblank_timer() implements
+ * enable_vblank of struct drm_crtc_helper_funcs for CRTCs that require
+ * a VBLANK timer. It sets up the timer on the first invocation. The
+ * started timer expires after the current frame duration. See struct
+ * &drm_vblank_crtc.framedur_ns.
+ *
+ * See also struct &drm_crtc_helper_funcs.enable_vblank.
+ *
+ * Returns:
+ * 0 on success, or a negative errno code otherwise.
+ */
+int drm_crtc_vblank_helper_enable_vblank_timer(struct drm_crtc *crtc)
+{
+ return drm_crtc_vblank_start_timer(crtc);
+}
+EXPORT_SYMBOL(drm_crtc_vblank_helper_enable_vblank_timer);
+
+/**
+ * drm_crtc_vblank_helper_disable_vblank_timer - Implements struct &drm_crtc_funcs.disable_vblank
+ * @crtc: The CRTC
+ *
+ * The helper drm_crtc_vblank_helper_disable_vblank_timer() implements
+ * disable_vblank of struct drm_crtc_funcs for CRTCs that require a
+ * VBLANK timer.
+ *
+ * See also struct &drm_crtc_helper_funcs.disable_vblank.
+ */
+void drm_crtc_vblank_helper_disable_vblank_timer(struct drm_crtc *crtc)
+{
+ drm_crtc_vblank_cancel_timer(crtc);
+}
+EXPORT_SYMBOL(drm_crtc_vblank_helper_disable_vblank_timer);
+
+/**
+ * drm_crtc_vblank_helper_get_vblank_timestamp_from_timer -
+ * Implements struct &drm_crtc_funcs.get_vblank_timestamp
+ * @crtc: The CRTC
+ * @max_error: Maximum acceptable error
+ * @vblank_time: Returns the next vblank timestamp
+ * @in_vblank_irq: True is called from drm_crtc_handle_vblank()
+ *
+ * The helper drm_crtc_helper_get_vblank_timestamp_from_timer() implements
+ * get_vblank_timestamp of struct drm_crtc_funcs for CRTCs that require a
+ * VBLANK timer. It returns the timestamp according to the timer's expiry
+ * time.
+ *
+ * See also struct &drm_crtc_funcs.get_vblank_timestamp.
+ *
+ * Returns:
+ * True on success, or false otherwise.
+ */
+bool drm_crtc_vblank_helper_get_vblank_timestamp_from_timer(struct drm_crtc *crtc,
+ int *max_error,
+ ktime_t *vblank_time,
+ bool in_vblank_irq)
+{
+ drm_crtc_vblank_get_vblank_timeout(crtc, vblank_time);
+
+ return true;
+}
+EXPORT_SYMBOL(drm_crtc_vblank_helper_get_vblank_timestamp_from_timer);
diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
index ce7c7aeac887..fe32854b7ffe 100644
--- a/include/drm/drm_modeset_helper_vtables.h
+++ b/include/drm/drm_modeset_helper_vtables.h
@@ -490,6 +490,18 @@ struct drm_crtc_helper_funcs {
bool in_vblank_irq, int *vpos, int *hpos,
ktime_t *stime, ktime_t *etime,
const struct drm_display_mode *mode);
+
+ /**
+ * @handle_vblank_timeout: Handles timeouts of the vblank timer.
+ *
+ * Called by CRTC's the vblank timer on each timeout. Semantics is
+ * equivalient to drm_crtc_handle_vblank(). Implementations should
+ * invoke drm_crtc_handle_vblank() as part of processing the timeout.
+ *
+ * This callback is optional. If unset, the vblank timer invokes
+ * drm_crtc_handle_vblank() directly.
+ */
+ bool (*handle_vblank_timeout)(struct drm_crtc *crtc);
};
/**
diff --git a/include/drm/drm_vblank.h b/include/drm/drm_vblank.h
index 151ab1e85b1b..ffa564d79638 100644
--- a/include/drm/drm_vblank.h
+++ b/include/drm/drm_vblank.h
@@ -25,6 +25,7 @@
#define _DRM_VBLANK_H_
#include <linux/seqlock.h>
+#include <linux/hrtimer.h>
#include <linux/idr.h>
#include <linux/poll.h>
#include <linux/kthread.h>
@@ -103,6 +104,28 @@ struct drm_vblank_crtc_config {
bool disable_immediate;
};
+/**
+ * struct drm_vblank_crtc_timer - vblank timer for a CRTC
+ */
+struct drm_vblank_crtc_timer {
+ /**
+ * @timer: The vblank's high-resolution timer
+ */
+ struct hrtimer timer;
+ /**
+ * @interval_lock: Protects @interval
+ */
+ spinlock_t interval_lock;
+ /**
+ * @interval: Duration between two vblanks
+ */
+ ktime_t interval;
+ /**
+ * @crtc: The timer's CRTC
+ */
+ struct drm_crtc *crtc;
+};
+
/**
* struct drm_vblank_crtc - vblank tracking for a CRTC
*
@@ -254,6 +277,11 @@ struct drm_vblank_crtc {
* cancelled.
*/
wait_queue_head_t work_wait_queue;
+
+ /**
+ * @vblank_timer: Holds the state of the vblank timer
+ */
+ struct drm_vblank_crtc_timer vblank_timer;
};
struct drm_vblank_crtc *drm_crtc_vblank_crtc(struct drm_crtc *crtc);
@@ -290,6 +318,10 @@ wait_queue_head_t *drm_crtc_vblank_waitqueue(struct drm_crtc *crtc);
void drm_crtc_set_max_vblank_count(struct drm_crtc *crtc,
u32 max_vblank_count);
+int drm_crtc_vblank_start_timer(struct drm_crtc *crtc);
+void drm_crtc_vblank_cancel_timer(struct drm_crtc *crtc);
+void drm_crtc_vblank_get_vblank_timeout(struct drm_crtc *crtc, ktime_t *vblank_time);
+
/*
* Helpers for struct drm_crtc_funcs
*/
diff --git a/include/drm/drm_vblank_helper.h b/include/drm/drm_vblank_helper.h
new file mode 100644
index 000000000000..74a971d0cfba
--- /dev/null
+++ b/include/drm/drm_vblank_helper.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef _DRM_VBLANK_HELPER_H_
+#define _DRM_VBLANK_HELPER_H_
+
+#include <linux/hrtimer_types.h>
+#include <linux/types.h>
+
+struct drm_crtc;
+
+/*
+ * VBLANK timer
+ */
+
+int drm_crtc_vblank_helper_enable_vblank_timer(struct drm_crtc *crtc);
+void drm_crtc_vblank_helper_disable_vblank_timer(struct drm_crtc *crtc);
+bool drm_crtc_vblank_helper_get_vblank_timestamp_from_timer(struct drm_crtc *crtc,
+ int *max_error,
+ ktime_t *vblank_time,
+ bool in_vblank_irq);
+
+/**
+ * DRM_CRTC_VBLANK_TIMER_FUNCS - Default implementation for VBLANK timers
+ *
+ * This macro initializes struct &drm_crtc_funcs to default helpers for
+ * VBLANK timers.
+ */
+#define DRM_CRTC_VBLANK_TIMER_FUNCS \
+ .enable_vblank = drm_crtc_vblank_helper_enable_vblank_timer, \
+ .disable_vblank = drm_crtc_vblank_helper_disable_vblank_timer, \
+ .get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp_from_timer
+
+#endif
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH 6.18.y 2/5] drm/vblank: Add CRTC helpers for simple use cases
2026-05-25 13:16 ` [PATCH 6.18.y 0/5] drm/vkms: Backport generic vblank timer to fix ABBA deadlock w15303746062
2026-05-25 13:16 ` [PATCH 6.18.y 1/5] drm/vblank: Add vblank timer w15303746062
@ 2026-05-25 13:16 ` w15303746062
2026-05-25 13:16 ` [PATCH 6.18.y 3/5] drm/vkms: Convert to DRM's vblank timer w15303746062
` (3 subsequent siblings)
5 siblings, 0 replies; 18+ messages in thread
From: w15303746062 @ 2026-05-25 13:16 UTC (permalink / raw)
To: stable, gregkh
Cc: tzimmermann, maarten.lankhorst, mripard, louis.chauvet, dri-devel,
linux-kernel, Javier Martinez Canillas, Michael Kelley
From: Thomas Zimmermann <tzimmermann@suse.de>
Implement atomic_flush, atomic_enable and atomic_disable of struct
drm_crtc_helper_funcs for vblank handling. Driver with no further
requirements can use these functions instead of adding their own.
Also simplifies the use of vblank timers.
The code has been adopted from vkms, which added the funtionality
in commit 3a0709928b17 ("drm/vkms: Add vblank events simulated by
hrtimers").
v3:
- mention vkms (Javier)
v2:
- fix docs
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
Tested-by: Michael Kelley <mhklinux@outlook.com>
Link: https://lore.kernel.org/r/20250916083816.30275-3-tzimmermann@suse.de
(cherry picked from commit d54dbb5963bdbdf8559903fe2b2343e871adcb30)
---
drivers/gpu/drm/drm_vblank_helper.c | 80 +++++++++++++++++++++++++++++
include/drm/drm_vblank_helper.h | 23 +++++++++
2 files changed, 103 insertions(+)
diff --git a/drivers/gpu/drm/drm_vblank_helper.c b/drivers/gpu/drm/drm_vblank_helper.c
index f94d1e706191..a04a6ba1b0ca 100644
--- a/drivers/gpu/drm/drm_vblank_helper.c
+++ b/drivers/gpu/drm/drm_vblank_helper.c
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: MIT
+#include <drm/drm_atomic.h>
#include <drm/drm_crtc.h>
#include <drm/drm_managed.h>
#include <drm/drm_modeset_helper_vtables.h>
@@ -17,6 +18,12 @@
* Drivers enable support for vblank timers by setting the vblank callbacks
* in struct &drm_crtc_funcs to the helpers provided by this library. The
* initializer macro DRM_CRTC_VBLANK_TIMER_FUNCS does this conveniently.
+ * The driver further has to send the VBLANK event from its atomic_flush
+ * callback and control vblank from the CRTC's atomic_enable and atomic_disable
+ * callbacks. The callbacks are located in struct &drm_crtc_helper_funcs.
+ * The vblank helper library provides implementations of these callbacks
+ * for drivers without further requirements. The initializer macro
+ * DRM_CRTC_HELPER_VBLANK_FUNCS sets them coveniently.
*
* Once the driver enables vblank support with drm_vblank_init(), each
* CRTC's vblank timer fires according to the programmed display mode. By
@@ -25,6 +32,79 @@
* struct &drm_crtc_helper_funcs.handle_vblank_timeout.
*/
+/*
+ * VBLANK helpers
+ */
+
+/**
+ * drm_crtc_vblank_atomic_flush -
+ * Implements struct &drm_crtc_helper_funcs.atomic_flush
+ * @crtc: The CRTC
+ * @state: The atomic state to apply
+ *
+ * The helper drm_crtc_vblank_atomic_flush() implements atomic_flush of
+ * struct drm_crtc_helper_funcs for CRTCs that only need to send out a
+ * VBLANK event.
+ *
+ * See also struct &drm_crtc_helper_funcs.atomic_flush.
+ */
+void drm_crtc_vblank_atomic_flush(struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+ struct drm_pending_vblank_event *event;
+
+ spin_lock_irq(&dev->event_lock);
+
+ event = crtc_state->event;
+ crtc_state->event = NULL;
+
+ if (event) {
+ if (drm_crtc_vblank_get(crtc) == 0)
+ drm_crtc_arm_vblank_event(crtc, event);
+ else
+ drm_crtc_send_vblank_event(crtc, event);
+ }
+
+ spin_unlock_irq(&dev->event_lock);
+}
+EXPORT_SYMBOL(drm_crtc_vblank_atomic_flush);
+
+/**
+ * drm_crtc_vblank_atomic_enable - Implements struct &drm_crtc_helper_funcs.atomic_enable
+ * @crtc: The CRTC
+ * @state: The atomic state
+ *
+ * The helper drm_crtc_vblank_atomic_enable() implements atomic_enable
+ * of struct drm_crtc_helper_funcs for CRTCs the only need to enable VBLANKs.
+ *
+ * See also struct &drm_crtc_helper_funcs.atomic_enable.
+ */
+void drm_crtc_vblank_atomic_enable(struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
+{
+ drm_crtc_vblank_on(crtc);
+}
+EXPORT_SYMBOL(drm_crtc_vblank_atomic_enable);
+
+/**
+ * drm_crtc_vblank_atomic_disable - Implements struct &drm_crtc_helper_funcs.atomic_disable
+ * @crtc: The CRTC
+ * @state: The atomic state
+ *
+ * The helper drm_crtc_vblank_atomic_disable() implements atomic_disable
+ * of struct drm_crtc_helper_funcs for CRTCs the only need to disable VBLANKs.
+ *
+ * See also struct &drm_crtc_funcs.atomic_disable.
+ */
+void drm_crtc_vblank_atomic_disable(struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
+{
+ drm_crtc_vblank_off(crtc);
+}
+EXPORT_SYMBOL(drm_crtc_vblank_atomic_disable);
+
/*
* VBLANK timer
*/
diff --git a/include/drm/drm_vblank_helper.h b/include/drm/drm_vblank_helper.h
index 74a971d0cfba..fcd8a9b35846 100644
--- a/include/drm/drm_vblank_helper.h
+++ b/include/drm/drm_vblank_helper.h
@@ -6,8 +6,31 @@
#include <linux/hrtimer_types.h>
#include <linux/types.h>
+struct drm_atomic_state;
struct drm_crtc;
+/*
+ * VBLANK helpers
+ */
+
+void drm_crtc_vblank_atomic_flush(struct drm_crtc *crtc,
+ struct drm_atomic_state *state);
+void drm_crtc_vblank_atomic_enable(struct drm_crtc *crtc,
+ struct drm_atomic_state *state);
+void drm_crtc_vblank_atomic_disable(struct drm_crtc *crtc,
+ struct drm_atomic_state *crtc_state);
+
+/**
+ * DRM_CRTC_HELPER_VBLANK_FUNCS - Default implementation for VBLANK helpers
+ *
+ * This macro initializes struct &drm_crtc_helper_funcs to default helpers
+ * for VBLANK handling.
+ */
+#define DRM_CRTC_HELPER_VBLANK_FUNCS \
+ .atomic_flush = drm_crtc_vblank_atomic_flush, \
+ .atomic_enable = drm_crtc_vblank_atomic_enable, \
+ .atomic_disable = drm_crtc_vblank_atomic_disable
+
/*
* VBLANK timer
*/
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH 6.18.y 3/5] drm/vkms: Convert to DRM's vblank timer
2026-05-25 13:16 ` [PATCH 6.18.y 0/5] drm/vkms: Backport generic vblank timer to fix ABBA deadlock w15303746062
2026-05-25 13:16 ` [PATCH 6.18.y 1/5] drm/vblank: Add vblank timer w15303746062
2026-05-25 13:16 ` [PATCH 6.18.y 2/5] drm/vblank: Add CRTC helpers for simple use cases w15303746062
@ 2026-05-25 13:16 ` w15303746062
2026-05-25 13:16 ` [PATCH 6.18.y 4/5] drm/atomic: Increase timeout in drm_atomic_helper_wait_for_vblanks() w15303746062
` (2 subsequent siblings)
5 siblings, 0 replies; 18+ messages in thread
From: w15303746062 @ 2026-05-25 13:16 UTC (permalink / raw)
To: stable, gregkh
Cc: tzimmermann, maarten.lankhorst, mripard, louis.chauvet, dri-devel,
linux-kernel, Javier Martinez Canillas
From: Thomas Zimmermann <tzimmermann@suse.de>
Replace vkms' vblank timer with the DRM implementation. The DRM
code is identical in concept, but differs in implementation.
Vblank timers are covered in vblank helpers and initializer macros,
so remove the corresponding hrtimer in struct vkms_output. The
vblank timer calls vkms' custom timeout code via handle_vblank_timeout
in struct drm_crtc_helper_funcs.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Tested-by: Louis Chauvet <louis.chauvet@bootlin.com>
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
Link: https://lore.kernel.org/r/20250916083816.30275-4-tzimmermann@suse.de
(cherry picked from commit 02e2681ffe1addde1fc8c35d05657b16bfa79613)
---
drivers/gpu/drm/vkms/vkms_crtc.c | 83 +++-----------------------------
drivers/gpu/drm/vkms/vkms_drv.h | 2 -
2 files changed, 7 insertions(+), 78 deletions(-)
diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c
index e60573e0f3e9..bd79f24686dc 100644
--- a/drivers/gpu/drm/vkms/vkms_crtc.c
+++ b/drivers/gpu/drm/vkms/vkms_crtc.c
@@ -7,25 +7,18 @@
#include <drm/drm_managed.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_vblank.h>
+#include <drm/drm_vblank_helper.h>
#include "vkms_drv.h"
-static enum hrtimer_restart vkms_vblank_simulate(struct hrtimer *timer)
+static bool vkms_crtc_handle_vblank_timeout(struct drm_crtc *crtc)
{
- struct vkms_output *output = container_of(timer, struct vkms_output,
- vblank_hrtimer);
- struct drm_crtc *crtc = &output->crtc;
+ struct vkms_output *output = drm_crtc_to_vkms_output(crtc);
struct vkms_crtc_state *state;
- u64 ret_overrun;
bool ret, fence_cookie;
fence_cookie = dma_fence_begin_signalling();
- ret_overrun = hrtimer_forward_now(&output->vblank_hrtimer,
- output->period_ns);
- if (ret_overrun != 1)
- pr_warn("%s: vblank timer overrun\n", __func__);
-
spin_lock(&output->lock);
ret = drm_crtc_handle_vblank(crtc);
if (!ret)
@@ -57,55 +50,6 @@ static enum hrtimer_restart vkms_vblank_simulate(struct hrtimer *timer)
dma_fence_end_signalling(fence_cookie);
- return HRTIMER_RESTART;
-}
-
-static int vkms_enable_vblank(struct drm_crtc *crtc)
-{
- struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
- struct vkms_output *out = drm_crtc_to_vkms_output(crtc);
-
- hrtimer_setup(&out->vblank_hrtimer, &vkms_vblank_simulate, CLOCK_MONOTONIC,
- HRTIMER_MODE_REL);
- out->period_ns = ktime_set(0, vblank->framedur_ns);
- hrtimer_start(&out->vblank_hrtimer, out->period_ns, HRTIMER_MODE_REL);
-
- return 0;
-}
-
-static void vkms_disable_vblank(struct drm_crtc *crtc)
-{
- struct vkms_output *out = drm_crtc_to_vkms_output(crtc);
-
- hrtimer_cancel(&out->vblank_hrtimer);
-}
-
-static bool vkms_get_vblank_timestamp(struct drm_crtc *crtc,
- int *max_error, ktime_t *vblank_time,
- bool in_vblank_irq)
-{
- struct vkms_output *output = drm_crtc_to_vkms_output(crtc);
- struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
-
- if (!READ_ONCE(vblank->enabled)) {
- *vblank_time = ktime_get();
- return true;
- }
-
- *vblank_time = READ_ONCE(output->vblank_hrtimer.node.expires);
-
- if (WARN_ON(*vblank_time == vblank->time))
- return true;
-
- /*
- * To prevent races we roll the hrtimer forward before we do any
- * interrupt processing - this is how real hw works (the interrupt is
- * only generated after all the vblank registers are updated) and what
- * the vblank core expects. Therefore we need to always correct the
- * timestampe by one frame.
- */
- *vblank_time -= output->period_ns;
-
return true;
}
@@ -159,9 +103,7 @@ static const struct drm_crtc_funcs vkms_crtc_funcs = {
.reset = vkms_atomic_crtc_reset,
.atomic_duplicate_state = vkms_atomic_crtc_duplicate_state,
.atomic_destroy_state = vkms_atomic_crtc_destroy_state,
- .enable_vblank = vkms_enable_vblank,
- .disable_vblank = vkms_disable_vblank,
- .get_vblank_timestamp = vkms_get_vblank_timestamp,
+ DRM_CRTC_VBLANK_TIMER_FUNCS,
.get_crc_sources = vkms_get_crc_sources,
.set_crc_source = vkms_set_crc_source,
.verify_crc_source = vkms_verify_crc_source,
@@ -213,18 +155,6 @@ static int vkms_crtc_atomic_check(struct drm_crtc *crtc,
return 0;
}
-static void vkms_crtc_atomic_enable(struct drm_crtc *crtc,
- struct drm_atomic_state *state)
-{
- drm_crtc_vblank_on(crtc);
-}
-
-static void vkms_crtc_atomic_disable(struct drm_crtc *crtc,
- struct drm_atomic_state *state)
-{
- drm_crtc_vblank_off(crtc);
-}
-
static void vkms_crtc_atomic_begin(struct drm_crtc *crtc,
struct drm_atomic_state *state)
__acquires(&vkms_output->lock)
@@ -265,8 +195,9 @@ static const struct drm_crtc_helper_funcs vkms_crtc_helper_funcs = {
.atomic_check = vkms_crtc_atomic_check,
.atomic_begin = vkms_crtc_atomic_begin,
.atomic_flush = vkms_crtc_atomic_flush,
- .atomic_enable = vkms_crtc_atomic_enable,
- .atomic_disable = vkms_crtc_atomic_disable,
+ .atomic_enable = drm_crtc_vblank_atomic_enable,
+ .atomic_disable = drm_crtc_vblank_atomic_disable,
+ .handle_vblank_timeout = vkms_crtc_handle_vblank_timeout,
};
struct vkms_output *vkms_crtc_init(struct drm_device *dev, struct drm_plane *primary,
diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
index 8013c31efe3b..fb9711e1c6fb 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.h
+++ b/drivers/gpu/drm/vkms/vkms_drv.h
@@ -215,8 +215,6 @@ struct vkms_output {
struct drm_crtc crtc;
struct drm_writeback_connector wb_connector;
struct drm_encoder wb_encoder;
- struct hrtimer vblank_hrtimer;
- ktime_t period_ns;
struct workqueue_struct *composer_workq;
spinlock_t lock;
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH 6.18.y 4/5] drm/atomic: Increase timeout in drm_atomic_helper_wait_for_vblanks()
2026-05-25 13:16 ` [PATCH 6.18.y 0/5] drm/vkms: Backport generic vblank timer to fix ABBA deadlock w15303746062
` (2 preceding siblings ...)
2026-05-25 13:16 ` [PATCH 6.18.y 3/5] drm/vkms: Convert to DRM's vblank timer w15303746062
@ 2026-05-25 13:16 ` w15303746062
2026-05-25 13:16 ` [PATCH 6.18.y 5/5] drm/vblank: Fix kernel docs for vblank timer w15303746062
2026-05-26 11:35 ` [PATCH 6.18.y 0/5] drm/vkms: Backport generic vblank timer to fix ABBA deadlock Sasha Levin
5 siblings, 0 replies; 18+ messages in thread
From: w15303746062 @ 2026-05-25 13:16 UTC (permalink / raw)
To: stable, gregkh
Cc: tzimmermann, maarten.lankhorst, mripard, louis.chauvet, dri-devel,
linux-kernel, syzbot+fcede535e7eb57cf5b43,
Ville Syrjälä
From: Thomas Zimmermann <tzimmermann@suse.de>
Increase the timeout for vblank events from 100 ms to 1000 ms. This
is the same fix as in commit f050da08a4ed ("drm/vblank: Increase
timeout in drm_wait_one_vblank()") for another vblank timeout.
After merging generic DRM vblank timers [1] and converting several
DRM drivers for virtual hardware, these drivers synchronize their
vblank events to the display refresh rate. This can trigger timeouts
within the DRM framework.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://lore.kernel.org/dri-devel/20250904145806.430568-1-tzimmermann@suse.de/ # [1]
Reported-by: syzbot+fcede535e7eb57cf5b43@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/dri-devel/69381d6c.050a0220.4004e.0017.GAE@google.com/
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Fixes: 74afeb812850 ("drm/vblank: Add vblank timer")
Link: https://patch.msgid.link/20251209143325.102056-1-tzimmermann@suse.de
(cherry picked from commit 79ae8510b5b81b9500370f89c619b50ca9c0990f)
---
drivers/gpu/drm/drm_atomic_helper.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index d5ebe6ea0acb..f9d328dcaed8 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1837,7 +1837,7 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
ret = wait_event_timeout(dev->vblank[i].queue,
state->crtcs[i].last_vblank_count !=
drm_crtc_vblank_count(crtc),
- msecs_to_jiffies(100));
+ msecs_to_jiffies(1000));
WARN(!ret, "[CRTC:%d:%s] vblank wait timed out\n",
crtc->base.id, crtc->name);
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH 6.18.y 5/5] drm/vblank: Fix kernel docs for vblank timer
2026-05-25 13:16 ` [PATCH 6.18.y 0/5] drm/vkms: Backport generic vblank timer to fix ABBA deadlock w15303746062
` (3 preceding siblings ...)
2026-05-25 13:16 ` [PATCH 6.18.y 4/5] drm/atomic: Increase timeout in drm_atomic_helper_wait_for_vblanks() w15303746062
@ 2026-05-25 13:16 ` w15303746062
2026-05-26 11:35 ` [PATCH 6.18.y 0/5] drm/vkms: Backport generic vblank timer to fix ABBA deadlock Sasha Levin
5 siblings, 0 replies; 18+ messages in thread
From: w15303746062 @ 2026-05-25 13:16 UTC (permalink / raw)
To: stable, gregkh
Cc: tzimmermann, maarten.lankhorst, mripard, louis.chauvet, dri-devel,
linux-kernel, Stephen Rothwell, Javier Martinez Canillas,
David Airlie, Simona Vetter
From: Thomas Zimmermann <tzimmermann@suse.de>
Fix documentation for drm_crtc_vblank_start_timer(), which referred
to drm_crtc_vblank_cancel_timer().
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reported-by: Stephen Rothwell <sfr@canb.auug.org.au>
Closes: https://lore.kernel.org/dri-devel/20251106152201.6f248c09@canb.auug.org.au/
Fixes: 74afeb812850 ("drm/vblank: Add vblank timer")
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: Louis Chauvet <louis.chauvet@bootlin.com>
Cc: Javier Martinez Canillas <javierm@redhat.com>
Cc: David Airlie <airlied@gmail.com>
Cc: Simona Vetter <simona@ffwll.ch>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: dri-devel@lists.freedesktop.org
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Link: https://patch.msgid.link/20251106073207.11192-1-tzimmermann@suse.de
(cherry picked from commit 3946d3ba99342f3b9996e621f05e7003d4308171)
---
drivers/gpu/drm/drm_vblank.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c
index 61e211fd3c9c..451ec9620226 100644
--- a/drivers/gpu/drm/drm_vblank.c
+++ b/drivers/gpu/drm/drm_vblank.c
@@ -2258,7 +2258,7 @@ int drm_crtc_vblank_start_timer(struct drm_crtc *crtc)
EXPORT_SYMBOL(drm_crtc_vblank_start_timer);
/**
- * drm_crtc_vblank_start_timer - Cancels the given CRTC's vblank timer
+ * drm_crtc_vblank_cancel_timer - Cancels the given CRTC's vblank timer
* @crtc: the CRTC
*
* Drivers should call this function from their CRTC's disable_vblank
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH 6.18.y 0/5] drm/vkms: Backport generic vblank timer to fix ABBA deadlock
2026-05-25 13:16 ` [PATCH 6.18.y 0/5] drm/vkms: Backport generic vblank timer to fix ABBA deadlock w15303746062
` (4 preceding siblings ...)
2026-05-25 13:16 ` [PATCH 6.18.y 5/5] drm/vblank: Fix kernel docs for vblank timer w15303746062
@ 2026-05-26 11:35 ` Sasha Levin
2026-05-26 12:06 ` w15303746062
5 siblings, 1 reply; 18+ messages in thread
From: Sasha Levin @ 2026-05-26 11:35 UTC (permalink / raw)
To: stable, gregkh
Cc: Sasha Levin, tzimmermann, maarten.lankhorst, mripard,
louis.chauvet, dri-devel, linux-kernel, Mingyu Wang, w15303746062
> [PATCH 6.18.y 0/5] drm/vkms: Backport generic vblank timer to fix ABBA deadlock
>
> 1/5 drm/vblank: Add vblank timer (74afeb812850)
> 2/5 drm/vblank: Add CRTC helpers for simple use cases (d54dbb5963bd)
> 3/5 drm/vkms: Convert to DRM's vblank timer (02e2681ffe1a)
> 4/5 drm/atomic: Increase timeout in drm_atomic_helper_wait_for_vblanks() (79ae8510b5b8)
> 5/5 drm/vblank: Fix kernel docs for vblank timer (3946d3ba9934)
Thanks for putting this together.
Looking at the five commits:
- 1/5 (74afeb812850) is the one that actually fixes the ABBA
deadlock you observed under Syzkaller; it adds the generic vblank
timer that replaces the open-coded vkms hrtimer path.
- 2/5 (d54dbb5963bd) adds new CRTC helpers for "simple use cases".
No Fixes:/Cc:stable, no described bug.
- 3/5 (02e2681ffe1a) is a refactor that converts vkms to the new
helpers. No Fixes:/Cc:stable, no described bug.
- 4/5 (79ae8510b5b8) is a v7.1-rc1 timeout bump that depends on 1/5.
It is not yet in any released stable, so applying it to 6.18.y
would put it on an LTS before any LTS contains it.
- 5/5 (3946d3ba9934) is a doc fix for 1/5.
Per stable-kernel-rules, what I need to queue is the minimum set that
fixes the bug. Could you explain, per patch, why 2/5..5/5 are required
to make 1/5 work / are required to actually fix the deadlock? If only
1/5 is needed, please resend just that one with your Signed-off-by
added (the carried patches today only have Thomas's S-o-b, which
breaks the chain of custody on a stable submission).
--
Thanks,
Sasha
^ permalink raw reply [flat|nested] 18+ messages in thread* Re:Re: [PATCH 6.18.y 0/5] drm/vkms: Backport generic vblank timer to fix ABBA deadlock
2026-05-26 11:35 ` [PATCH 6.18.y 0/5] drm/vkms: Backport generic vblank timer to fix ABBA deadlock Sasha Levin
@ 2026-05-26 12:06 ` w15303746062
2026-05-26 12:48 ` Maarten Lankhorst
0 siblings, 1 reply; 18+ messages in thread
From: w15303746062 @ 2026-05-26 12:06 UTC (permalink / raw)
To: Sasha Levin
Cc: stable, gregkh, tzimmermann, maarten.lankhorst, mripard,
louis.chauvet, dri-devel, linux-kernel, Mingyu Wang
Hi Sasha,
>Looking at the five commits:
>
> - 1/5 (74afeb812850) is the one that actually fixes the ABBA
> deadlock you observed under Syzkaller; it adds the generic vblank
> timer that replaces the open-coded vkms hrtimer path.
>
> - 2/5 (d54dbb5963bd) adds new CRTC helpers for "simple use cases".
> No Fixes:/Cc:stable, no described bug.
>
> - 3/5 (02e2681ffe1a) is a refactor that converts vkms to the new
> helpers. No Fixes:/Cc:stable, no described bug.
>
> - 4/5 (79ae8510b5b8) is a v7.1-rc1 timeout bump that depends on 1/5.
> It is not yet in any released stable, so applying it to 6.18.y
> would put it on an LTS before any LTS contains it.
>
> - 5/5 (3946d3ba9934) is a doc fix for 1/5.
>
>Per stable-kernel-rules, what I need to queue is the minimum set that
>fixes the bug. Could you explain, per patch, why 2/5..5/5 are required
>to make 1/5 work / are required to actually fix the deadlock? If only
>1/5 is needed, please resend just that one with your Signed-off-by
>added (the carried patches today only have Thomas's S-o-b, which
>breaks the chain of custody on a stable submission).
Thanks for the quick review and for pointing out the missing Signed-off-by. I apologize for that omission; it was my mistake during the cherry-pick process.
Regarding the dependency chain, I would like to clarify why commit 1/5 alone cannot fix the issue:
Commits 1/5 and 2/5 introduce the new generic vblank timer infrastructure to the DRM core but do *not* touch the vkms driver at all.
Commit 3/5 (02e2681ffe1a) is the actual fix that modifies `drivers/gpu/drm/vkms/vkms_crtc.c`. It removes the buggy open-coded hrtimer that causes the ABBA deadlock and switches vkms to use the new infrastructure introduced in 1/5 and 2/5.
Therefore, 1/5, 2/5, and 3/5 form an indivisible set. Applying only 1/5 would leave the deadlock in vkms completely unpatched.
As for 4/5 and 5/5 (the timeout bump and doc fix), Maarten Lankhorst (DRM maintainer) explicitly recommended pulling in this exact 5-commit list as the proper upstream fix for this specific vkms issue (see the mailing list link in this thread).
However, if you feel 4/5 and 5/5 introduce unnecessary risk for the 6.18.y stable tree, I can absolutely drop them and only submit 1/5, 2/5, and 3/5.
I am preparing a v2 patch series now with my Signed-off-by added to the chain of custody. Could you let me know if you prefer the full 5-patch series as recommended by DRM maintainers, or just the minimal 3-patch series?
Best regards,
Mingyu
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 6.18.y 0/5] drm/vkms: Backport generic vblank timer to fix ABBA deadlock
2026-05-26 12:06 ` w15303746062
@ 2026-05-26 12:48 ` Maarten Lankhorst
2026-05-26 12:50 ` Sasha Levin
0 siblings, 1 reply; 18+ messages in thread
From: Maarten Lankhorst @ 2026-05-26 12:48 UTC (permalink / raw)
To: w15303746062, Sasha Levin
Cc: stable, gregkh, tzimmermann, mripard, louis.chauvet, dri-devel,
linux-kernel, Mingyu Wang
Hello,
Den 2026-05-26 kl. 14:06, skrev w15303746062:
>
> Hi Sasha,
>
>> Looking at the five commits:
>>
>> - 1/5 (74afeb812850) is the one that actually fixes the ABBA
>> deadlock you observed under Syzkaller; it adds the generic vblank
>> timer that replaces the open-coded vkms hrtimer path.
>>
>> - 2/5 (d54dbb5963bd) adds new CRTC helpers for "simple use cases".
>> No Fixes:/Cc:stable, no described bug.
>>
>> - 3/5 (02e2681ffe1a) is a refactor that converts vkms to the new
>> helpers. No Fixes:/Cc:stable, no described bug.
>>
>> - 4/5 (79ae8510b5b8) is a v7.1-rc1 timeout bump that depends on 1/5.
>> It is not yet in any released stable, so applying it to 6.18.y
>> would put it on an LTS before any LTS contains it.
>>
>> - 5/5 (3946d3ba9934) is a doc fix for 1/5.
>>
>> Per stable-kernel-rules, what I need to queue is the minimum set that
>> fixes the bug. Could you explain, per patch, why 2/5..5/5 are required
>> to make 1/5 work / are required to actually fix the deadlock? If only
>> 1/5 is needed, please resend just that one with your Signed-off-by
>> added (the carried patches today only have Thomas's S-o-b, which
>> breaks the chain of custody on a stable submission).
>
> Thanks for the quick review and for pointing out the missing Signed-off-by. I apologize for that omission; it was my mistake during the cherry-pick process.
>
> Regarding the dependency chain, I would like to clarify why commit 1/5 alone cannot fix the issue:
>
> Commits 1/5 and 2/5 introduce the new generic vblank timer infrastructure to the DRM core but do *not* touch the vkms driver at all.
> Commit 3/5 (02e2681ffe1a) is the actual fix that modifies `drivers/gpu/drm/vkms/vkms_crtc.c`. It removes the buggy open-coded hrtimer that causes the ABBA deadlock and switches vkms to use the new infrastructure introduced in 1/5 and 2/5.
>
> Therefore, 1/5, 2/5, and 3/5 form an indivisible set. Applying only 1/5 would leave the deadlock in vkms completely unpatched.
>
> As for 4/5 and 5/5 (the timeout bump and doc fix), Maarten Lankhorst (DRM maintainer) explicitly recommended pulling in this exact 5-commit list as the proper upstream fix for this specific vkms issue (see the mailing list link in this thread).
>
> However, if you feel 4/5 and 5/5 introduce unnecessary risk for the 6.18.y stable tree, I can absolutely drop them and only submit 1/5, 2/5, and 3/5.
>
> I am preparing a v2 patch series now with my Signed-off-by added to the chain of custody. Could you let me know if you prefer the full 5-patch series as recommended by DRM maintainers, or just the minimal 3-patch series?
>
> Best regards,
> Mingyu
5/5 might strictly speaking not be needed as it's a documentation fix and I have no idea of the policy about those.
The reporter made a bug report of an ABBA deadlock that was fixed in upstream by the first 4 patches, perhaps it's good to those attach here to this discussion.
Kind regards,
~Maarten Lankhorst
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 6.18.y 0/5] drm/vkms: Backport generic vblank timer to fix ABBA deadlock
2026-05-26 12:48 ` Maarten Lankhorst
@ 2026-05-26 12:50 ` Sasha Levin
2026-05-26 12:59 ` Maarten Lankhorst
0 siblings, 1 reply; 18+ messages in thread
From: Sasha Levin @ 2026-05-26 12:50 UTC (permalink / raw)
To: Maarten Lankhorst
Cc: w15303746062, stable, gregkh, tzimmermann, mripard, louis.chauvet,
dri-devel, linux-kernel, Mingyu Wang
On Tue, May 26, 2026 at 02:48:55PM +0200, Maarten Lankhorst wrote:
>Hello,
>
>Den 2026-05-26 kl. 14:06, skrev w15303746062:
>>
>> Hi Sasha,
>>
>>> Looking at the five commits:
>>>
>>> - 1/5 (74afeb812850) is the one that actually fixes the ABBA
>>> deadlock you observed under Syzkaller; it adds the generic vblank
>>> timer that replaces the open-coded vkms hrtimer path.
>>>
>>> - 2/5 (d54dbb5963bd) adds new CRTC helpers for "simple use cases".
>>> No Fixes:/Cc:stable, no described bug.
>>>
>>> - 3/5 (02e2681ffe1a) is a refactor that converts vkms to the new
>>> helpers. No Fixes:/Cc:stable, no described bug.
>>>
>>> - 4/5 (79ae8510b5b8) is a v7.1-rc1 timeout bump that depends on 1/5.
>>> It is not yet in any released stable, so applying it to 6.18.y
>>> would put it on an LTS before any LTS contains it.
>>>
>>> - 5/5 (3946d3ba9934) is a doc fix for 1/5.
>>>
>>> Per stable-kernel-rules, what I need to queue is the minimum set that
>>> fixes the bug. Could you explain, per patch, why 2/5..5/5 are required
>>> to make 1/5 work / are required to actually fix the deadlock? If only
>>> 1/5 is needed, please resend just that one with your Signed-off-by
>>> added (the carried patches today only have Thomas's S-o-b, which
>>> breaks the chain of custody on a stable submission).
>>
>> Thanks for the quick review and for pointing out the missing Signed-off-by. I apologize for that omission; it was my mistake during the cherry-pick process.
>>
>> Regarding the dependency chain, I would like to clarify why commit 1/5 alone cannot fix the issue:
>>
>> Commits 1/5 and 2/5 introduce the new generic vblank timer infrastructure to the DRM core but do *not* touch the vkms driver at all.
>> Commit 3/5 (02e2681ffe1a) is the actual fix that modifies `drivers/gpu/drm/vkms/vkms_crtc.c`. It removes the buggy open-coded hrtimer that causes the ABBA deadlock and switches vkms to use the new infrastructure introduced in 1/5 and 2/5.
>>
>> Therefore, 1/5, 2/5, and 3/5 form an indivisible set. Applying only 1/5 would leave the deadlock in vkms completely unpatched.
>>
>> As for 4/5 and 5/5 (the timeout bump and doc fix), Maarten Lankhorst (DRM maintainer) explicitly recommended pulling in this exact 5-commit list as the proper upstream fix for this specific vkms issue (see the mailing list link in this thread).
>>
>> However, if you feel 4/5 and 5/5 introduce unnecessary risk for the 6.18.y stable tree, I can absolutely drop them and only submit 1/5, 2/5, and 3/5.
>>
>> I am preparing a v2 patch series now with my Signed-off-by added to the chain of custody. Could you let me know if you prefer the full 5-patch series as recommended by DRM maintainers, or just the minimal 3-patch series?
>>
>> Best regards,
>> Mingyu
>
>5/5 might strictly speaking not be needed as it's a documentation fix and I have no idea of the policy about those.
>
>The reporter made a bug report of an ABBA deadlock that was fixed in upstream by the first 4 patches, perhaps it's good to those attach here to this discussion.
I have no objection to taking all 5 if you're okay with it.
--
Thanks,
Sasha
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 6.18.y 0/5] drm/vkms: Backport generic vblank timer to fix ABBA deadlock
2026-05-26 12:50 ` Sasha Levin
@ 2026-05-26 12:59 ` Maarten Lankhorst
0 siblings, 0 replies; 18+ messages in thread
From: Maarten Lankhorst @ 2026-05-26 12:59 UTC (permalink / raw)
To: Sasha Levin
Cc: w15303746062, stable, gregkh, tzimmermann, mripard, louis.chauvet,
dri-devel, linux-kernel, Mingyu Wang
Den 2026-05-26 kl. 14:50, skrev Sasha Levin:
> On Tue, May 26, 2026 at 02:48:55PM +0200, Maarten Lankhorst wrote:
>> Hello,
>>
>> Den 2026-05-26 kl. 14:06, skrev w15303746062:
>>>
>>> Hi Sasha,
>>>
>>>> Looking at the five commits:
>>>>
>>>> - 1/5 (74afeb812850) is the one that actually fixes the ABBA
>>>> deadlock you observed under Syzkaller; it adds the generic vblank
>>>> timer that replaces the open-coded vkms hrtimer path.
>>>>
>>>> - 2/5 (d54dbb5963bd) adds new CRTC helpers for "simple use cases".
>>>> No Fixes:/Cc:stable, no described bug.
>>>>
>>>> - 3/5 (02e2681ffe1a) is a refactor that converts vkms to the new
>>>> helpers. No Fixes:/Cc:stable, no described bug.
>>>>
>>>> - 4/5 (79ae8510b5b8) is a v7.1-rc1 timeout bump that depends on 1/5.
>>>> It is not yet in any released stable, so applying it to 6.18.y
>>>> would put it on an LTS before any LTS contains it.
>>>>
>>>> - 5/5 (3946d3ba9934) is a doc fix for 1/5.
>>>>
>>>> Per stable-kernel-rules, what I need to queue is the minimum set that
>>>> fixes the bug. Could you explain, per patch, why 2/5..5/5 are required
>>>> to make 1/5 work / are required to actually fix the deadlock? If only
>>>> 1/5 is needed, please resend just that one with your Signed-off-by
>>>> added (the carried patches today only have Thomas's S-o-b, which
>>>> breaks the chain of custody on a stable submission).
>>>
>>> Thanks for the quick review and for pointing out the missing Signed-off-by. I apologize for that omission; it was my mistake during the cherry-pick process.
>>>
>>> Regarding the dependency chain, I would like to clarify why commit 1/5 alone cannot fix the issue:
>>>
>>> Commits 1/5 and 2/5 introduce the new generic vblank timer infrastructure to the DRM core but do *not* touch the vkms driver at all.
>>> Commit 3/5 (02e2681ffe1a) is the actual fix that modifies `drivers/gpu/drm/vkms/vkms_crtc.c`. It removes the buggy open-coded hrtimer that causes the ABBA deadlock and switches vkms to use the new infrastructure introduced in 1/5 and 2/5.
>>>
>>> Therefore, 1/5, 2/5, and 3/5 form an indivisible set. Applying only 1/5 would leave the deadlock in vkms completely unpatched.
>>>
>>> As for 4/5 and 5/5 (the timeout bump and doc fix), Maarten Lankhorst (DRM maintainer) explicitly recommended pulling in this exact 5-commit list as the proper upstream fix for this specific vkms issue (see the mailing list link in this thread).
>>>
>>> However, if you feel 4/5 and 5/5 introduce unnecessary risk for the 6.18.y stable tree, I can absolutely drop them and only submit 1/5, 2/5, and 3/5.
>>>
>>> I am preparing a v2 patch series now with my Signed-off-by added to the chain of custody. Could you let me know if you prefer the full 5-patch series as recommended by DRM maintainers, or just the minimal 3-patch series?
>>>
>>> Best regards,
>>> Mingyu
>>
>> 5/5 might strictly speaking not be needed as it's a documentation fix and I have no idea of the policy about those.
>>
>> The reporter made a bug report of an ABBA deadlock that was fixed in upstream by the first 4 patches, perhaps it's good to those attach here to this discussion.
>
> I have no objection to taking all 5 if you're okay with it.
>
Mingyu made an effort to reproduce, check if commits fixed it and then checked if other
drivers needed the same bug fixed. I'm ok with the series.
Kind regards,
~Maarten Lankhorst
^ permalink raw reply [flat|nested] 18+ messages in thread