Public bug reported:

# Meteor Lake (ThinkPad T16 Gen 3): only the first s2idle per boot gets
deep; every later s2idle stays in Package C2 for the whole sleep, and
runtime idle is stuck at PC2 until reboot

## Summary

On a Lenovo ThinkPad T16 Gen 3 (Core Ultra 7 165H, Meteor Lake-H) under
Ubuntu, s2idle (the only sleep state the firmware offers) never reaches
S0ix. Worse:

- **First s2idle after boot:** the package reaches PC8 (7.0.0-38) or PC10 
(7.0.0-34) for essentially the whole sleep, but SLP_S0 residency stays 0.
- **Second and later s2idle on the same boot:** the package sits in **PC2 for 
100% of the sleep** (verified with the PC2 counter advancing at TSC rate). 
System draw is about **1.7 W**, so a full battery is gone in about a day; the 
laptop gets warm in a bag and the fan sometimes runs.
- **After that second resume, runtime idle is also broken:** PC6 residency 
falls from ~40% to **0** and stays 0 until reboot. Before the bad suspend the 
box idles in PC2/PC6; after it, in PC2 only.

It reproduces on two Ubuntu kernels (7.0.0-34 and 7.0.0-38). **Booting
with `nvme.noacpi=1` (ignoring the NVMe StorageD3Enable property) makes
it go away**; see "Trigger" below. **Windows 11 on the same machine and
the same BIOS reaches HW DRIPS for 98.6% and 98.9% of two consecutive
sleeps at 0.47 W and 0.36 W.** So the platform can do S0ix; the problem
is on the Linux side.

## System

| | |
|---|---|
| Machine | Lenovo ThinkPad T16 Gen 3, type 21MQS6US00 |
| CPU | Intel Core Ultra 7 165H (Meteor Lake-H, family 6 model 0xaa stepping 
4), microcode 0x28 |
| BIOS | N47ET29W (1.18), 2026-04-23 (latest per Lenovo as of 2026-10-18) |
| Sleep states | `ACPI: PM: (supports S0 S4 S5)`, `/sys/power/mem_sleep` = 
`[s2idle]` (no S3) |
| OS | Ubuntu 26.04, KDE Plasma 6.6 (Wayland) |
| Kernels tested | Ubuntu 7.0.0-38.38-generic (main), Ubuntu 
7.0.0-34.34-generic |
| Firmware packages | linux-firmware 20260319.git217ca6e4, intel-microcode 
3.20260210.1ubuntu2 |
| NVMe | KIOXIA XG8 [1e0f:0010] on 00:06.1 (CPU/IOE root port). `nvme 
0000:04:00.0: platform quirk: setting simple suspend` (StorageD3Enable) |
| Wi-Fi | Intel BE200 [8086:272b] on 00:1c.7, iwlmld |
| Ethernet | I219-LM [8086:550a] (e1000e), no cable. vPro / AMT platform |
| Other | Goodix fingerprint 27c6:6594 (USB 3-7), Intel BE200 Bluetooth (USB), 
Thunderbolt 4 (no device attached during tests) |
| Kernel cmdline | `quiet splash no_console_suspend pm_debug_messages 
crashkernel=…`. The debug options were added on purpose and **shown not to 
matter** (see run 2) |
| Taint | 0 (VirtualBox modules not loaded) |

## How it was measured

Script `s2idle-test.sh` (included) runs as root and does the following:
- dumps every file in `/sys/kernel/debug/pmc_core/`, the LPIT residency 
counters, `/sys/power/suspend_stats/*`, wakeup sources, GPE counts and 
`BAT0/energy_now`;
- does this before and after 30 s of runtime idle, then after a `rtcwake -m no 
-s N && systemctl suspend` cycle, then after another 30 s of idle;
- sets `intel_pmc_core.warn_on_s0ix_failures=1`, so the kernel prints the 
package C-state counter deltas for the suspend.

All runs were on battery, undocked, lid open, nothing touched, and the
Logitech USB receiver plugged in with its mouse turned off. Its wakeup
is disabled via udev.

In `package_cstate_show` deltas below, units are µs. In the
`intel_pmc_core` resume warnings, units are TSC ticks (3.08 GHz).

## Results

