Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save mogul/6179e6384eb9242a7a1865df1d841a53 to your computer and use it in GitHub Desktop.

Select an option

Save mogul/6179e6384eb9242a7a1865df1d841a53 to your computer and use it in GitHub Desktop.
Fix loss of Wifi/Bluetooth on CachyOS/Arch t2linux system

Fix for WiFi/Bluetooth Not Working After Hibernation on T2 MacBooks

This guide documents how to fix WiFi and Bluetooth connectivity issues after hibernation on T2 MacBooks (like MacBookAir9,1) running CachyOS/Arch Linux.

Problem Description

After resuming from hibernation (long sleep), WiFi and Bluetooth devices appear in ip link show but show NO-CARRIER state and cannot connect to networks. Running the firmware.sh script temporarily fixes the issue until the next hibernation.

Prerequisites

IMPORTANT: This guide assumes hibernation itself is working. If you cannot successfully hibernate and resume your system, you MUST fix hibernation first before proceeding with WiFi/Bluetooth fixes.

Pre-Step: Verify Hibernation Works

Test hibernation:

sudo systemctl hibernate

If your system:

  • Fails to hibernate: You have hibernation configuration issues. See Appendix A: Setting Up Hibernation first.
  • Hibernates but won't resume: Check your bootloader configuration and resume kernel parameters.
  • Hibernates and resumes successfully: Continue with this guide.

Root Cause

The Broadcom WiFi card in T2 MacBooks enters power save mode before hibernation. When the system resumes, the card's power state doesn't properly reinitialize, causing it to remain in a non-functional state despite the interface appearing "up."

Solution Overview

  1. Install firmware properly (one-time setup)
  2. Configure hibernation (if not already done)
  3. Create a system-sleep hook that:
    • Disables WiFi power save before hibernating
    • Re-enables power save after resuming (for battery life)

Step-by-Step Solution

Step 1: Install WiFi/Bluetooth Firmware

If not already installed, run the t2linux firmware script:

cd ~/firmware  # or wherever your firmware.sh is located
sudo bash firmware.sh get_from_efi

This extracts firmware from the EFI partition and installs it to /lib/firmware/brcm/.

Verification:

ls -la /lib/firmware/brcm/ | grep brcmfmac
ip link show | grep wlan

Step 2: Configure Hibernation (If Not Already Working)

See Appendix A for full hibernation setup instructions.

Quick verification:

swapon --show  # Should show a swapfile >= your RAM size
cat /proc/cmdline | grep resume  # Should show resume=UUID=xxx resume_offset=yyy

Step 3: Create the Power Management Hook

Create a systemd-sleep hook that manages WiFi power state around hibernation:

sudo tee /usr/lib/systemd/system-sleep/wifi-hibernate-manager << 'EOF'
#!/bin/bash

case "$1" in
    pre)
        # Before sleep: Disable power save so WiFi works on resume
        logger "Pre-hibernate: Disabling WiFi power save"
        /sbin/iw dev wlan0 set power_save off 2>/dev/null || true
        ;;
    post)
        # After resume: Re-enable power save for battery life
        # Wait a bit for WiFi to settle
        sleep 3
        logger "Post-resume: Re-enabling WiFi power save"
        /sbin/iw dev wlan0 set power_save on 2>/dev/null || true
        ;;
esac
EOF

sudo chmod +x /usr/lib/systemd/system-sleep/wifi-hibernate-manager

Step 4: Test the Solution

  1. Check current power save state (should be ON for normal battery life):

    iw dev wlan0 get power_save
    # Expected: "Power save: on"
  2. Test hibernation:

    sudo systemctl hibernate
  3. After resume, verify:

    # WiFi should be connected and working
    ip link show wlan0  # Should show UP and have an IP
    
    # Power save should be re-enabled for battery life
    iw dev wlan0 get power_save  # Should show "Power save: on"
    
    # Bluetooth should also be working
    bluetoothctl

