Arreglar la suspensión/reanudación en Meteor Lake: un parámetro del kernel, un año tarde
Mantuve pulsado el botón de encendido más de 300 veces en esta máquina.
ThinkPad P1 Gen7, Intel Core Ultra 9 185H (Meteor Lake), del kernel 6.x al 7.x. Cada intento de suspensión acababa igual: cuelgue al entrar o pantalla negra al reanudar, y luego apagado forzado. Más de un año de trabajo real en una máquina incapaz de dormir. Eso no es una molestia menor — significa no poder cerrar la tapa durante una reunión, no poder suspender rápido entre tareas, la batería agotándose porque olvidaste enchufarla antes de levantarte.
Probé lo obvio. PSR1, DC2, EnableS0ixPowerManagement, split_lock_detect. Dos intentos en 6.18, ambos cuelgues completos sin logs que inspeccionar. La solución era un único parámetro que me faltó todo el tiempo.
Síntomas — para saber que estás en el sitio correcto
- Cuelgue al entrar en suspensión (el sistema se detiene, la pantalla se apaga, no despierta)
- Pantalla negra al reanudar — LED de encendido activo, máquina sin respuesta
- Apagado forzado obligatorio cada vez
- Sin logs del intento fallido (journalctl -b -1 está vacío o truncado — el cuelgue ocurre antes de que el logger vuelque a disco)
- El problema persiste entre versiones del kernel (6.x y 7.x afectadas)
- Funciona bien bajo Windows — es específico de Linux
Hardware que encaja: cualquier portátil Meteor Lake (Intel Core Ultra serie 100 o 200) que use el driver i915 para la GPU integrada. El P1 Gen7 está confirmado. Otros sistemas MTL con dGPU NVIDIA probablemente estén afectados.
Causa raíz
PSR2 (Panel Self Refresh 2) permite al controlador de pantalla saltarse la lectura de fotogramas cuando nada cambia en pantalla. La variante de lectura selectiva (psr2_sel_fetch) es más agresiva — solo lee las regiones del fotograma que han cambiado.
En Meteor Lake, esta lectura selectiva corrompe el estado del pipeline de pantalla antes de que se ejecute la ruta de suspensión. El driver i915 sufre un fallo de atomic commit, que cuelga la GPU, lo que impide que la transferencia de suspensión se complete limpiamente. Resultado: cuelgue.
El proyecto linux-surface aisló esto en el issue #2158. La solución desactiva la lectura selectiva manteniendo PSR2 activo — conservas el ahorro de energía de la pantalla y solo pierdes la variante más agresiva de regiones parciales.
La solución
Mínima — añade esto a la cmdline de tu kernel
i915.enable_psr=2 i915.enable_dc=1 i915.enable_psr2_sel_fetch=0 mem_sleep_default=s2idle
i915.enable_psr=2— PSR2 activado (ahorra ~0.3 W, habilita DEEP_SLEEP)i915.enable_dc=1— estados de energía de pantalla DC5/DC6i915.enable_psr2_sel_fetch=0— la solución: desactiva la lectura selectiva, evita el cuelguemem_sleep_default=s2idle— Meteor Lake no tiene S3; s2idle (S0ix) es lo que hay
i915.enable_psr2_sel_fetch=0 es la única línea que lo cambia todo. Lo demás es ajuste fino.
Con dGPU NVIDIA (serie RTX)
i915.enable_psr=2 i915.enable_dc=1 i915.enable_psr2_sel_fetch=0
i915.enable_fbc=1 i915.enable_guc=3
i915.force_probe=7d55 xe.force_probe=!7d55
nvidia_drm.modeset=1 nvidia_drm.fbdev=1
nvidia.NVreg_DynamicPowerManagement=0x02
nvidia.NVreg_PreserveVideoMemoryAllocations=1
mem_sleep_default=s2idle
i915.force_probe=7d55 y xe.force_probe=!7d55 asignan explícitamente la iGPU Meteor Lake al driver i915 y bloquean que el driver xe compita por ella. En un sistema de doble GPU esto importa. 0x7d55 es el device ID del P1 Gen7 — el tuyo puede diferir; compruébalo con lspci -nn | grep VGA.
NVreg_DynamicPowerManagement=0x02 habilita D3 de grano fino para la dGPU (la RTX corta su alimentación al estar inactiva).NVreg_PreserveVideoMemoryAllocations=1 permite al driver NVIDIA guardar y restaurar el estado de la VRAM a través de la suspensión — necesario para una reanudación fiable cuando la dGPU estaba activa.
Con passthrough de GPU en QEMU/KVM
i915.enable_psr=2 i915.enable_dc=1 i915.enable_psr2_sel_fetch=0
intel_iommu=on iommu=pt
mem_sleep_default=s2idle
iommu=pt (modo passthrough) mantiene bajo el sobrecoste del IOMMU para los dispositivos del host. Mantenlo si ejecutas VMs con passthrough de GPU; CUDA en bare metal no lo necesita.
Cómo aplicarlo (GRUB / grub-btrfs / systemd-boot)
GRUB — edita /etc/default/grub, añade a GRUB_CMDLINE_LINUX_DEFAULT, y luego:
sudo grub-mkconfig -o /boot/grub/grub.cfg
systemd-boot — edita tu entrada de loader en /boot/loader/entries/*.conf, añade a la línea options. No hace falta reconstruir nada.
Pruebas
# Verificar que s2idle está activo
cat /sys/power/mem_sleep
# Debería mostrar: s2idle [s2idle] o similar — s2idle entre corchetes = seleccionado
# Forzarlo si no está puesto
echo s2idle | sudo tee /sys/power/mem_sleep
# Suspender
sudo systemctl suspend
# Espera 10 segundos. Pulsa el botón de encendido una vez para despertar.
# Si funciona — captura los logs de inmediato
dmesg > dmesg-after-suspend.log
journalctl -b > journal-after-suspend.log
# Comprobación rápida
journalctl -b | grep -E 'PM: suspend|resume'
Si ves PM: suspend entry y PM: suspend exit en el journal con timestamps separados por unos segundos, la suspensión funcionó. Si la máquina no responde tras pulsar el botón de encendido, se colgó. Apagado forzado, y luego:
# Revisar el arranque anterior
journalctl -b -1 | grep -E 'PM: suspend|i915.*fail|drm.*fail|panic'
dmesg -b -1 > dmesg-failed.log
El modo de fallo suele mostrar errores de drm_atomic_commit o fallos de aserción de i915 justo antes del punto de cuelgue.
Ajuste de energía — qué hacer cuando la suspensión ya funciona
Autosuspend de USB — no uses el interruptor global
Tenía usbcore.autosuspend=-1 en mi cmdline, que desactiva el autosuspend de USB para todos los dispositivos globalmente. Funciona, pero es perezoso y cuesta batería. El enfoque correcto: activar el autosuspend globalmente en TLP y eximir solo los dispositivos que no deben dormir.
# /etc/tlp.conf
USB_AUTOSUSPEND=1
USB_DENYLIST="1050:0407 27c6:6594 04f2:b805"
Los IDs de arriba son el YubiKey (1050:0407), el lector de huella Goodix (27c6:6594) y la cámara integrada Chicony (04f2:b805). Encuentra los tuyos con lsusb. Añade dongles Bluetooth, lectores de tarjetas inteligentes, cualquier cosa que deba responder al instante.
Quita usbcore.autosuspend=-1 de tu cmdline tras confirmar que la suspensión funciona. Regenera la config de GRUB, reinicia, prueba de nuevo.
TLP — ya bien afinado para Meteor Lake
Si usas TLP, los ajustes que importan en MTL:
CPU_DRIVER_OPMODE_ON_AC=active
CPU_DRIVER_OPMODE_ON_BAT=active
CPU_SCALING_GOVERNOR_ON_AC=powersave
CPU_SCALING_GOVERNOR_ON_BAT=powersave
CPU_BOOST_ON_AC=1
CPU_BOOST_ON_BAT=0
PLATFORM_PROFILE_ON_AC=balanced
PLATFORM_PROFILE_ON_BAT=low-power
El modo active es el correcto para intel_pstate en MTL — no cambies a passive. El gobernador powersave con intel_pstate no es lo que su nombre sugiere; sigue subiendo la frecuencia cuando hace falta, solo que con mejores decisiones de eficiencia.
Consumo de energía — medido tras la solución
En reposo, pantalla encendida, con batería, escritorio ligero:
- Consumo en reposo: ~6.5 W de todo el sistema (energy-rate de
upower) - Potencia del paquete de CPU: ~2.4 W (
turbostat --show PkgWatt) - Residencia RC6 de la GPU Intel: 98% (
intel_gpu_top) — la iGPU queda aparcada casi toda la ventana en reposo - Batería: ~13 h en reposo (89.9 Wh a plena carga ÷ 6.5 W; batería al 99.9% de salud) — 12 h+ realista, en uso mixto menos
Un 98% de RC6 significa que PSR2 cumple su función sin el bloqueo del selective fetch; por encima del 90% en reposo es el objetivo. Confírmalo en tu máquina con intel_gpu_top y turbostat.
Problemas conocidos no críticos
NVIDIA “PRH failed to update thermal limit”
NVRM: GPU0 nvAssertFailedNoLog: Assertion failed: PRH failed to update thermal limit!
Aparece dos veces en el arranque (a los ~7 s y ~147 s en mi sistema). Es un bug en nvidia-open — el Platform Request Handler no consigue sincronizar con el firmware GSP. No es fatal; no provoca cuelgues; no afecta a la suspensión. Si te molesta, cambia al paquete propietario nvidia. Si no, ignóralo de momento.
“Correcting number of heads (0x00)”
Esperado cuando no hay ninguna pantalla externa conectada. No es un bug de tu configuración.
Deprecación de vm.laptop_mode en TLP
tlp: vm.laptop_mode is deprecated. Ignoring setting.
Quita la línea de tu config de TLP. Cosmético.
Lo que hacía mal antes de esto
En 6.18 usaba i915.enable_psr=1 (PSR1) e i915.enable_dc=2. Dos intentos con cuelgue, sin logs ninguna de las veces. El parámetro enable_psr2_sel_fetch no existía en esa configuración. Ahí estaba el hueco — no en el nivel de PSR, ni en el modo DC. Una sola línea que faltaba.
nvidia.NVreg_EnableS0ixPowerManagement=1 también estaba ahí. Con psr2_sel_fetch=0 en su sitio, ese parámetro es innecesario — el problema de suspensión está en el lado del pipeline de pantalla, no en la negociación de S0ix. Lo quité de la config actual.
Un año y más de 300 apagados forzados por una sola línea. Así son las cosas a veces.
Referencias
- linux-surface issue #2158 — donde se identificó la causa raíz de PSR2 sel_fetch
- Arch BBS #313469 — hilo de la regresión MTL en el kernel 7.x
- Meteor Lake power tuning guide
- TLP documentation
- Ubuntu certified: ThinkPad P1 Gen7
Angel Sulev
Cybersecurity + Agentic AI Expert
Especialista senior en ciberseguridad e IA Agéntica con 30+ años transformando la seguridad en ventaja competitiva para empresas visionarias.
Más sobre míArtículos Relacionados
LLMs privados vs ChatGPT: por qué tu empresa no debería usar la API de OpenAI para datos sensibles
Cada vez que tu equipo copia un contrato, un correo interno o datos de cliente en ChatGPT, esa …
Zero Trust no es un producto que se compra: es una arquitectura que se construye
En los últimos años “Zero Trust” ha pasado de ser un concepto de seguridad riguroso a …