| Run | Kernel | Suspend # in boot | Length | Package residency during suspend 
| Energy | Runtime PC6 after resume |
|---|---|---|---|---|---|---|
| `20261017-175837` | 7.0.0-38 | 1st | 57 s | **PC8 58.1 s** (100%), PC10 0, 
SLP_S0 0 | n/a (too short) | OK (9.95 s / 30 s) |
| `20261017-180550` | 7.0.0-38 | 2nd | 597 s | **PC2 596.8 s** (100%), PC6/8/10 
0 | 290 mWh → **1.74 W** | **0** |
| `20261017-170647` | 7.0.0-38 | 2nd (previous boot) | 598 s | PC2 ~598 s 
(100%) | 280 mWh → **1.68 W** | 0 (already stuck before) |
| `20261017-172521` | 7.0.0-38, `console_suspend=Y` at runtime | 3rd | 599 s | 
PC2 100% | 280 mWh → 1.68 W | 0 |
| `20261017-183759` | **7.0.0-34** | 1st | 58 s | **PC10 ~56 s**, but `CPU did 
not enter SLP_S0!!! (S0ix cnt=0)` | n/a | OK (6.3 s / 30 s) |
| `20261017-184109` | **7.0.0-34** | 2nd | 58 s | **PC2 59 s** (100%) | n/a | 
**0** |
| `20261018-113012` | 7.0.0-38 + **`nvme.noacpi=1`** | 1st | 58 s | PC8 58.9 s, 
PC10 0 | n/a | OK (6.4 s / 30 s) |
| `20261018-113255` | 7.0.0-38 + **`nvme.noacpi=1`** | **2nd** | 59 s | **PC8 
59.2 s** (100%), PC10 0 | n/a | **OK (13.0 s / 30 s)** |
| `20261018-113924` | 7.0.0-38 + **`nvme.noacpi=1`** | **3rd** | 598 s | **PC8 
597.4 s** (100%), PC10 0, SLP_S0 0 | 120 mWh → **0.72 W** | OK (12.5 s / 30 s) |

On 7.0.0-38 before the first suspend, runtime idle reached PC6 for 7–13
s of every 30 s. It never reached PC8 or PC10 at runtime on either
kernel. The second suspend in a boot was 4–5 minutes after the first,
and the system was idle in between.

All cores **do** enter C10 during s2idle. `cpu*/cpuidle/state3` (C10)
`s2idle/usage` increments and states 1 and 2 stay at 0. So only the
package is held shallow.

Excerpt from the 2nd suspend (`20261017-180550/kernel.log`):
```
PM: suspend-to-idle
Timekeeping suspended for 597.190 seconds
PM: resume from suspend-to-idle
intel_pmc_core INT33A1:00: CPU did not enter Package C10!!! (Package C10 
cnt=0x0)
intel_pmc_core INT33A1:00: Prev Package C2 cnt = ..., (delta = 596.8 s at TSC 
rate)
intel_pmc_core INT33A1:00: Prev Package C6 cnt = 0x..., Current Package C6 cnt 
= (unchanged)
```

## What differs between the good and the stuck state (awake, same boot)

This diffs `idle-before.txt` (after the 1st resume, good) against 
`idle-post.txt` (after the 2nd resume, stuck) in `20261017-180550/`:
- `pch_ip_power_gating_status`: **PMC0 SPB On** when stuck (Off when good); 
LPSS and P2SB flip the other way.
- `substate_live_status_registers`: `PMC0:SPB_PGD0_PG_STS` goes 1 → 0.

The same SPB difference appeared when comparing a good snapshot and a
stuck one across the previous boot. That comparison also showed SPD,
MPFPW4_0_PLL and REF_PLL (PMC1) and changes in the SOUTHPORT_D and
IOE_PMC LTR values, but those later returned to normal while the package
stayed stuck. Treat them as noise.

## Ruled out while stuck (runtime, each measured over 10 s idle, PC6
stayed 0)