How It Works

The Problem:

  • Broadcom WiFi cards (brcmfmac driver) don't properly reinitialize power state after hibernation
  • When power save is enabled, the card enters a low-power state before hibernation
  • On resume, the card can't exit this state properly, resulting in NO-CARRIER

The Solution:

  • The system-sleep hook runs pre (before) and post (after) hibernation
  • Before hibernation: Disables power save → card stays in active state → survives hibernation
  • After resuming: Re-enables power save → returns to normal battery-saving behavior

Battery Impact:

  • Normal use: Power save ON (saves ~10-20% battery)
  • Only disabled during hibernation transition (negligible impact)

Troubleshooting

Issue: WiFi still doesn't work after resume

  1. Check if the hook is executing:

    journalctl | grep "Pre-hibernate\|Post-resume"
  2. Verify the hook is executable:

    ls -la /usr/lib/systemd/system-sleep/wifi-hibernate-manager
  3. Check if firmware is properly installed:

    ls /lib/firmware/brcm/brcmfmac*.bin

Issue: Power save doesn't re-enable after resume

The hook includes a 3-second delay to allow WiFi to settle. If your system needs more time:

sudo nano /usr/lib/systemd/system-sleep/wifi-hibernate-manager
# Change "sleep 3" to "sleep 5" or longer

Issue: Hook conflicts with other services

If you previously created systemd services for this fix (e.g., wifi-power-save-off.service), disable them:

sudo systemctl disable wifi-power-save-off.service 2>/dev/null || true
sudo rm -f /etc/systemd/system/wifi-power-save-off.service
sudo systemctl daemon-reload

System Information

This solution was tested and verified on:

  • Hardware: MacBookAir9,1 (T2 Mac)
  • OS: CachyOS (Arch Linux-based)
  • Kernel: 6.19.9-1-cachyos
  • WiFi Card: Broadcom BCM4364 (brcmfmac driver)
  • Firmware: Extracted from macOS EFI partition using firmware.sh

References


Appendix A: Setting Up Hibernation

If hibernation is not working on your system, follow these steps:

A1. Create Swap File (must be >= RAM size)

Check your RAM:

free -h

Create swap file (8GB for 7.6GB RAM):

sudo swapoff /swapfile  # If existing swapfile exists
sudo rm /swapfile       # Remove old swapfile

sudo truncate -s 0 /swapfile
sudo chattr +C /swapfile  # Disable COW for swap (BTRFS only)
sudo fallocate -l 8G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

A2. Get Swap File Offset

For BTRFS filesystems:

sudo btrfs inspect-internal map-swapfile -r /swapfile
# Note the number (e.g., 13696046)

For other filesystems:

sudo filefrag -v /swapfile | awk '$1=="0:" {print substr($4, 1, length($4)-2)}'

A3. Configure Kernel Parameters

Get your swap partition UUID:

findmnt -no UUID /

Edit your bootloader config (example for Limine):

sudo nano /boot/limine.conf

Add to your kernel cmdline:

resume=UUID=YOUR_SWAP_PARTITION_UUID resume_offset=YOUR_OFFSET_NUMBER

Example:

cmdline: quiet rw root=UUID=xxx resume=UUID=xxx resume_offset=13696046

A4. Reboot and Test

sudo reboot

# After reboot, verify parameters:
cat /proc/cmdline | grep resume

# Test hibernation:
sudo systemctl hibernate

A5. Common Hibernation Issues

Error: "Specified resume device is missing or is not an active swap device"

  • Solution: You forgot to add resume and resume_offset kernel parameters, or the offset is wrong.

Error: System hibernates but won't resume

  • Solution: Check that the resume partition UUID is correct. For swap files, verify the offset calculation.

System immediately wakes after hibernating

  • Solution: Check wake-on-LAN settings or USB devices. See Arch Wiki troubleshooting section.

Document Version: 1.0 Last Updated: 2026-03-22

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