Suspend hangs on PRIME render-offload laptop: NVIDIA forces VT switch despite having no scanout

NVIDIA driver: 595.99.02, open kernel modules; also reproduced on 595.71.05
OS: NixOS 26.05 (Yarara)
Kernel: Linux 6.18.53, x86_64
systemd: 260.4
Xorg: 1.21.1.24, startx on tty1, i3, no display manager
Hardware: Dell XPS 15 9520, Intel Iris Xe + NVIDIA GeForce RTX 3050 Ti Laptop GPU
Incidence: Always

Setup

This is a PRIME render-offload configuration:

  • NVreg_DynamicPowerManagement=0x02
  • nvidia-drm.modeset=1
  • nvidia-drm.fbdev=1
  • NVreg_UseKernelSuspendNotifiers=1
  • NVreg_PreserveVideoMemoryAllocations=1

The Intel iGPU owns every display connector (eDP-1, HDMI-A-1, DP-1 through DP-4). The NVIDIA GPU has no display connectors / usable scanout and logs:

nvidia-drm: Cannot find any crtc or sizes

It reaches D3cold when idle.

Bug

The NVIDIA driver registers the dGPU as requiring a suspend/resume VT switch even though it does not drive a display.

Linux skips the suspend VT switch only when no registered device requires one. The DRM fbdev helper sets skip_vt_switch = true, which results in:

pm_vt_switch_required(fb_info->device, false);

i915 therefore permits switchless suspend on this machine.

NVIDIA overrides this. In 595.99.02, the PCI probe path in kernel-open/nvidia/nv-pci.c registers:

pm_vt_switch_required(nvl->dev, NV_TRUE);

With NVIDIA DRM fbdev enabled, kernel-open/nvidia-drm/nvidia-drm-drv.c later explicitly reasserts the requirement after fbdev setup:

/*
 * The fbdev setup functions above may override the
 * `pm_vt_switch_required` state of our PCI device. For now, a VT switch
 * is required during suspend and resume.
 */
pm_vt_switch_required(dev->dev, true);

Since any registered true requirement makes the kernel perform the VT switch, the otherwise headless NVIDIA GPU forces a switch to the suspend console.

Failure

With systemd’s default user-session freezing enabled, systemd-sleep freezes user.slice before entering kernel suspend. This includes the X session.

The kernel then enters pm_prepare_console() and tries to switch from the X VT to the suspend console. Because X is already frozen, the VT handoff never completes.

A watchdog dumping the blocked systemd-sleep process after 120 seconds captured:

__vt_event_wait.part.0+0x5c/0xb0
vt_waitactive+0x141/0x1d0
vt_move_to_console+0x68/0xa0
pm_prepare_console+0x26/0x50
pm_suspend.cold+0x15e/0x36b
state_store+0x6c/0xd0
kernfs_fop_write_iter+0x189/0x230
vfs_write+0x260/0x480
ksys_write+0x73/0xf0
do_syscall_64+0xd6/0x7c0
entry_SYSCALL_64_after_hwframe+0x77/0x7f

The journal reaches:

PM: suspend entry (s2idle)
Filesystems sync: ...

but never reaches the kernel’s Freezing user space processes stage.

The screen is black, the machine remains awake with the fans running, and a forced power-off is required.

This reproduces consistently with unmodified 595.71.05 and 595.99.02.

As a diagnostic control, setting:

SYSTEMD_SLEEP_FREEZE_USER_SESSIONS=false

allows the machine to enter and leave suspend, confirming that the initial hang depends on the interaction between the frozen X session and subsequent VT switch. This is not a proposed workaround.

The forced VT switch still causes a separate problem on this system: after returning from VT 63, the startx X session remains paused. Closely matching reports:

Reproduction

  1. Use a PRIME render-offload laptop where the NVIDIA GPU drives no display.
  2. Load the NVIDIA modules with DRM modesetting/fbdev enabled.
  3. Log in on a text VT and run startx.
  4. Run systemctl suspend or close the lid.