- Re-programming ASPM (L1, L1.1, L1.2) on the NVMe and Wi-Fi links via 
`/sys/bus/pci/devices/*/link/*`
- `rfkill block bluetooth`
- Unbinding, cumulatively: xhci_hcd (00:14.0), 8250 serial on the AMT KT 
redirection (00:16.3), mei_me (00:16.0), proc_thermal (00:04.0), e1000e 
(00:1f.6). *Caveat: the PCI functions stayed D0 after unbind (XHCI and GBE 
remained "On" in power gating), so this doesn't fully exclude them.*
- Wi-Fi radio off, then `rmmod iwlmld iwlwifi`: root port 00:1c.7 went to 
D3hot, **SPB stayed On**, PC6 stayed 0.
- Display: PSR2 is in DEEP_SLEEP and the DMC (mtl_dmc v2.23) DC3→DC5/DC6 
counters advance. GT RC6 residency is about 90% while idle.
- `no_console_suspend` (run 2 sets `console_suspend=Y` at runtime; no change)
- Dock: the USB-C Dell monitor was not connected at all on the fresh-boot runs.
- Kernel regression between 7.0.0-34 and 7.0.0-38: both show it.
- BIOS: already the latest.

## Windows 11 on the same machine (powercfg /sleepstudy)

Both sleeps were on battery, with no external monitor and the lid open:

| Sleep | Length | HW low-power (DRIPS) time | Energy |
|---|---|---|---|
| 1st after boot (2026-10-18 08:08) | 1231 s | 1213.8 s = **98.6%** | 160 mWh → 
**0.47 W** |
| 2nd (08:32) | 1894 s | 1873.9 s = **98.9%** | 190 mWh → **0.36 W** |

The only listed blockers, each active for a few seconds, were the root
ports `\_SB.PC00.RP08` (Wi-Fi) and `RP10` (NVMe) and the xHCI.

## Related reports

- StarLabs StarFighter (Meteor Lake, coreboot), 
https://github.com/StarLabsLtd/firmware/issues/465. The package is stuck in PC2 
after resume until reboot (S3 on that board). That report implicates 
StorageD3Enable, with the CPU-attached NVMe link staying powered, and says 
`nvme.noacpi=1` helped. This machine also hits the StorageD3Enable "simple 
suspend" quirk, and its NVMe sits on a CPU/IOE root port.
- Meteor Lake S0ix blockers from AMT (KVMCC, USBR0, SUSRAM) on a ThinkPad P1 
Gen 7, cleared by disabling AMT in BIOS: 
https://www.feeditout.com/s0ix-sleep-and-hibernate-on-meteor-lake-nvidia-and-the-thinkpad-p1-gen-7/
- Meteor Lake GBE / CSME power gating is boot-dependent: 
https://blog.fsck.com/agent-blog/2026/03/30/linux-power-tuning-meteor-lake/

## Trigger: the NVMe StorageD3Enable "simple suspend" path

Booting with **`nvme.noacpi=1`** makes the kernel ignore the firmware's
StorageD3Enable `_DSD` for the KIOXIA SSD on the CPU/IOE root port
00:06.1. With it, the `platform quirk: setting simple suspend` message
is gone, and the 2nd suspend in a boot behaves like the 1st: PC8 for the
whole sleep, and runtime PC6 intact afterwards (runs `20261018-113012`
and `-113255`). Without it, the 2nd suspend is 100% PC2 and leaves the
package stuck at PC2 until reboot, on both 7.0.0-34 and 7.0.0-38.

So once the NVMe has been through the D3 "simple suspend" / resume
cycle, something in the IOE/PCIe path is left in a state that holds the
package at PC2. That matches the StarLabs report, where the CPU-attached
SSD link stays powered after sleep until reboot.

A 10-minute 3rd suspend with `nvme.noacpi=1` drew **0.72 W**. Without it
the figure is 1.7 W, and Windows draws 0.36–0.47 W.

`nvme.noacpi=1` does **not** give S0ix: the package still tops out at
PC8 and SLP_S0 stays 0. That remaining gap to Windows (99% DRIPS) is a
separate issue.

## Not yet tested

- Disabling Intel AMT in BIOS (for the remaining PC8 → PC10/S0ix gap). 
CSME_KVM, CSME_PTIO, CSME_USBR and CSME_SUSRAM show "On" in 
`pch_ip_power_gating_status`.
- Disabling the PCH LAN controller in BIOS.

## Attached data

