Ricardo, Listen, I'm right there with you, scratching my head. First thing I did when I bisected to that commit was modprobe -r that module. Easy sacrifice; I don't use my camera that often. When it still froze, I assumed that maybe something related to module init was still lingering, so I disabled it by kernel boot param. When that didn't work, I just didn't build it in at all. Then I ignored it and tried a few other things. Eventually I came back to that commit. Instead of patching any code, I just added a comment to the file, thinking maybe this is just some build artifact that's causing a false positive. No dice. So far, the only thing that has allowed VT switching to work is restoring those PM calls around the video_ioctl2 call. I am not presenting it as a solution (quite the contrary!), I am presenting it solely because it's all I've got to go on.
Andrés On Mon, Feb 23, 2026 at 8:18 AM Ricardo Ribalda <[email protected]> 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) > > 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 > > > > > -- > Ricardo Ribalda
