Skip to content

PCI: apple: suspend-to-idle on the K116s (adopted N1 link, kernel-trained SD reader port) - #1647

Open
sithglan wants to merge 2 commits into
aurora-silicon:integration/aurorafrom
sithglan:thomas/k116s-pcie-s2idle
Open

sithglan wants to merge 2 commits into
aurora-silicon:integration/aurorafrom
sithglan:thomas/k116s-pcie-s2idle

Conversation

@sithglan

@sithglan sithglan commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

Base: integration/aurora (673f618). Two commits in pcie-apple's check for suspend-to-idle over an adopted link.

  • Qualify the K116s. The adopted-link check admitted only the J716c. The K116s is its OLED sibling, with the same T6050 host and the N1 on port 0, and its first s2idle failed with -EBUSY from the noirq suspend.
  • D0 below a kernel-trained port only on the awake path. The check walked the whole bus and refused to suspend when any device had left D0. With a kernel-trained second port (the K116s's SD reader, in arm64: dts: apple: t6050-k116s: N1, USB-C, SMC, DCP, sound, PMP/SEP, GPU, SD reader, microphones, camera #1648) the PCI core puts that root port into D3hot, and suspend failed with -EBUSY. Below a port Linux trained itself (port->pwren, set only by the cold train), only the devices that asked to stay awake need to stay in D0. Below a port the boot loader trained, such as the N1's, every device must still be in D0. So the J716c and the K114c, whose only port is adopted, are checked exactly as before.

Tested by Jens on the K116s: s2idle with everything loaded, also while the camera streams, measured 3.6-3.9 W over 24 minutes against about 5.1 W awake idle. That measurement was on his kernel before the rebase and has not been repeated on the rebased one. On the rebased branch (643e102) he ran an s2idle cycle with Wi-Fi up: clean, with Wi-Fi associated and the SD controller present after wake. The current head, 70bf8ed, narrows the second commit to kernel-trained ports and still needs a K116s cycle.

Build: arm64, LLVM 22; drivers/pci/controller/pcie-apple.o, no warnings.

Authorship. Jens Axboe wrote these commits and runs them on his K116s (16-inch MacBook Pro, M5 Pro, OLED; Mac17,12; stub macOS 27.2 26B8125). They come from his K116s bundle of 2026-11-11 (integration/aurora 254c9bd plus 34 commits, kernel 7.3.0 running on the machine). I rebased them onto integration/aurora 673f618, where the check also admits the K114c (aea2429), and removed the LLM co-author and session trailers. Jens has given his OK: the commits carry his Signed-off-by.

@RyanTheTide

Copy link
Copy Markdown
Contributor

@sithglan The K116s part is fine. The second commit also changes the J716c: devices off the awake path are now skipped by the D0 check. Could you get one s2idle cycle on a J716c (with Wi-Fi up and with Wi-Fi down) and one on the K116s with the rebased kernel? If the N1 functions are not on the awake path in some state, the check would now let the suspend through with the link's device out of D0.

… link

The adopted link's suspend check admits only the J716c; the K116s is its
OLED sibling with the same T6050 host and the N1 on port 0, and the
first s2idle attempt there failed with -EBUSY from the noirq suspend.
Let it through the same checks.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
[thomas: rebased onto integration, where the check also admits the K114c]
Signed-off-by: Thomas Glanzmann <thomas@glanzmann.de>
@sithglan
sithglan force-pushed the thomas/k116s-pcie-s2idle branch from 4f65a0c to 643e102 Compare November 13, 2026 06:41
@sithglan

sithglan commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor Author

@RyanTheTide rebased onto integration 673f618. It is now 643e102 (was 4f65a0c); the old branch no longer merged.

  • The only conflict was the machine list in apple_pcie_check_adopted_s2idle(), where aea2429 admitted the K114c. The check now admits the J716c, the K114c and the K116s.
  • Both commits build with W=1 and no warnings (LLVM 22).
  • So the second commit now changes the K114c as well as the J716c and K116s.

When the second commit lets a suspend through that used to be refused: only when a device is off the awake path and out of D0. In the N1's case:

  • All four N1 functions have drivers whose suspend callbacks call device_set_awake_path() unconditionally: centauri_suspend() for 0x1900–0x1902 and cen_suspend() in btcentauri for 0x1903. The PM core then marks their root port too. That doesn't depend on whether Wi-Fi is up or down: ip link set … down or rfkill leave the drivers bound, so both of your Wi-Fi states take the same path.
  • The case left is an N1 with no driver bound (the modules not loaded, or unbound through sysfs). Then nothing is on the awake path, the check skips every device, and the root port goes to D3hot under a link the bootloader trained. Before, that suspend was refused with -EBUSY. Afterwards, nothing can retrain the N1 until the next boot.
  • On the J716c in this tree, port 0 is the only port and no port is kernel-trained, so this unbound-N1 case is the only one where its behaviour changes.

If you'd rather close that case in code: port->pwren is set only by apple_pcie_t6050_cold_train(). So the check can skip only devices below a port Linux trained itself, and require D0 for everything under an adopted port as before. That keeps the J716c and K114c exactly as they are now. The catch: on a boot where the loader trains the K116s SD port itself, that port is adopted, and s2idle is refused again, as it was before the second commit. I can push that variant if you prefer it.

Hardware: I don't have a J716c or a K116s here. The K116s run on this rebased branch needs Jens's machine, and the J716c rows, with Wi-Fi up and down, need someone with a J716c.

@axboe

axboe commented Nov 13, 2026

Copy link
Copy Markdown
Contributor

K116s run for this PR (16" M5 Pro OLED, 27.2 stub, Linux at EL2).

Built as @sithglan described: integration/aurora 10dca1d with the eight thomas/ K116s branches merged, HEAD 51a64cc5474c01b393d39612faf17d8035e46f0c (so both commits of this PR are in).

  • One s2idle cycle with Wi-Fi up, lid close/open, 18.5 s asleep: suspend_stats success 1, fail 0.
  • After the wake Wi-Fi is still associated and pings. The SD reader's controller (02:00.0) is on the bus and mmc0 is registered. No card was inserted, so no I/O on it.
  • pcie-apple 1cb0000000.pcie: port 1: trained by Linux, the boot loader left it down. Port 0 (N1) is adopted.
  • @RyanTheTide on the loader question: my loader has left the SD port down on every boot I checked, so it is always Linux that trains port 1 here.
output
== commit 51a64cc5474c01b393d39612faf17d8035e46f0c  uname 7.3.0-m5pro-g51a64cc5474c
== stage2 1.0.0b2-g636de666  os-fw 27.2
== trained by Linux
[    2.509090] pcie-apple 1cb0000000.pcie: port 1: trained by Linux, the boot loader left it down
== adopted
[    1.959057] pcie-apple 1cb0000000.pcie: adopted port 0, endpoint 01:00
[    2.509090] pcie-apple 1cb0000000.pcie: port 1: trained by Linux, the boot loader left it down
[    2.509181] pcie-apple 1cb0000000.pcie: adopted port 1, endpoint 02:00
[    2.793076] pcie-apple 1cb0000000.pcie: port 0: link retrained after a root-port reset
== suspend_stats
1
0
1   06:24:53.743749 18.5      0        0        
1 suspend(s), 0 with a PS message or a PMP crash, 0 PMP error line(s) in this boot
RESULT: PASS so far (1 clean)
suspend_stats: success: 1 fail: 0 failed_freeze: 0 failed_prepare: 0 failed_suspend: 0 failed_suspend_late: 0 failed_suspend_noirq: 0 f
== after wake
wlp1s0f0:connected:<ssid>
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 6.804/7.763/9.630/1.320 ms
00:00.0 PCI bridge: Apple Inc. Apple Silicon PCI Express Root Port (rev 01)
00:01.0 PCI bridge: Apple Inc. Apple Silicon PCI Express Root Port (rev 01)
01:00.0 Unassigned class [ff00]: Apple Inc. Device 1900 (rev 01)
01:00.1 802.11a 5 GHz controller: Apple Inc. Device 1902 (rev 01)
01:00.2 Bluetooth: Apple Inc. Device 1903 (rev 01)
02:00.0 SD Host controller: Genesys Logic, Inc GL9755 SD Host Controller (rev 02)
[    2.519188] sdhci-pci 0000:02:00.0: SDHCI controller found [17a0:9755] (rev 2)
[    2.519205] sdhci-pci 0000:02:00.0: enabling device (0000 -> 0002)
[    2.553106] mmc0: SDHCI controller on PCI [0000:02:00.0] using ADMA 64-bit
== dmesg suspend entry to exit
[   55.878359] PM: suspend entry (s2idle)
[   55.885675] Filesystems sync: 0.007 seconds
[   55.885791] snd-soc-macaudio sound: Speaker volumes locked: System suspend
[   55.891072] Freezing user space processes
[   55.904780] Freezing user space processes completed (elapsed 0.013 seconds)
[   55.904808] OOM killer disabled.
[   55.904817] Freezing remaining freezable tasks
[   55.906000] Freezing remaining freezable tasks completed (elapsed 0.001 seconds)
[   55.906019] printk: Suspending console(s) (use no_console_suspend to debug)
[   55.910322] apple-dcp 48ae00000.dcp: RTKit: syslog message: ipeDCP_H17GSCD.cpp:2985: brightness_changed: brightness value: 0
[   55.910835] apple-dcp 48ae00000.dcp: RTKit: syslog message: UPBlock_SWMPR_v1.cpp:65: program_dbv: M3 BrightnessUsed: 650, Brightness: 262
[   55.953789] apple-dcp 48ae00000.dcp: RTKit: syslog message: ipeDCP_H17GSCD.cpp:2985: brightness_changed: brightness value: 0
[   56.005593] macsmc 28c600000.smc: RTKit: syslog message: smc/apComms.cpp:354: SMC HID Event: 03 00 01
[   56.005674] macsmc-input macsmc-input: lid open 72030001 at +18180 ms in sleep, MSLD=0: wakeup
[   56.236810] apple-dcp 48ae00000.dcp: set_digital_out_mode(color:1 timing:2) "3472x2266": 120 1200262 3472 3496 3504 3512 2266 2754 2812 2848 0x48 0x5
[   56.236836] apple-dcp 48ae00000.dcp: set_digital_out_mode() color mode depth:9 format:0 colorimetry:16 eotf:0 range:0 vrr:0
[   56.237017] apple-dcp 48ae00000.dcp: RTKit: syslog message: ifiedPipeline.cpp:11609: set_digital_out_mode: Modeset requested for colorID: 1, timingID: 2
[   56.237272] apple-dcp 48ae00000.dcp: RTKit: syslog message: ifiedPipeline.cpp:11936: Already set to timingID: 2 colorID: 1. 3472x2266 link: 1
[   56.237314] apple-dcp 48ae00000.dcp: set_digital_out_mode finished:2125
[   56.238222] apple-dcp 48ae00000.dcp: RTKit: syslog message: ipeDCP_H17GSCD.cpp:2985: brightness_changed: brightness value: 0
[   56.249535] apple-dcp 48ae00000.dcp: RTKit: syslog message: ipeDCP_H17GSCD.cpp:2985: brightness_changed: brightness value: 6619136
[   56.250123] apple-dcp 48ae00000.dcp: RTKit: syslog message: UPBlock_SWMPR_v1.cpp:65: program_dbv: M3 BrightnessUsed: 262, Brightness: 650
[   56.252876] OOM killer enabled.
[   56.252912] Restarting tasks: Starting
[   56.253963] Restarting tasks: Done
[   56.254072] random: crng reseeded on system resumption
[   56.256706] PM: suspend exit
== after exit
[   56.258155] power_supply_format_property: 9 callbacks suppressed
[   56.258157] power_supply macsmc-battery: driver failed to report `manufacture_year' property: -95
[   56.264365] power_supply macsmc-battery: driver failed to report `manufacture_year' property: -95
[   56.268540] power_supply macsmc-battery: driver failed to report `manufacture_year' property: -95
[   56.271934] power_supply macsmc-battery: driver failed to report `manufacture_year' property: -95
[   56.274925] power_supply macsmc-battery: driver failed to report `manufacture_year' property: -95
[   56.279711] power_supply macsmc-battery: driver failed to report `manufacture_year' property: -95
[   56.302606] power_supply macsmc-battery: driver failed to report `manufacture_year' property: -95
[   56.308038] power_supply macsmc-battery: driver failed to report `manufacture_year' property: -95
[   56.310750] power_supply macsmc-battery: driver failed to report `manufacture_year' property: -95
[   56.313583] power_supply macsmc-battery: driver failed to report `manufacture_year' property: -95
[   65.792396] apple_centauri_t6050 0000:01:00.0: Wi-Fi firmware channels: 2.4 GHz 11, 5 GHz 25, 6 GHz 59 (167 entries)

The adopted-link s2idle check walked the whole bus and refused to suspend
when any device had left D0. With a kernel-trained second port (the SD
reader on the K116s) the PCI core puts that root port into D3hot, and
suspend failed with -EBUSY. Below a port Linux trained itself, only the
devices that asked to stay awake need to remain in D0; the PCI core
restores the rest. Below a port the boot loader trained, such as the
N1's, every device must still be in D0, so the J716c and the K114c, whose
only port is adopted, are checked as before.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
[thomas: skip only devices below a port Linux trained (port->pwren), so
 adopted ports keep requiring D0 for every device]
Signed-off-by: Thomas Glanzmann <thomas@glanzmann.de>
@sithglan
sithglan force-pushed the thomas/k116s-pcie-s2idle branch from 643e102 to 70bf8ed Compare November 13, 2026 17:07
@sithglan

Copy link
Copy Markdown
Contributor Author

@RyanTheTide @axboe I pushed the stricter variant. It is 70bf8ed (was 643e102); the first commit is unchanged.

apple_pcie_check_d0() now skips a device only if it is off the awake path and sits below a port Linux trained itself. port->pwren marks such a port; only apple_pcie_t6050_cold_train() sets it. Below a port the boot loader trained, every device must still be in D0, as before the PR.

  • J716c and K114c: neither device tree in integration has pwren-gpios on a PCIe port. Their only port is adopted, so the check behaves exactly as before this PR. The J716c Wi-Fi up/down run shouldn't be needed any more.
  • K116s: port 1 (the SD reader) is cold-trained on Jens's boots ("trained by Linux, the boot loader left it down"). Its root port and the GL9755 are still skipped, and the N1 on port 0 still has to be in D0.
  • The case I raised earlier, an N1 with no driver bound, is refused with -EBUSY again.
  • If a loader ever trains the K116s SD port itself, that port counts as adopted, and s2idle is refused as it was before the second commit. Jens's loader has never done that.

pcie-apple.o builds with W=1 and no warnings (LLVM 22), and the branch merges cleanly into integration 6882c13.

@axboe could you run one more s2idle cycle with this head on the K116s? The changed condition is exactly the path your SD port takes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants