下面是我让 ai 帮我解决掉 wifi 和充电冲突的问题的脚本
#!/bin/bash
# Fix MacBook10,1 suspend/resume WiFi issues caused by BCM4350 brcmfmac PCIe D3 timeout
#
# ROOT CAUSE: systemd-sleep hooks run AFTER kernel PM tries to freeze devices.
# brcmfmac driver is still loaded when kernel calls pci_pm_suspend() -> D3 timeout
# error -5 -> suspend fails -> retry -> firmware corruption -> WiFi dead.
#
# SOLUTION: Use systemd services (Before=sleep.target / After=suspend.target)
# which execute BEFORE kernel PM freezes and AFTER kernel PM resumes.
#
# Run with: sudo bash ~/
fix-macbook12-suspend.shset -euo pipefail
if [[ $EUID -ne 0 ]]; then
echo "ERROR: Please run with sudo: sudo bash $0"
exit 1
fi
echo "=== 1/6 Removing old systemd-sleep hook ==="
if [[ -f /etc/systemd/system-sleep/
brcmfmac-suspend.sh ]]; then
rm /etc/systemd/system-sleep/
brcmfmac-suspend.sh echo "Removed old hook"
else
echo "Old hook not found, skipping"
fi
echo ""
echo "=== 2/6 Creating WiFi recovery script ==="
cat > /usr/local/bin/
brcmfmac-recovery.sh << 'SCRIPT'
#!/bin/bash
# Full PCIe reset + driver reload for BCM4350 on MacBook10,1
BRCM_PCI="0000:02:00.0"
LOG="/var/log/brcmfmac-resume.log"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG"
}
log "=== ${1:-manual} START ==="
# Step 1: Unload everything
log "Stopping iwd"
systemctl stop iwd 2>/dev/null
log "Removing brcmfmac modules"
modprobe -r brcmfmac_wcc 2>/dev/null || true
modprobe -r brcmfmac 2>/dev/null || true
sleep 1
# Step 2: PCIe bus reset (hardware level)
if [[ -f "/sys/bus/pci/devices/${BRCM_PCI}/reset" ]]; then
log "PCIe bus reset"
echo 1 > "/sys/bus/pci/devices/${BRCM_PCI}/reset" 2>/dev/null && log "reset OK" || log "reset failed"
sleep 2
else
log "No reset file, trying remove+rescan"
if [[ -d "/sys/bus/pci/devices/${BRCM_PCI}" ]]; then
echo 1 > "/sys/bus/pci/devices/${BRCM_PCI}/remove" 2>/dev/null || true
sleep 2
fi
echo 1 > /sys/bus/pci/rescan 2>/dev/null || true
sleep 3
fi
# Step 3: Reload driver
log "Loading brcmfmac"
modprobe brcmfmac 2>/dev/null && log "brcmfmac OK" || log "brcmfmac FAIL"
modprobe brcmfmac_wcc 2>/dev/null || true
sleep 2
# Step 4: Start iwd
log "Starting iwd"
systemctl start iwd 2>/dev/null && log "iwd OK" || log "iwd FAIL"
sleep 3
# Step 5: Verify
if ip link show wlan0 &>/dev/null && iw dev wlan0 info &>/dev/null 2>&1; then
log "wlan0 functional - SUCCESS"
else
log "wlan0 broken, retrying once more"
modprobe -r brcmfmac_wcc 2>/dev/null || true
modprobe -r brcmfmac 2>/dev/null || true
sleep 2
echo 1 > "/sys/bus/pci/devices/${BRCM_PCI}/reset" 2>/dev/null || true
sleep 2
modprobe brcmfmac 2>/dev/null || true
modprobe brcmfmac_wcc 2>/dev/null || true
sleep 3
systemctl restart iwd 2>/dev/null || true
sleep 2
ip link show wlan0 &>/dev/null && log "retry SUCCESS" || log "retry FAILED - may need reboot"
fi
log "=== ${1:-manual} DONE ==="
SCRIPT
chmod +x /usr/local/bin/
brcmfmac-recovery.shecho "Created: /usr/local/bin/
brcmfmac-recovery.sh"
echo ""
echo "=== 3/6 Creating suspend service (runs BEFORE kernel PM freeze) ==="
cat > /etc/systemd/system/brcmfmac-suspend.service << 'SVC'
[Unit]
Description=Unload brcmfmac WiFi driver before suspend
Before=sleep.target
StopWhenUnneeded=yes
[Service]
Type=oneshot
ExecStart=/usr/bin/rmmod brcmfmac_wcc
ExecStart=/usr/bin/rmmod brcmfmac
RemainAfterExit=yes
ExecStop=/usr/bin/modprobe brcmfmac
TimeoutSec=15
[Install]
WantedBy=sleep.target
SVC
echo "Created: /etc/systemd/system/brcmfmac-suspend.service"
echo ""
echo "=== 4/6 Creating resume service (runs AFTER kernel PM resume) ==="
cat > /etc/systemd/system/brcmfmac-resume.service << 'SVC'
[Unit]
Description=Reset and reload brcmfmac WiFi after resume
After=suspend.target hibernate.target hybrid-sleep.target suspend-then-hibernate.target
StopWhenUnneeded=yes
[Service]
Type=oneshot
ExecStart=/usr/local/bin/
brcmfmac-recovery.sh resume
TimeoutSec=30
[Install]
WantedBy=suspend.target hibernate.target hybrid-sleep.target suspend-then-hibernate.target
SVC
echo "Created: /etc/systemd/system/brcmfmac-resume.service"
echo ""
echo "=== 5/6 Creating udev rule for Type-C hotplug ==="
cat > /etc/udev/rules.d/99-brcmfmac-typec.rules << 'UDEV'
# Reset brcmfmac when Type-C port state changes and WiFi is broken
ACTION=="change|remove", SUBSYSTEM=="typec", RUN+="/usr/local/bin/
brcmfmac-typec-check.sh"
UDEV
chmod 644 /etc/udev/rules.d/99-brcmfmac-typec.rules
echo "Created: /etc/udev/rules.d/99-brcmfmac-typec.rules"
cat > /usr/local/bin/
brcmfmac-typec-check.sh << 'CHECK'
#!/bin/bash
# Only reset if WiFi is actually broken
if ip link show wlan0 &>/dev/null && iw dev wlan0 info &>/dev/null 2>&1; then
exit 0
fi
/usr/local/bin/
brcmfmac-recovery.sh typec-hotplug
CHECK
chmod +x /usr/local/bin/
brcmfmac-typec-check.shecho "Created: /usr/local/bin/
brcmfmac-typec-check.sh"
echo ""
echo "=== 6/6 Enabling services ==="
systemctl daemon-reload
systemctl enable brcmfmac-suspend.service
systemctl enable brcmfmac-resume.service
udevadm control --reload-rules
echo ""
echo "=== Verify ==="
echo "--- suspend service ---"
cat /etc/systemd/system/brcmfmac-suspend.service
echo ""
echo "--- resume service ---"
cat /etc/systemd/system/brcmfmac-resume.service
echo ""
echo "--- service status ---"
systemctl is-enabled brcmfmac-suspend.service brcmfmac-resume.service
echo ""
echo "=== DONE ==="
echo ""
echo "Test: close lid with charger -> wait 1min -> open lid"
echo "Check WiFi: iw dev wlan0 link"
echo "Check debug log: cat /var/log/brcmfmac-resume.log"
echo ""
echo "Manual recovery: sudo /usr/local/bin/
brcmfmac-recovery.sh manual"