- `s2idle-results/<run>/`: `info.txt`, `idle-before`, `idle-after`, 
`pre-suspend`, `post-suspend` and `idle-post.txt` (full pmc_core dumps), 
`kernel.log`, `logind.log`, `summary.txt`
- `s2idle-results/toggle-*`, `sweep-*`, `wifi-*`, `display-*`: the runtime 
triage above
- `windows-sleepstudy-sessions.json`: the two sleep sessions extracted from the 
powercfg sleepstudy report (the raw HTML is withheld because it contains 
per-user app usage)
- Scripts: `s2idle-test.sh`, `pc6-toggle-test.sh`, `unbind-sweep.sh`, 
`wifi-test.sh`, `display-dump.sh`
- `system/`: lspci -nnvvv, lsusb, lsmod, dmesg of the current boot, cmdline

ProblemType: Bug
DistroRelease: Ubuntu 26.04
Package: linux-image-7.0.0-38-generic 7.0.0-38.38
ProcVersionSignature: Ubuntu 7.0.0-38.38-generic 7.0.14
Uname: Linux 7.0.0-38-generic x86_64
ApportVersion: 2.34.1-0ubuntu0.1
Architecture: amd64
AudioDevicesInUse:
 USER        PID ACCESS COMMAND
 /dev/snd/controlC0:  tomislav   4962 F.... pipewire
                      tomislav   4985 F.... wireplumber
 /dev/snd/seq:        tomislav   4962 F.... pipewire
CasperMD5CheckResult: pass
CurrentDesktop: KDE
Date: Sun Oct 18 12:02:54 2026
InstallationDate: Installed on 2025-11-05 (347 days ago)
InstallationMedia: Ubuntu 25.10 "Questing Quokka" - Release amd64 (20251007)
MachineType: LENOVO 21MQS6US00
ProcFB: 0 i915drmfb
ProcKernelCmdLine: BOOT_IMAGE=/vmlinuz-7.0.0-38-generic 
root=/dev/mapper/ubuntu--vg-ubuntu--lv ro quiet splash no_console_suspend 
pm_debug_messages 
crashkernel=2G-4G:320M,4G-32G:512M,32G-64G:1024M,64G-128G:2048M,128G-:4096M 
nvme.noacpi=1
PulseList: Error: command ['pacmd', 'list'] failed with exit code 1: No 
PulseAudio daemon running, or not running as session daemon.
SourcePackage: linux
UpgradeStatus: Upgraded to resolute on 2026-06-12 (128 days ago)
dmi.bios.date: 04/23/2026
dmi.bios.release: 1.18
dmi.bios.vendor: LENOVO
dmi.bios.version: N47ET29W (1.18 )
dmi.board.asset.tag: Not Available
dmi.board.name: 21MQS6US00
dmi.board.vendor: LENOVO
dmi.board.version: SDK0T76530 WIN
dmi.chassis.asset.tag: No Asset Information
dmi.chassis.type: 10
dmi.chassis.vendor: LENOVO
dmi.chassis.version: None
dmi.ec.firmware.release: 1.16
dmi.modalias: 
dmi:bvnLENOVO:bvrN47ET29W(1.18):bd04/23/2026:br1.18:efr1.16:svnLENOVO:pn21MQS6US00:pvrThinkPadT16Gen3:rvnLENOVO:rn21MQS6US00:rvrSDK0T76530WIN:cvnLENOVO:ct10:cvrNone:skuLENOVO_MT_21MQ_BU_Think_FM_ThinkPadT16Gen3:pfaThinkPadT16Gen3:
dmi.product.family: ThinkPad T16 Gen 3
dmi.product.name: 21MQS6US00
dmi.product.sku: LENOVO_MT_21MQ_BU_Think_FM_ThinkPad T16 Gen 3
dmi.product.version: ThinkPad T16 Gen 3
dmi.sys.vendor: LENOVO

** Affects: linux (Ubuntu)
     Importance: Undecided
         Status: New


** Tags: amd64 apport-bug resolute wayland-session

-- 
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/2171322

Title:
  ThinkPad T16 Gen 3 (Meteor Lake): 2nd+ s2idle stuck in Package C2 (1.7
  W) until reboot; fixed by nvme.noacpi=1 (StorageD3Enable)

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/2171322/+subscriptions


-- 
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to