Deadlock between DIFR prefetch worker and KMS modeset path (nvidia_modeset), 595.84 and 610.43.02
Summary
On a Legion Pro 5 16IAX10H with an RTX 5070 Ti Laptop GPU, the desktop display freezes permanently
while the rest of the system stays fully functional. The cause is a lock inversion inside
nvidia_modeset:
- The
nvidia-modeset/kernel thread runs a DIFR (Display Idle Frame Refresh) prefetch and spins
indefinitely innvWriteGpEntry, in stateR, while holding the NVKMS PM lock. - Any subsequent atomic modeset/flip from the compositor enters
ApplyModeSetConfig→nvkms_ioctl_from_kapi_try_pmlockand blocks in stateDon that same
semaphore, forever.
The result is a display that never updates again. The kernel, audio, storage, networking and input
all keep working normally — during one event the machine continued printing hung-task traces every
30 s for 3.5 minutes, and audio from a playing video kept running without a glitch while the image
was frozen on a single frame.
This reproduces on two different driver branches (595.84 and 610.43.02) and two different
kernels (7.0.0-28 and 7.0.0-29), with a function-for-function identical holder-side stack.
Important: Currently running 610.43.02. The attached nvidia-bug-report.log.gz captures older boots and its dmesg shows 595.84, so the deadlock traces are not in it — they are in the separate trace-595.txt and trace-610.txt files.
System
| Machine | Lenovo Legion Pro 5 16IAX10H (83LU) |
| BIOS | Q6CN79WW, 2026-04-23 |
| CPU | Intel Core Ultra 9 275HX |
| iGPU | Intel Arrow Lake-S [8086:7d67] (rev 06) |
| dGPU | NVIDIA GB205M / GeForce RTX 5070 Ti Laptop GPU [10de:2f58] (rev a1) |
| VBIOS | 98.05.41.00.0B |
| OS | Ubuntu 26.04 LTS |
| Kernels | 7.0.0-29-generic (610.43.02), 7.0.0-28-generic (595.84) |
| Driver | nvidia-driver-610-open 610.43.02 — open kernel modules; also seen on nvidia-driver-595-open 595.84 |
| Session | GNOME on Wayland (mutter), hybrid graphics |
| Module options | nvidia_drm modeset=1, NVreg_PreserveVideoMemoryAllocations=1, NVreg_TemporaryFilePath=/var |
Display topology — relevant, because the dGPU drives a real output:
- Internal panel
eDP-1on the Intel iGPU. - External monitor on
HDMI-A-1, which is wired to the dGPU. So the NVIDIA display engine is in
continuous use during normal desktop work, not only for GPU offload.
Symptoms
- Display stops updating entirely and never recovers. Observed frozen for 20 minutes on one
occasion and 3.5 minutes on another (the user gave up and forced a reboot both times). - Audio continues perfectly. A YouTube video that was playing kept its audio stream running while
the image stayed frozen on one frame — the flip never completed. - The kernel remains fully healthy. Hung-task traces continue to be written to disk, the
filesystem stays mounted read-write, and SSH login from another machine still works. systemd-logind’s power-key handling does not help, because GNOME holds ablock-mode inhibitor
onhandle-power-keyand its shutdown dialog cannot be drawn on the wedged display. Recovery
requires SysRq or SSH.
Root cause
Holder: DIFR prefetch worker, spinning while holding the PM lock
The nvidia-modeset/ kthread is in state R (running, never yields the lock) with this stack:
RIP: 0010:nvWriteGpEntry+0xf7/0x370 [nvidia_modeset]
? nvPushKickoff+0x28/0x50 [nvidia_modeset]
? PrefetchHelperSurfaceEvo+0x45c/0x650 [nvidia_modeset]
? nvDIFRPrefetchSurfaces+0x135/0x1f0 [nvidia_modeset]
? DifrPrefetchEventDeferredWork+0x16/0x30 [nvidia_modeset]
? nvkms_kthread_q_callback+0xe9/0x190 [nvidia_modeset]
? _main_loop+0x99/0x160 [nvidia_modeset]
? kthread+0xf7/0x130
? ret_from_fork+0x195/0x2a0
Register/code context at the faulting instruction (610.43.02 event):
RIP: 0010:nvWriteGpEntry+0xf7/0x370 [nvidia_modeset]
Code: ... 48 8b 83 10 01 00 00 <8b> 38 c1 ef 12 01 ff 39 fd 74 a2 ...
RSP: 0018:ffffce3ec0a47cf8 EFLAGS: 00000246
RAX: ffff8d174b933000 RBX: ffff8d1726a4f430 RCX: ffffce3ec696a378
RDX: ffff8d174b945000 RSI: 0000000000000384 RDI: 0000000000000004
RBP: 0000000000000004 R08: 0000000000000000 R09: 0000000000000001
R10: 0000000000000002 R11: 0000000000000010 R12: ffffce3ec12930d8
R13: 0000000000000384 R14: 0000000000000314 R15: 0000000000000000
The trapped instruction loads a dword through a pointer, shifts it right by 18, adds, compares
against a cached value and branches backwards on equality. That is consistent with polling a
pushbuffer GET pointer for free space — i.e. an unbounded wait for GPU progress performed while
the NVKMS PM lock is held. Because the thread stays in state R, the lock is never released and
the wait never terminates.
Waiter: compositor atomic commit, blocked forever
INFO: task KMS thread:90142 blocked for more than 30 seconds.
task:KMS thread state:D pid:90142 tgid:90127 ppid:89457
Call Trace:
__schedule+0x2bb/0x650
schedule+0x27/0x90
schedule_timeout+0xcf/0x110
___down_common+0x108/0x1e0
__down_common+0x5a/0x180
__down+0x1d/0x30
down+0x5e/0x80
nvkms_ioctl_from_kapi_try_pmlock+0x55/0xc0 [nvidia_modeset]
ApplyModeSetConfig+0x60a/0xc70 [nvidia_modeset]
? nv_drm_atomic_apply_modeset_config+0x79d/0xb40 [nvidia_drm]
? nv_drm_plane_atomic_check+0x10a/0x6a0 [nvidia_drm]
? nv_drm_atomic_check+0x12d/0x150 [nvidia_drm]
? drm_atomic_check_only+0x199/0x420
? drm_atomic_nonblocking_commit+0x18/0x70
? drm_mode_atomic_ioctl+0x57e/0x910
? drm_ioctl_kernel+0xb5/0x110
? drm_ioctl+0x309/0x5f0
? nv_drm_ioctl+0x38/0x420 [nvidia_drm]
? __x64_sys_ioctl+0xa3/0x100
? do_syscall_64+0x105/0x5a0
? entry_SYSCALL_64_after_hwframe+0x76/0x7e
</TASK>
INFO: task KMS thread:90142 blocked on a semaphore likely last held by task nvidia-modeset/:1854
KMS thread here is mutter’s own KMS thread (tgid:90127 is gnome-shell). The kernel’s own
hung-task detector names the culprit directly: “blocked on a semaphore likely last held by task
nvidia-modeset/”.
The waiter is in drm_mode_atomic_ioctl — a page flip. That is exactly why the video image froze
on one frame while its audio continued.
Confirmation across driver branches
The same event on 595.84 / kernel 7.0.0-28 (2026-07-28), holder side:
RIP: 0010:nvWriteGpEntry+0xfe/0x370 [nvidia_modeset]
? nvPushKickoff+0x28/0x50 [nvidia_modeset]
? PrefetchHelperSurfaceEvo+0x45c/0x650 [nvidia_modeset]
? nvDIFRPrefetchSurfaces+0x135/0x1f0 [nvidia_modeset]
? DifrPrefetchEventDeferredWork+0x16/0x30 [nvidia_modeset]
? nvkms_kthread_q_callback+0xe9/0x1a0 [nvidia_modeset]
? _main_loop+0x99/0x170 [nvidia_modeset]
waiter side:
nvkms_ioctl_from_kapi_try_pmlock+0x55/0xd0 [nvidia_modeset]
ApplyModeSetConfig+0x59e/0xba0 [nvidia_modeset]
? nv_drm_atomic_apply_modeset_config+0x80b/0x9c0 [nvidia_drm]
Identical call chain, only offsets differ. On that occasion the hung-task detector reported the same
thread still blocked after 1228 seconds (20 minutes), escalating 122 → 245 → 368 → 491 → 614 →
737 → 860 → 983 → 1105 → 1228 s. It does not recover.
Trigger conditions
The pattern across observed events:
- The display goes idle — the user steps away and the screen blanks, or the content is static
for a long period. This is DIFR’s engagement condition. - A modeset or flip then arrives. Observed triggers: opening a new window, launching a browser, a
video beginning playback, and a GNOME fast-user-switch to a second session. - The deadlock takes hold at the first atomic commit after the DIFR prefetch has started.
The most recent event, with timestamps:
(user away, screen idle) -> DIFR prefetch begins, PM lock taken
19:16:41 GNOME fast user switch to a second profile; new gnome-shell (pid 90127) starts
Chrome launched; a YouTube tab resumes playback
19:17:12 mutter's KMS thread wedges on the PM lock
19:17:42 hung-task detector confirms (repeats at 60, 90, 120, 151 s)
19:20:11 forced power-off
Note this machine had not suspended — there were zero suspend/resume events in that 7-hour
uptime. Plain display idle is sufficient.
Frequency is roughly monthly under normal desktop use, which suggests a race window rather than a
deterministic ordering bug. Confirmed occurrences: 2026-07-28, 2026-08-13, 2026-08-17, plus two
earlier hard power-offs on 2026-07-29 and 2026-08-04 consistent with the same failure.
Ruled out
These were all checked against the system journal and are not involved:
- No kernel panic or oops. The kernel stays healthy throughout.
- No Xid errors at any point.
- No OOM. 30 GB RAM, swap untouched at 0 B used.
- No thermal throttling or critical-temperature events.
- No MCE, EDAC or PCIe AER errors.
- No filesystem or NVMe errors. Disk health is clean.
The only NVRM messages present are two benign boot-time ones that appear on every boot regardless
(PlatformRequestHandler failed to get target temp from SBIOS, and an
Unable to read EDID for display device DP-0 warning).
Notes for triage
- There is no user-facing way to disable DIFR as a workaround.
modinfo nvidia_modeseton 610.43.02
exposes 15 parameters and none of them control DIFR. The DIFR symbols are still present in
610.43.02 (nvDIFRPrefetchSurfaces,DifrPrefetchEventDeferredWork,nvDIFRNotifyFlip,
nvDIFRAllocate,nvDIFRFree,nvRmRegisterDIFREventHandler), so the feature was not removed
between branches. - A module parameter to disable DIFR would be a very welcome stopgap even ahead of a real fix.
- The apparent defect is that the DIFR prefetch path performs an unbounded wait on GPU pushbuffer
progress while holding a lock that the modeset path needs. A bounded timeout with a fallback that
drops the prefetch, or releasing the PM lock across the kickoff wait, would both break the
deadlock.
Attachments
nvidia-bug-report.log.gz(generated withsudo nvidia-bug-report.sh)- Full kernel traces for both events, as captured from
journalctl.
kernel.hung_task_timeout_secs was lowered from 120 to 30 on this machine specifically to capture
these traces, so the 30/60/90/120/151 s escalation in the 610.43.02 event reflects that setting, not
a kernel default.
trace-610.txt (3.5 KB)
trace-595.txt (2.6 KB)
nvidia-bug-report.log.gz (847.8 KB)