Thorsten,
So I built vanilla 7.0-rc1. I also added these kernel params:
nvidia-drm.modeset=0
modprobe.blacklist=nvidia,nvidia_drm,nvidia_modeset,nvidia_uvm
rd.driver.blacklist=nvidia,nvidia_drm,nvidia_modeset,nvidia_uvm
then I booted into it. this is what my nvidia loadout looks like on my
usual 6.18.9:
+ uname -r
6.18.9-arch1-2
+ lsmod
+ grep -E nvidia|nouveau
nvidia_drm 147456 3
nvidia_modeset 2121728 3 nvidia_drm
nvidia_uvm 2568192 0
nvidia 16306176 34 nvidia_uvm,nvidia_modeset
drm_ttm_helper 16384 2 nvidia_drm,xe
video 81920 4 thinkpad_acpi,xe,i915,nvidia_modeset
+ lspci -nnk
+ grep -iA2 VGA\|3D\|Display
00:02.0 VGA compatible controller [0300]: Intel Corporation
TigerLake-H GT1 [UHD Graphics] [8086:9a60] (rev 01)
Subsystem: Lenovo Device [17aa:22d8]
Kernel driver in use: i915
--
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation
TU117GLM [T1200 Laptop GPU] [10de:1fbc] (rev a1)
Subsystem: Lenovo Device [17aa:22d8]
Kernel driver in use: nvidia
and this is what it looked like in vanilla 7.0-rc1 with blacklisted nvidia:
+ uname -r
7.0.0-rc1-dirty
+ lsmod
+ grep -E nvidia|nouveau
+ lspci -nnk
+ grep -iA2 VGA\|3D\|Display
00:02.0 VGA compatible controller [0300]: Intel Corporation
TigerLake-H GT1 [UHD Graphics] [8086:9a60] (rev 01)
Subsystem: Lenovo Device [17aa:22d8]
Kernel driver in use: i915
--
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation
TU117GLM [T1200 Laptop GPU] [10de:1fbc] (rev a1)
Subsystem: Lenovo Device [17aa:22d8]
Kernel modules: nouveau
when I did a VT switch, it froze. my 90s failsafe triggered and rebooted me.
then I rebuilt 7.0-rc1 with my patch, rebooted with the same efi
loader, and was able to perform VT switching without any issues.
Andrés
On Mon, Feb 23, 2026 at 8:26 AM Thorsten Leemhuis
<[email protected]> wrote:
>
>
>
> On 2/23/26 09:10, Ricardo Ribalda wrote:
> > Hi Andrés
> >
> > Thanks for doing the bisecting
> >
> > On Sun, 22 Feb 2026 at 22:56, Andrés Pérez <[email protected]> wrote:
> >>
> >> # OVERVIEW
> >>
> >> Since kernel v6.16.1, switching from an X11 session to a text VT and back
> >> freezes the display on a ThinkPad P15 Gen 2. The system remains responsive
> >> over SSH; only the display is frozen. Bisecting identified commit
> >> d1b618e7954802fe ("media: uvcvideo: Do not turn on the camera for some
> >> ioctls") as the trigger. Reverting the logic change in that commit
> >> fixes VT switching
> >> on v6.16.1, v6.17.9, and v6.18.9, but that is not an actual solution.
> >> Wayland
> >> compositors (e.g., river and sway) are not affected.
> >>
> >> Last good: v6.15.9
> >> First bad: v6.16.1
> >> Bisect result: d1b618e7954802fe media: uvcvideo: Do not turn on the
> >> camera for some ioctls
> >>
> >> ## Hardware: Lenovo ThinkPad P15 Gen 2i (20YQ0031US)
> >> CPU: Intel Core i7-11800H (Tiger Lake-H)
> >> iGPU: Intel UHD Graphics (TGL GT1)
> >> dGPU: NVIDIA T1200 (not involved in eDP output; driver: nvidia-open)
>
> Could this be caused by nvidia's own driver, even if it is not supposed
> to be involved? Might be worth ruling out with a proper vanilla kernel,
> ideally really fresh, so 7.0-rc1.
>
> Ciao, Thorsten
>
> >> Display: 15.6" 1920x1080 eDP, 10 bpc capable (EDID 1.4)
> >> Webcam: Integrated Camera on PCH xHCI (Bus 003 Port 004)
> >> Firmware: LENOVO N37ET61W (1.97)
> >> OS: Arch Linux, Nix home-manager, X11 + xmonad, no display manager
> >>
> >> ## Symptoms and reproduction steps:
> >> 1. Boot, start X11 on tty1 (startx).
> >> 2. Switch to tty2 (Ctrl+Alt+F2): works.
> >> 3. Switch back to tty1 (Ctrl+Alt+F1): display freezes.
> >> - Frozen on the last frame shown before switching away.
> >> - System is fully responsive over SSH.
> >> - Other VTs switch normally between each other as long as X11 is
> >> not active on them.
> >> - Killing X does not recover the display. A reboot is required.
> >>
> >> # DEBUG ANALYSIS
> >>
> >> On v6.16.1, the VT switch back to X triggers a full modeset due to pipe
> >> configuration mismatches detected by intel_pipe_config_compare:
> >>
> >> [drm:intel_pipe_config_compare] fastset requirement not met in pipe_bpp
> >> (expected 30, found 24)
> >> [drm:intel_pipe_config_compare] fastset requirement not met in dp_m_n
> >> (expected link 269484/524288, found link 336855/524288)
> >> [drm:intel_pipe_config_compare] fastset requirement not met in
> >> dpll_hw_state
> >> (expected cfgcr0: 0xe001a5, found cfgcr0: 0x1c2)
> >> [drm:intel_pipe_config_compare] fastset requirement not met in port_clock
> >> (expected 270000, found 216000)
> >> [drm:intel_atomic_check] forcing full modeset
> >>
> >> On v6.15.9, the same VT switch shows no such messages.
> >> no pipe_config_compare runs, no modeset, no freeze.
> >>
> >> # BISECT AND VERIFICATION
> >>
> >> The bisect converged on d1b618e7954802fe in the uvcvideo driver. This
> >> commit adds a switch statement to uvc_v4l2_unlocked_ioctl that allows
> >> certain V4L2 IOCTLS to call video_ioctl2 directly without first calling
> >> uvc_pm_get/uvc_pm_put. Prior to this commit, all ioctls called uvc_pm_get
> >> before video_ioctl2.
> >>
> >> ## VT switching verification across kernel versions:
> >>
> >> v6.12.74 arch pkg: WORKS
> >> v6.15.9 arch pkg: WORKS
> >> v6.15.9 from source: WORKS
> >> v6.16.1 with d1b618e reverted: WORKS
> >> v6.17.9 with PM wrapping restored: WORKS
> >> v6.18.9 with PM wrapping restored: WORKS
> >>
> >> v6.16.1 from source: FREEZES
> >> v6.16.1 arch pkg: FREEZES
> >> v6.17.9 arch pkg: FREEZES
> >> v6.18.9 from source: FREEZES
> >> v6.18.9 arch pkg: FREEZES
> >>
> >> ## Things that do not eliminate the freeze
> >>
> >> - module_blacklist=uvcvideo on boot
> >> - CONFIG_USB_VIDEO_CLASS=n (compiled out)
> >
> > This is puzzling me a bit... You are saying that if you do not build
> > the uvc driver, the freeze is still happening?
> >
> > Am I understanding this correctly?
> >
> >> - i915.enable_psr=0
> >> - Bypassing intel_vrr_transcoder_enable/disable (no-op)
> >> - xrandr --output eDP-1 --set "max bpc" 10
> >> - Xorg config FBDepth 30 (No effect on pipe_bpp)
> >>
> >> ## Workaround patch
> >>
> >> Reverting the optimization from d1b618e to restore the unconditional
> >> uvc_pm_get/put wrapping for all ioctls. This is not a proper fix.
> >>
> >> diff --git a/drivers/media/usb/uvc/uvc_v4l2.c
> >> b/drivers/media/usb/uvc/uvc_v4l2.c
> >> index 9e4a251eca88..15057b47ec4f 100644
> >> --- a/drivers/media/usb/uvc/uvc_v4l2.c
> >> +++ b/drivers/media/usb/uvc/uvc_v4l2.c
> >> @@ -1199,33 +1199,12 @@ static long uvc_v4l2_unlocked_ioctl(struct file
> >> *file,
> >> unsigned int converted_cmd = v4l2_translate_cmd(cmd);
> >> int ret;
> >>
> >> - /* The following IOCTLs need to turn on the camera. */
> >> - switch (converted_cmd) {
> >> - case UVCIOC_CTRL_MAP:
> >> - case UVCIOC_CTRL_QUERY:
> >> - case VIDIOC_G_CTRL:
> >> - case VIDIOC_G_EXT_CTRLS:
> >> - case VIDIOC_G_INPUT:
> >> - case VIDIOC_QUERYCTRL:
> >> - case VIDIOC_QUERYMENU:
> >> - case VIDIOC_QUERY_EXT_CTRL:
> >> - case VIDIOC_S_CTRL:
> >> - case VIDIOC_S_EXT_CTRLS:
> >> - case VIDIOC_S_FMT:
> >> - case VIDIOC_S_INPUT:
> >> - case VIDIOC_S_PARM:
> >> - case VIDIOC_TRY_EXT_CTRLS:
> >> - case VIDIOC_TRY_FMT:
> >> - ret = uvc_pm_get(handle->stream->dev);
> >> - if (ret)
> >> - return ret;
> >> - ret = video_ioctl2(file, cmd, arg);
> >> - uvc_pm_put(handle->stream->dev);
> >> + ret = uvc_pm_get(handle->stream->dev);
> >> + if (ret)
> >> return ret;
> >> - }
> >> -
> >> - /* The other IOCTLs can run with the camera off. */
> >> - return video_ioctl2(file, cmd, arg);
> >> + ret = video_ioctl2(file, cmd, arg);
> >> + uvc_pm_put(handle->stream->dev);
> >> + return ret;
> >> }
> >>
> >> const struct v4l2_ioctl_ops uvc_ioctl_ops = {
> >>
> >> Andrés
> >>
> >
> >
>