Skip to content

Add T2 suspend/resume support#5998

Open
jjohnson wants to merge 2 commits into
basecamp:devfrom
jjohnson:add-t2-suspend
Open

Add T2 suspend/resume support#5998
jjohnson wants to merge 2 commits into
basecamp:devfrom
jjohnson:add-t2-suspend

Conversation

@jjohnson

@jjohnson jjohnson commented May 29, 2026

Copy link
Copy Markdown

Summary

Adds suspend/resume support for Apple T2 Macs. The apple_bce module must be
unloaded before suspend (its PCI PM can't handle D3 entry), but userspace ALSA
clients (PipeWire/WirePlumber) keep it pinned. This service unbinds aaudio before
suspend, unloads apple_bce and dependent T2 modules, then reloads everything
after resume.

Tested on

  • Model: MacBookPro15,4 (MacBook Pro 13", 2019)
  • Kernel: (T2 Arch Linux) 6.19.13-arch1-Watanare-T2-1-t2 7.1.3-arch1-Watanare-T2-2-t2
  • Userspace: PipeWire + WirePlumber (no stop/restart needed across suspend)

Test results (extended suspend/resume + overnight/multi-night)

Condition Result
Clean suspend/resume (audio, Wi-Fi, Touch Bar, USB, keyboard) Pass
External monitor (HDMI) across suspend Pass
Overnight suspend cycle (8+ hours) Pass
Multi-night suspend cycle (48+ hours) Pass
Bluetooth audio (headset playback and mic) across suspend Pass
Built-in webcam after resume Pass
invalid position / scheduling while atomic kernel errors Gone
appletbdrm *ERROR* Failed to send message on module unload Gone
brcmfmac: brcmf_pcie_pm_enter_D3: Timeout Gone
Playback resume after suspend (Spotify, local audio) Pass
Record after resume (microphone input) Pass
Wi-Fi reconnect after resume Pass
Bluetooth recovers/reconnects after resume Pass
Screen capture (grim) after resume Pass
Audio recording (arecord) after resume Pass

For testers

The service installs and enables automatically via Omarchy on T2 Macs
(detected via PCI ID 106b:180[12]). To test:

# After updating Omarchy, the migration runs automatically on next update,
# or run it local manually:
OMARCHY_PATH=~/Projects/omarchy bash ~/Projects/omarchy/migrations/1780075490.sh

# Check status:
systemctl status omarchy-apple-t2-suspend.service
journalctl -t t2-suspend

# Test a suspend cycle:
systemctl suspend

Kernel module requirement (for clean audio after reload)

The fix is included in linux-lts-t2 6.18.36-1 and newer. As of linux-t2
7.1.4-1, it has not yet been imported into the mainline linux-t2 package.

Clean audio after reloading apple_bce requires the PLAYBACK timestamp fix
from t2linux/apple-bce-drv#30. Without it, aaudio_pcm_pointer can return
an invalid position after module re-probe, causing XRUNs and
"scheduling while atomic" errors.

The patch is one line in audio/pcm.c: change dev_timestampos_timestamp
in the aaudio_handle_stream_timestamp call for the PLAYBACK substream.

Mainline linux-t2 testers can rebuild and install the corrected current upstream driver:

git clone https://github.com/t2linux/apple-bce-drv && cd apple-bce-drv
make -C /lib/modules/$(uname -r)/build M=$PWD
# Backup original compressed module, then install the patched one
sudo mv /lib/modules/$(uname -r)/kernel/drivers/staging/apple-bce/apple-bce.ko.zst \
       /lib/modules/$(uname -r)/kernel/drivers/staging/apple-bce/apple-bce.ko.zst.bak
sudo cp apple-bce.ko /lib/modules/$(uname -r)/kernel/drivers/staging/apple-bce/
sudo depmod -a

Model compatibility

The module lists in PRE_MODS/POST_MODS cover all T2 peripherals known on the
MacBookPro15,4. Other T2 models (MacBookAir, Mac mini, Mac Pro, iMac) may need
adjustments if their Wi-Fi chipset or other modules differ. The mod_ld guard
skips absent modules silently.

More testing is needed on dGPU-equipped T2 Macs. Models with a discrete
GPU may require additional module handling. The latest consolidated
BCM4364 logic is based on MBP16,1 results, still awaiting retest.

Debugging

If suspend/resume doesn't work on your model, collect the debug info:

collect-t2-debug() {
  echo "=== Service log ===" ; journalctl -t t2-suspend
  echo "=== Kernel errors ===" ; sudo dmesg | grep -iE "XRUN|appletbdrm|brcmfmac|apple_bce"
  echo "=== Modules ===" ; lsmod | grep -E "apple|brcmfmac"
  echo "=== Suspend method ===" ; cat /sys/power/mem_sleep
  echo "=== Model ===" ; cat /sys/class/dmi/id/product_name ; cat /sys/class/dmi/id/product_version
  echo "=== Kernel ===" ; uname -r
  echo "=== Cmdline ===" ; cat /proc/cmdline
  echo "=== PCI devices ===" ; lspci -nn | grep -iE "106b|vga|3d|display"
}
collect-t2-debug > ~/t2-debug.txt

Then attach ~/t2-debug.txt to your comment.

Copilot AI review requested due to automatic review settings May 29, 2026 17:00

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds Apple T2 suspend/resume support by installing a systemd sleep hook and helper script, including a migration for existing installs.

Changes:

  • Add a migration to install/enable the apple-bce.service on existing T2 Mac installations.
  • Add an installer hardware config script to set up the same systemd unit during installation.
  • Add the omarchy-hw-t2-suspend helper invoked by the systemd unit, and wire the new setup into the main install flow.

Reviewed changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 3 comments.

File Description
migrations/1780070899.sh Migration to install and enable the apple-bce systemd oneshot sleep service on T2 Macs.
install/config/hardware/apple/fix-t2-suspend.sh New install-time configuration script that writes/enables the T2 suspend/resume service.
install/config/all.sh Runs the new T2 suspend/resume fix script as part of the installer hardware steps.
bin/omarchy-hw-t2-suspend Helper script to unload/reload T2-related modules around suspend/resume.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread migrations/1780070899.sh Outdated
Comment thread install/config/hardware/apple/fix-t2-suspend.sh Outdated
Comment thread install/config/hardware/apple/fix-t2-suspend.sh Outdated
@jjohnson
jjohnson requested a review from Copilot May 29, 2026 17:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 4 changed files in this pull request and generated 8 comments.

Comment thread migrations/1780070899.sh Outdated
Comment thread install/config/hardware/apple/fix-t2-suspend.sh
Comment thread migrations/1780070899.sh Outdated
Comment thread install/config/hardware/apple/fix-t2-suspend.sh Outdated
Comment thread install/config/hardware/apple/fix-t2-suspend.sh Outdated
Comment thread install/config/hardware/apple/fix-t2-suspend.sh Outdated
Comment thread migrations/1780070899.sh Outdated
Comment thread migrations/1780070899.sh Outdated
Copilot AI review requested due to automatic review settings May 29, 2026 22:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.

Comment thread install/config/hardware/apple/fix-t2-suspend.sh Outdated
Comment thread install/config/hardware/apple/fix-t2-suspend.sh
Comment thread migrations/1780075490.sh
Comment thread install/config/hardware/apple/t2-suspend Outdated
Comment thread install/config/hardware/apple/t2-suspend Outdated
Comment thread install/config/hardware/apple/t2-suspend Outdated
Copilot AI review requested due to automatic review settings May 29, 2026 22:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.

Comment thread install/config/hardware/apple/fix-t2-suspend.sh Outdated
Comment thread install/config/hardware/apple/fix-t2-suspend.sh Outdated
Comment thread migrations/1780075490.sh
Comment thread install/config/hardware/apple/fix-t2-suspend.sh
Comment thread migrations/1780075490.sh Outdated
@liquid1982

Copy link
Copy Markdown

Awesome. This is very much needed in order to run Omarchy on older Intel MacBooks. Looking forward to trying this out!

@maulik13

maulik13 commented Jun 8, 2026

Copy link
Copy Markdown

Any suggestion on how to test this particular fix on my macbook?

@jjohnson

jjohnson commented Jun 8, 2026

Copy link
Copy Markdown
Author

The PR description has step-by-step test instructions under "For testers".

@RayBB

RayBB commented Jun 10, 2026

Copy link
Copy Markdown

This is awesome and badly needed! Would be great to also get it upstreamed into some of the other distros/build tools for the t2linux wiki. They've been quite responsive the few times I've reached out and opened PRs.

https://wiki.t2linux.org/

I've had good experience with https://github.com/t2linux/T2-Mint in particular

@TopperH

TopperH commented Jun 11, 2026

Copy link
Copy Markdown

Tested on MacBookAir8,1 (2018 Retina Air, T2) with kernel 7.0.11-arch1-Watanare-T2-1-t2.

Cloned the add-t2-suspend branch and ran the migration.
KERNEL_CMDLINE[default]+=" pcie_ports=compat intel_iommu=on iommu=pt pcie_port_pm=off"

The service runs correctly: aaudio unbound, apple_bce and all T2 modules unloaded in order before sleep, all reloaded cleanly after resume. No Thunderbolt D3hot errors, no audio XRUNs, no brcmfmac timeouts. Wi-Fi, keyboard/trackpad, USB-C data and charging all working after resume.

I've been using it as a daily driver and it works fine across multiple suspend cycles.

@joshpavlovich

joshpavlovich commented Jun 14, 2026

Copy link
Copy Markdown

@jjohnson - Thanks for putting this clean solution together to fix the suspend/resume long standing issue for T2 Mac users.

I have tested using the provided testing steps on my MacBookPro16,1. The suspend/resume now resumes rather than previously hanging the system. However the Wi-Fi does not properly load on resume consistently. The Wi-Fi interface (wlan0) only has properly loaded post resume 1% of the time when testing the fix.

Current result: suspend/resume works, Touch Bar comes back, Wi-Fi does NOT comes back.

Please see the attached t2-debug.txt:
t2-debug.txt

@voioo

voioo commented Jun 15, 2026

Copy link
Copy Markdown

Tested on MacBookPro15,4 (MacBook Pro 13", 2019)

  • Kernel: 7.0.12-arch1-Watanare-T2-1-t2
  • Userspace: PipeWire + WirePlumber
  • Suspend mode: s2idle [deep]

Setup:

  • Cloned the add-t2-suspend branch and ran migration 1780075490.sh
  • Applied the one-line os_timestamp patch to apple-bce-drv (audio/pcm.c:304: dev_timestampos_timestamp) and rebuilt the module

Results:

Condition Result
Clean suspend/resume (audio, Wi-Fi, Touch Bar, USB, keyboard) ✅ Pass
Playback resume after suspend (Spotify, local audio) ✅ Pass
Record after resume (microphone input) ✅ Pass
Wi-Fi reconnect after resume ✅ Pass
Touch Bar (tiny-dfr) after resume ✅ Pass
invalid position / scheduling while atomic kernel errors ❌ Gone
brcmfmac: brcmf_pcie_pm_enter_D3: Timeout ❌ Gone
appletbdrm *ERROR* Failed to send message on module unload ❌ Gone

Logs:

Jun 15 19:33:59 mbp2019 t2-suspend[2315]: 0000:02:00.3 Unbound
Jun 15 19:33:59 mbp2019 t2-suspend[2353]: Unloaded appletbdrm
Jun 15 19:33:59 mbp2019 t2-suspend[2371]: Unloaded hid_appletb_kbd
Jun 15 19:33:59 mbp2019 t2-suspend[2389]: Unloaded brcmfmac_wcc
Jun 15 19:34:00 mbp2019 t2-suspend[2396]: Unloaded apple_bce
Jun 15 19:34:00 mbp2019 t2-suspend[2398]: Ready to suspend
Jun 15 19:35:52 mbp2019 t2-suspend[2488]: Loaded apple_bce
Jun 15 19:35:54 mbp2019 t2-suspend[2517]: Loaded brcmfmac
Jun 15 19:35:54 mbp2019 t2-suspend[2527]: Loaded brcmfmac_wcc
Jun 15 19:35:55 mbp2019 t2-suspend[2543]: Loaded hid_appletb_kbd
Jun 15 19:35:55 mbp2019 t2-suspend[2552]: Loaded appletbdrm
Jun 15 19:35:55 mbp2019 t2-suspend[2562]: Resume complete

No XRUNs, no brcmfmac D3 timeouts, no appletbdrm errors. Everything working cleanly across multiple suspend/resume cycles. The os_timestamp patch is essential for clean audio after module reload — without it you get XRUNs from wild dev_timestamp after re-probe.

@jjohnson

Copy link
Copy Markdown
Author

@joshpavlovich Thanks for testing! This is the first data point on a 16,1 and confirms the module lifecycle works — suspend/resume and Touch Bar recovering is good progress.

The Wi-Fi D3cold issue (Unable to change power state from D3cold to D0) is specific to this model.

A couple things to try:

  1. Add pcie_port_pm=off to your kernel cmdline — this disables PCIe port power management and should prevent the D3cold entry entirely. This is the simplest fix if it works.
  2. If that doesn't help, try pcie_aspm=off — more aggressive, disables Active State Power Management at the PCIe link level.
  3. Alternative on the recovery side: try forcing the device out of D3cold before the module reload by adding this to the post-resume path in the script: echo "on" > /sys/bus/pci/devices/0000:05:00.0/power/control
    If the device leaves D3cold, the existing modprobe brcmfmac should succeed.

Also, if you could collect debug info with collect-t2-debug > ~/t2-debug.txt (defined in the PR description) and attach that file above instead of a lengthy debug in PR.

@hoclun-rigsep

Copy link
Copy Markdown

Hello. I have a target macbook that I can devote to testing if someone can give me appropriate instructions.

I'm sure people have noticed that #5129 is also open; here's making it explicit.

@voioo

voioo commented Jun 30, 2026

Copy link
Copy Markdown

Again,

Tested on MacBookPro15,4 (2019 13" MBP) with kernel 7.0.12-arch1-Watanare-T2-1-t2.

Suspend/resume works, but Bluetooth (BCM4377) was not recovering after resume. The hci_bcm4377 and bluetooth modules were missing from both PRE_MODS and POST_MODS in the t2-suspend script.

Fix applied to /usr/local/libexec/apple/t2-suspend:

PRE_MODS=(appletbdrm hid_appletb_kbd hid_appletb_bl brcmfmac_wcc brcmfmac hci_bcm4377 bluetooth)
POST_MODS=(brcmfmac brcmfmac_wcc hci_bcm4377 bluetooth hid_appletb_bl hid_appletb_kbd appletbdrm)

Test results after fix:

Condition Result
Bluetooth powered after suspend/resume Pass
hci_bcm4377 unloaded before suspend Pass
hci_bcm4377 reloaded after resume Pass
bluetoothctl show reports Powered: yes Pass

hci_bcm4377 must be explicitly unloaded in pre — when only apple_bce was removed, the module directory still existed, so load() silently skipped re-probing it on resume.

So now its fully usable 🎉

@joshpavlovich

joshpavlovich commented Jul 1, 2026

Copy link
Copy Markdown

Follow-up on MacBookPro16,1 Wi-Fi fix

After further investigation, the D3cold issue on the 16,1 is caused by unloading brcmfmac before sleep. The kernel PCI PM subsystem handles the D3cold->D0 transition correctly only when the driver stays bound — manual unbind/rebind breaks the sequence.

Fix applied:

  • Removed brcmfmac/brcmfmac_wcc from both PRE_MODS and POST_MODS — driver stays bound during sleep, kernel manages PCI PM natively
  • Added xhci_pci unload/reload (TouchBar USB re-enumeration)
  • systemctl start tiny-dfr -> systemctl restart tiny-dfr (no-op otherwise after appletbdrm reload)

Results on MacBookPro16,1 (BCM4364):

Condition Result
Clean suspend/resume Pass
Wi-Fi recovery (wlan0 instant) Pass
Touch Bar Pass
Resume time ~6s
Cycles tested 15+

Not needed:

  • pcie_port_pm=off / pcie_aspm=off — not required with this approach
  • echo on > power/control fallback — never triggered in 15 cycles
  • WiFi polling / service restart — wlan0 appears instantly every time

I would be happy to open a PR with these changes... Thanks

@jbisits

jbisits commented Jul 15, 2026

Copy link
Copy Markdown

@jjohnson and @voioo thank you very much for this fix! I have omarchy installed on a 2018 mac mini. To date suspend/resume has worked after I made the modifications suggested by t2linux but wifi would not be available after waking. Initially I tried the solution in this PR from @jjohnson but still the wifi did not return after waking from suspend. After making the changes to PRE_MODS and POST_MODS suggested by @voioo I have had wifi and bluetooth on every single wake from suspend since then (I think six or seven wakes). So thanks again! Let me know if there is any more info, e.g. the collect-t2-debug txt file, I can provide to help.

After updating/changing anything that is specific to omarchy, would this fix work on other arch distributions? Eventually I will try but just wondering if anyone already has. Thanks again!

* install/config/hardware/apple/t2-suspend: manages apple_bce module
  for clean suspend/resume by unbinding aaudio and unloading T2
  modules before suspend, reloading after resume
* install/config/hardware/apple/fix-t2-suspend.sh: install-time setup,
  copies script to /usr/local/libexec/omarchy/apple/t2-suspend and
  enables omarchy-apple-t2-suspend.service
* migrations/1780075490.sh: install t2-suspend for existing T2 installs
* Skip brcmfmac unload on BCM4364; kernel PCI PM handles D3cold, keep,
  unload on BCM4377b and unknown chipsets to avoid D3 timeout
* Add hci_bcm4377 to module lists for Bluetooth recovery after resume
* Fix tiny-dfr start: use reset-failed + restart instead of stop/start,
  start is a no-op on already-running units
Copilot AI review requested due to automatic review settings July 21, 2026 02:52

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

install/config/hardware/apple/fix-t2-suspend.sh:31

  • This script writes/updates a systemd unit but doesn’t run systemctl daemon-reload. Other installer steps reload the manager immediately after writing unit files/drop-ins (e.g., install/config/fast-shutdown.sh:5, install/config/plocate-ac-only.sh:3). Without a reload, updates to an already-loaded unit may not be picked up until reboot.

  sudo systemctl enable omarchy-apple-t2-suspend.service

  echo "T2 suspend/resume service enabled."

@jjohnson

jjohnson commented Jul 21, 2026

Copy link
Copy Markdown
Author

Thanks for the detailed follow-ups. I've incorporated both findings into the latest script:

Bluetooth — only hci_bcm4377 is cycled; the Bluetooth core module remains loaded and does not require reprobe.

Mac 16,1 dGPU — The script now auto-detects the BCM4364 chipset via its PCI ID (14e4:4464) and skips brcmfmac/brcmfmac_wcc on those models, keeping the driver bound so kernel PCI PM handles D3cold→D0 natively. BCM4377b chipsets; brcmfmac is still unloaded (to avoid D3 timeout).

The xhci_pci entry was dropped because it is built in (CONFIG_USB_XHCI_PCI=y on T2 kernels) and the attempted unload was a no-op. The earlier MBP16,1 test already showed Touch Bar recovery without an xHCI reset. Restarting tiny-dfr ensures the daemon is refreshed after the Touch Bar devices return.

@voioo @joshpavlovich if you can retest and let us know.

@hoclun-rigsep @jbisits Please retest the latest script on Mac mini and other models and report the results.

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.

10 participants