Conversation
(cherry picked from commit 3f5aece)
REQUEST_UPDATE can complete immediately when dirty rectangles are already pending, bypassing the UPDATE_READY notification path. This allows userspace frame acquisition to proceed independently of the DRM vblank cadence. Introduce per-device update state driven by the vblank timer. A frame token is published for each permitted vblank slot and consumed by the immediate REQUEST_UPDATE path. If the current slot has already been consumed, the request remains pending until a later slot. UPDATE_READY notification is dispatched through workqueue context rather than directly from the hrtimer callback, keeping painter locking out of timer context. Use the same hrtimer implementation from both modern CRTC vblank callbacks and the legacy drm_driver vblank callbacks so the pacing path also remains available on older supported kernels.
Add a writable max_fps module parameter for limiting userspace frame acquisition without changing the DRM mode or vblank cadence. A fractional accumulator derives permitted update slots from the active refresh rate, allowing non-divisor rates such as 45 FPS on a 60 Hz mode. max_fps=0, or a value greater than or equal to the active refresh rate, preserves native update cadence.
xwr-ron
force-pushed
the
feature/vblank-update-pacing
branch
from
September 13, 2026 00:12
3e6c4d5 to
6cb6552
Compare
xwr-ron
marked this pull request as ready for review
September 13, 2026 00:16
mkaspryk-synaptics
force-pushed
the
main
branch
from
October 2, 2026 10:39
fb2ff77 to
558af9c
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR builds on and extends #562 by @IraSkyx.
The original hrtimer-based vblank commit is included with its original
authorship and cherry-pick attribution. On top of that work, this PR:
vblank;
REQUEST_UPDATEfast path that can otherwise bypassUPDATE_READY;of hrtimer context;
max_fpslimit without changing the DRM modeor vblank cadence.
max_fps=0preserves the native update cadence.Motivation
I started investigating consistently high CPU usage in
DisplayLinkManager during fullscreen video playback on a 1920x1080@60
DisplayLink output.
#562 significantly improved the situation by introducing hrtimer-based
vblank delivery and proper DRM frame pacing.
However, userspace frame acquisition could still proceed at the full
display refresh rate.
Tracing
evdi_painter_grabpix_ioctlshowed approximately one GRABPIXoperation per display refresh.
The important second path turned out to be
evdi_painter_request_update_ioctl: when dirty rectangles are alreadyavailable,
REQUEST_UPDATEcan complete immediately, bypassingUPDATE_READY.This PR adds explicit update-slot gating to cover both paths.
Implementation
The vblank timer publishes a frame token for each permitted update slot.
The immediate
REQUEST_UPDATEdirty-data path atomically consumes thattoken. If the current slot has already been consumed, the request remains
pending until a later slot.
Pending
UPDATE_READYnotification is dispatched through workqueuecontext rather than from the hrtimer callback, keeping painter locking
out of timer context.
For kernel API compatibility, the hrtimer enable/disable implementation
is shared by both the modern CRTC vblank callbacks and the legacy
drm_drivervblank callbacks.The optional
max_fpsparameter uses a fractional accumulator againstthe active refresh rate. This permits rates that are not integer
divisors of the display refresh.
For example, on a 60 Hz mode:
max_fps=45permits three update slots for every four vblanks;max_fps=30permits one update slot for every two vblanks.The CRTC mode and DRM vblank cadence are left unchanged.
Runtime results
Test output:
bpftrace/proc/<pid>/statThe measurements show that frame acquisition follows the configured
limit while the physical output remains at 60 Hz.
The CPU figures are workload- and system-specific and are included to
show the observed behavior rather than as a general performance
benchmark.
Boot / DisplayLink test
The final tree was also tested through a cold boot with
max_fps=45configured through modprobe options.
After boot:
max_fpsvalue was correctly set to 45.Build compatibility
The final module was successfully built against:
The 6.18.9 custom-kernel build emitted only the expected compiler-version
warning because that kernel had originally been built with an older GCC.
The Linux 5.10 build used a vanilla kernel source tree. Preparing that
older tree with the current GCC required an unrelated host-tool
compatibility fix in
tools/lib/subcmd; after kernel preparation, theEVDI module itself built successfully through the legacy API path.
Feature detection did not select the modern CRTC atomic-state/commit
callback variants for that build.
Relationship to #562
This work directly builds on the hrtimer vblank implementation introduced
in #562 by @IraSkyx.
Because #562 is still open, its commit is preserved here with the original
author and cherry-pick attribution.
If the maintainers prefer #562 to land independently first, I am happy to
rebase this PR on top of it or split the follow-up commits as appropriate.