With default systemd user-session freezing, suspend hangs in:

pm_prepare_console()
  -> vt_move_to_console()
     -> vt_waitactive()

Workaround / verification

For testing, I changed both NVIDIA registrations to false:

--- a/kernel-open/nvidia/nv-pci.c
+++ b/kernel-open/nvidia/nv-pci.c
@@
-    pm_vt_switch_required(nvl->dev, NV_TRUE);
+    pm_vt_switch_required(nvl->dev, NV_FALSE);
--- a/kernel-open/nvidia-drm/nvidia-drm-drv.c
+++ b/kernel-open/nvidia-drm/nvidia-drm-drv.c
@@
-        pm_vt_switch_required(dev->dev, true);
+        pm_vt_switch_required(dev->dev, false);

With this patch and otherwise unchanged configuration, including systemd’s default session freezing:

  • suspend and resume complete normally;
  • X remains usable after resume;
  • no suspend VT switch occurs;
  • a test recorded approximately 9.5 s of hardware sleep, with 99.99% of that interval in S0ix;
  • keyboard wake through i8042 works normally.

The failure is reproducible without the patch and disappears with it.

I apply this patch only on this PRIME render-offload machine. I am not proposing unconditional false as the general fix: NVIDIA GPUs that own a console or display output may require different behavior.

Expected behavior

A render-offload NVIDIA GPU with no console or scanout responsibility should not force the system-wide suspend VT switch.

The driver could make pm_vt_switch_required() reflect the GPU’s actual display role rather than registering true simply because the NVIDIA PCI/DRM device is present.

On the same machine with the NVIDIA modules unloaded, no suspend VT switch occurs and suspend/resume works normally.

Scope

The proprietary 595.99.02 package contains the same relevant pm_vt_switch_required() calls in its kernel sources, so this does not appear specific to the open modules.

I have only run the open modules.

Related reports

The systemd user-session-freezing interaction has also caused NVIDIA suspend failures in other distributions:

  • Debian #1072722 — suspend hangs with NVIDIA after user-session freezing was introduced; disabling SYSTEMD_SLEEP_FREEZE_USER_SESSIONS was adopted as an NVIDIA package workaround
    https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1072722

  • Gentoo — NVIDIA suspend/resume failure after systemd 256; the journal shows user.slice successfully frozen before the failure, and disabling SYSTEMD_SLEEP_FREEZE_USER_SESSIONS restores suspend/resume. Gentoo subsequently added the workaround to its NVIDIA package
    https://forums.gentoo.org/viewtopic-p-8845051.html

Additional reports showing the same suspend failure pattern or closely related VT-switch behavior:

  • NVIDIA Developer Forums — NVIDIA staff describes the same deadlock mechanism: systemd freezes Xorg before kernel suspend, then a kernel driver requests a VT switch and Xorg cannot respond. The NVIDIA package workaround disables user-session freezing.
    https://forums.developer.nvidia.com/t/ubuntu-24-fails-to-resume-after-hibernation-due-to-nvidia-issue/370371

  • systemd #33462 — suspend deadlocks because Xorg is frozen before the kernel requests a VT switch. This uses the Radeon Xorg driver rather than NVIDIA, but demonstrates the same kernel-side failure mechanism: frozen Xorg + required suspend VT switch → deadlock. It also discusses DRM drivers opting out of the suspend VT switch.
    https://github.com/systemd/systemd/issues/33462

  • Arch Linux — systemd 256 suspend regression affecting NVIDIA systems. Suspend works again when SYSTEMD_SLEEP_FREEZE_USER_SESSIONS=false, matching the same user-session-freezing interaction seen here.
    https://bbs.archlinux.org/viewtopic.php?id=296954

  • elogind #234 — NVIDIA Optimus + startx; suspend hangs during VT switching. Direct suspend through /sys/power/state works, while the VT-switch path hangs, making this relevant to the NVIDIA/Xorg VT behavior involved here.
    https://github.com/elogind/elogind/issues/234