From 5d933479b44e3ced7468e8212ba7e3f62d2e07bc Mon Sep 17 00:00:00 2001 From: Jason Zimdars Date: Fri, 27 Mar 2026 08:32:04 -0500 Subject: [PATCH 1/2] Fix suspend/sleep on T2 MacBooks T2 MacBooks crash during suspend because the hardware doesn't support S3 (deep) sleep, the brcmfmac WiFi driver fails to enter D3 power state, and NVMe/T2 bridge devices crash when entering d3cold during longer sleep periods. This adds three fixes to the T2 Mac installer and a migration for existing installations: - Force s2idle (freeze) as the suspend mode via sleep.conf and kernel cmdline parameter mem_sleep_default=s2idle - Create a systemd service that dynamically disables d3cold on Apple NVMe and T2 Bridge PCI devices before suspend - Unload brcmfmac and apple-bce modules before suspend and reload them on wake to prevent driver crashes The d3cold fix uses dynamic PCI device discovery (vendor 106b, devices 2005/1801) rather than hardcoded bus addresses so it works across all T2 Mac models. Fixes #1840 Validated on MacBookAir9,1 with linux-t2 6.17.7. Co-Authored-By: Claude Opus 4.6 (1M context) --- install/config/hardware/fix-apple-t2.sh | 33 ++++++++++++++++- migrations/1774617744.sh | 49 +++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 migrations/1774617744.sh diff --git a/install/config/hardware/fix-apple-t2.sh b/install/config/hardware/fix-apple-t2.sh index 67d1644c1f..43c8f23729 100644 --- a/install/config/hardware/fix-apple-t2.sh +++ b/install/config/hardware/fix-apple-t2.sh @@ -30,6 +30,37 @@ EOF sudo mkdir -p /etc/limine-entry-tool.d cat </dev/null # Generated by Omarchy installer for T2 Mac support -KERNEL_CMDLINE[default]+=" intel_iommu=on iommu=pt pcie_ports=compat" +KERNEL_CMDLINE[default]+=" intel_iommu=on iommu=pt pcie_ports=compat mem_sleep_default=s2idle" EOF + + # T2 Macs cannot use S3 (deep) sleep — force s2idle (freeze) mode + sudo mkdir -p /etc/systemd/sleep.conf.d + cat </dev/null +[Sleep] +SuspendState=freeze +EOF + + # Manage T2 modules and PCI power states around suspend: + # - Disable d3cold on Apple NVMe and T2 Bridge to prevent wake failures + # - Unload brcmfmac (WiFi) to avoid D3 suspend timeout + # - Unload apple-bce (keyboard/trackpad) to ensure clean resume + cat <<'EOF' | sudo tee /etc/systemd/system/omarchy-suspend-t2.service >/dev/null +[Unit] +Description=Manage T2 modules around suspend +Before=sleep.target +StopWhenUnneeded=yes + +[Service] +User=root +Type=oneshot +RemainAfterExit=yes +ExecStart=/bin/bash -c 'for dev in /sys/bus/pci/devices/*/; do vendor=$(cat "$dev/vendor" 2>/dev/null); device=$(cat "$dev/device" 2>/dev/null); if [[ "$vendor" == "0x106b" ]] && [[ "$device" == "0x2005" || "$device" == "0x1801" ]]; then echo 0 > "$dev/d3cold_allowed" 2>/dev/null; fi; done; rmmod brcmfmac_wcc 2>/dev/null; rmmod brcmfmac 2>/dev/null; rmmod -f apple-bce 2>/dev/null' +ExecStop=/bin/bash -c 'modprobe apple-bce; sleep 2; modprobe brcmfmac' + +[Install] +WantedBy=sleep.target +EOF + + chrootable_systemctl_enable omarchy-suspend-t2.service + sudo systemctl daemon-reload fi diff --git a/migrations/1774617744.sh b/migrations/1774617744.sh new file mode 100644 index 0000000000..ca1cdd4dd4 --- /dev/null +++ b/migrations/1774617744.sh @@ -0,0 +1,49 @@ +echo "Fix suspend/sleep on T2 MacBooks" + +# Only run on T2 Macs +if ! lspci -nn | grep -q "106b:180[12]"; then + exit 0 +fi + +# Force s2idle (freeze) suspend mode — T2 Macs cannot use S3 (deep) sleep +sudo mkdir -p /etc/systemd/sleep.conf.d +cat </dev/null +[Sleep] +SuspendState=freeze +EOF + +# Add mem_sleep_default=s2idle to kernel cmdline if not present +T2_CONF="/etc/limine-entry-tool.d/t2-mac.conf" +if [[ -f "$T2_CONF" ]] && ! grep -q "mem_sleep_default=s2idle" "$T2_CONF"; then + sudo sed -i 's/pcie_ports=compat"/pcie_ports=compat mem_sleep_default=s2idle"/' "$T2_CONF" +fi + +# Create and enable suspend service if not already present +if [[ ! -f /etc/systemd/system/omarchy-suspend-t2.service ]]; then + cat <<'EOF' | sudo tee /etc/systemd/system/omarchy-suspend-t2.service >/dev/null +[Unit] +Description=Manage T2 modules around suspend +Before=sleep.target +StopWhenUnneeded=yes + +[Service] +User=root +Type=oneshot +RemainAfterExit=yes +ExecStart=/bin/bash -c 'for dev in /sys/bus/pci/devices/*/; do vendor=$(cat "$dev/vendor" 2>/dev/null); device=$(cat "$dev/device" 2>/dev/null); if [[ "$vendor" == "0x106b" ]] && [[ "$device" == "0x2005" || "$device" == "0x1801" ]]; then echo 0 > "$dev/d3cold_allowed" 2>/dev/null; fi; done; rmmod brcmfmac_wcc 2>/dev/null; rmmod brcmfmac 2>/dev/null; rmmod -f apple-bce 2>/dev/null' +ExecStop=/bin/bash -c 'modprobe apple-bce; sleep 2; modprobe brcmfmac' + +[Install] +WantedBy=sleep.target +EOF + + sudo systemctl daemon-reload + sudo systemctl enable omarchy-suspend-t2.service +fi + +# Clean up old user-created suspend-t2.service (pre-omarchy naming) +if [[ -f /etc/systemd/system/suspend-t2.service ]]; then + sudo systemctl disable suspend-t2.service 2>/dev/null + sudo rm -f /etc/systemd/system/suspend-t2.service + sudo systemctl daemon-reload +fi From fbfd7528b129ac14c04d5efa84158fbbd97b3fdf Mon Sep 17 00:00:00 2001 From: Jason Zimdars Date: Fri, 27 Mar 2026 09:10:31 -0500 Subject: [PATCH 2/2] Address PR review feedback - Add PCI device ID 0x1802 to d3cold filter to match all T2 bridge variants (aligns with the T2 detection logic using 106b:180[12]) - Use plain systemctl enable instead of chrootable_systemctl_enable to avoid starting the service during install (which would unload WiFi and keyboard modules mid-install) - Run limine-mkinitcpio in migration so kernel cmdline change takes effect without waiting for a kernel update Co-Authored-By: Claude Opus 4.6 (1M context) --- install/config/hardware/fix-apple-t2.sh | 4 ++-- migrations/1774617744.sh | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/install/config/hardware/fix-apple-t2.sh b/install/config/hardware/fix-apple-t2.sh index 43c8f23729..477f52599a 100644 --- a/install/config/hardware/fix-apple-t2.sh +++ b/install/config/hardware/fix-apple-t2.sh @@ -54,13 +54,13 @@ StopWhenUnneeded=yes User=root Type=oneshot RemainAfterExit=yes -ExecStart=/bin/bash -c 'for dev in /sys/bus/pci/devices/*/; do vendor=$(cat "$dev/vendor" 2>/dev/null); device=$(cat "$dev/device" 2>/dev/null); if [[ "$vendor" == "0x106b" ]] && [[ "$device" == "0x2005" || "$device" == "0x1801" ]]; then echo 0 > "$dev/d3cold_allowed" 2>/dev/null; fi; done; rmmod brcmfmac_wcc 2>/dev/null; rmmod brcmfmac 2>/dev/null; rmmod -f apple-bce 2>/dev/null' +ExecStart=/bin/bash -c 'for dev in /sys/bus/pci/devices/*/; do vendor=$(cat "$dev/vendor" 2>/dev/null); device=$(cat "$dev/device" 2>/dev/null); if [[ "$vendor" == "0x106b" ]] && [[ "$device" == "0x2005" || "$device" == "0x1801" || "$device" == "0x1802" ]]; then echo 0 > "$dev/d3cold_allowed" 2>/dev/null; fi; done; rmmod brcmfmac_wcc 2>/dev/null; rmmod brcmfmac 2>/dev/null; rmmod -f apple-bce 2>/dev/null' ExecStop=/bin/bash -c 'modprobe apple-bce; sleep 2; modprobe brcmfmac' [Install] WantedBy=sleep.target EOF - chrootable_systemctl_enable omarchy-suspend-t2.service + sudo systemctl enable omarchy-suspend-t2.service sudo systemctl daemon-reload fi diff --git a/migrations/1774617744.sh b/migrations/1774617744.sh index ca1cdd4dd4..be58df941e 100644 --- a/migrations/1774617744.sh +++ b/migrations/1774617744.sh @@ -18,6 +18,11 @@ if [[ -f "$T2_CONF" ]] && ! grep -q "mem_sleep_default=s2idle" "$T2_CONF"; then sudo sed -i 's/pcie_ports=compat"/pcie_ports=compat mem_sleep_default=s2idle"/' "$T2_CONF" fi +# Regenerate boot config so kernel cmdline change takes effect +if command -v limine-mkinitcpio >/dev/null 2>&1; then + sudo limine-mkinitcpio +fi + # Create and enable suspend service if not already present if [[ ! -f /etc/systemd/system/omarchy-suspend-t2.service ]]; then cat <<'EOF' | sudo tee /etc/systemd/system/omarchy-suspend-t2.service >/dev/null @@ -30,7 +35,7 @@ StopWhenUnneeded=yes User=root Type=oneshot RemainAfterExit=yes -ExecStart=/bin/bash -c 'for dev in /sys/bus/pci/devices/*/; do vendor=$(cat "$dev/vendor" 2>/dev/null); device=$(cat "$dev/device" 2>/dev/null); if [[ "$vendor" == "0x106b" ]] && [[ "$device" == "0x2005" || "$device" == "0x1801" ]]; then echo 0 > "$dev/d3cold_allowed" 2>/dev/null; fi; done; rmmod brcmfmac_wcc 2>/dev/null; rmmod brcmfmac 2>/dev/null; rmmod -f apple-bce 2>/dev/null' +ExecStart=/bin/bash -c 'for dev in /sys/bus/pci/devices/*/; do vendor=$(cat "$dev/vendor" 2>/dev/null); device=$(cat "$dev/device" 2>/dev/null); if [[ "$vendor" == "0x106b" ]] && [[ "$device" == "0x2005" || "$device" == "0x1801" || "$device" == "0x1802" ]]; then echo 0 > "$dev/d3cold_allowed" 2>/dev/null; fi; done; rmmod brcmfmac_wcc 2>/dev/null; rmmod brcmfmac 2>/dev/null; rmmod -f apple-bce 2>/dev/null' ExecStop=/bin/bash -c 'modprobe apple-bce; sleep 2; modprobe brcmfmac' [Install]