Arch Linux on MacBook Pro (13-inch, 2017) におけるサスペンドのあれこれ
以前のブログで,サスペンドの復帰が早くなるように対策したのですが,まだ問題が残っていたので調査し解決しました.
以降は↑の「サスペンドからの復帰が早くなるようにする」に書いたsystemdの設定を行っていることが前提です.
環境
- MacBook Pro: 13-inch, 2017, Thunderbolt 3ポートx2 (A1708, MacBookPro14,1)
- Arch Linux
- Linux Kernel: 6.16.6-arch1-1
サスペンド後にネットワークが繋がらなくなる
問題
サスペンドから復帰したときに,iwdでエラーが出てWi-Fiに繋がらなくなる問題がありました.
問題発生時,journaldに以下のようなエラーが出ていました((12)とかの場合もあったような・・・?).
Received error during CMD_TRIGGER_SCAN: Input/output error (5)このMacBook Proに載っているのはBroadcomのネットワークデバイスなのですが,どうもBroadcomのデバイスはサスペンド周りのトラブルが多いらしいです(ChatGPT談).
lspci | grep -i network
# -> 02:00.0 Network controller: Broadcom Inc. and subsidiaries BCM4350 802.11ac Wireless Network Adapter (rev 05)解決方法
この問題に対して,サスペンドに入る前にカーネルモジュールをアンロードし,復帰したときに再ロードするようにすることで解決できました.
#!/usr/bin/bash
# unload brcmfmac during suspend
case $1 in
pre)
modprobe -r brcmfmac_wcc
modprobe -r brcmfmac
;;
post)
modprobe brcmfmac
modprobe brcmfmac_wcc
systemctl restart iwd
;;
esacsudo chmod +x /usr/local/lib/systemd/system-sleep/brcmfmac
sudo ln -s /usr/local/lib/systemd/system-sleep/brcmfmac /usr/lib/systemd/system-sleepトレードオフ
モジュールをアンロードしたことで,キーボードによるサスペンド復帰ができなくなり,サスペンド復帰のためには電源ボタンを押す必要が発生しました(モジュールがACPI wakeupに干渉している?). これは,トレードオフとして受け入れることにしました.
ただし,デフォルト設定だと電源ボタンでhaltする設定になっていて,サスペンド復帰するときに間違って2度押しなどすると電源が落ちてしまうので,設定を変更しました.
HandlePowerKey=suspendsudo systemctl restart systemd-logindサスペンドに入ったと思ったらすぐ復帰してしまうことがある
問題
サスペンドに入ってすぐに勝手に復帰してしまうことがありました.
解決方法
acpiのwakeupイベントを疑って,/proc/acpi/wakeupを一つずつdisabledにして試したところ,
どうもLID0のイベントのせいで復帰してしまっているようでした.
そこで,LID0をwakeupの対象外にすることで,問題は発生しなくなりました.
[Unit]
Description=Disable LID0 wakeup at boot
After=multi-user.target
[Service]
Type=oneshot
ExecStart=/bin/sh -c 'echo LID0 > /proc/acpi/wakeup'
[Install]
WantedBy=multi-user.targetsudo systemctl enable lid-disable-wakeup.serviceトレードオフ
蓋を開けたときに自動でサスペンドから復帰しなくなりましたが,電源ボタンを押すことで復帰できるので,それで妥協しました.
ディスプレイの蓋閉じでスリープに入らないことがある
問題
何回かに一度,ディスプレイの蓋を閉じてもスリープに入らないことがありました.
解決方法
デフォルトではsystemd-logindが蓋閉じを検知してDBUSへの書き込みするらしいのですが,これが不安定なようなので(ChatGPT談),acpidでsystemctl suspendを直接呼ぶようにしました.
sudo pacman -S acpidevent=button/lid.*close
action=/usr/bin/logger 'LID closed'; /usr/bin/systemctl suspendsudo systemctl restart acpidトレードオフ
トレードオフじゃないかもですが,acpidのLID opened / LID closedのjournaldログが記録されたりされなかったりするのですが,サスペンド前後で書き込みが失敗することがあるのだろうと思い妥協しました.
サスペンドの復帰に時間がかかることがある
問題
以前のブログでd3cold_allowedをdisabledにする設定を行いましたが,まだ復帰に時間がかかることがありました.
解決方法
journaldのログを見ると,復帰が遅いときに以下のようなログが出ていました.
Sep 27 22:16:12 HOSTNAME kernel: pcieport 0000:04:00.0: not ready 1023ms after resume; waiting
Sep 27 22:16:12 HOSTNAME kernel: pcieport 0000:04:00.0: not ready 2047ms after resume; waiting
Sep 27 22:16:12 HOSTNAME kernel: pcieport 0000:04:00.0: not ready 4095ms after resume; waiting
Sep 27 22:16:12 HOSTNAME kernel: pcieport 0000:04:00.0: not ready 8191ms after resume; waiting
Sep 27 22:16:12 HOSTNAME kernel: pcieport 0000:04:00.0: not ready 16383ms after resume; waiting
Sep 27 22:16:12 HOSTNAME kernel: pcieport 0000:04:00.0: not ready 32767ms after resume; waiting0000:04:00.0はThunderboltのデバイスのようです.
lspci | grep 04:00.0
# -> 04:00.0 PCI bridge: Intel Corporation DSL6540 Thunderbolt 3 Bridge [Alpine Ridge 4C 2015] (rev 02)そこで,Thunderboltのカーネルモジュールをサスペンド前後でunload/loadするようにしたところ,問題は起きなくなりました.
#!/usr/bin/bash
# unload thunderbold during suspend
case $1 in
pre)
modprobe -r thunderbolt
;;
post)
modprobe thunderbolt
;;
esacsudo chmod +x /usr/local/lib/systemd/system-sleep/thunderbolt
sudo ln -s /usr/local/lib/systemd/system-sleep/thunderbolt /usr/lib/systemd/system-sleepトレードオフ
今のところ弊害は発生していませんが,もしかするとUSB-Cで外部デバイスを接続してると,サスペンド前後でなにか問題が起きるかもしれません.(私の環境では電源しか繋いでいない.) このあたりは以下の記事でも触れられていました.
cf. MacBook Pro 2017でLinuxを使う場合のSuspend/Resumeの設定について | mbp2017-linux-note
サスペンド時のバッテリの持ちの比較
以前のブログと合わせて今回の変更を行ったあとに,サスペンド時のバッテリの持ちがMacOSと比べてどの程度なのか比較しました.
ちなみにバッテリの状態はこんな感じです(だいぶヘタってます).
upower -i /org/freedesktop/UPower/devices/battery_BAT0 | grep -E "(capacity|cycle)"
# -> charge-cycles: 142
# -> capacity: 84.071%起動状態での比較
まずは,ディスプレイ輝度を最大にし,起動した状態のままの状態でバッテリ残量がどのように推移するのか比較しました.
あまり違いはなく,どちらも6時間弱くらいでバッテリ残量0になりました.
サスペンド状態での比較
次にサスペンドした状態でたまに復帰させてバッテリ残量を確認し,すぐまたサスペンドする,という操作でバッテリ残量がどのように推移するのか比較しました.
こちらは大きな違いがありました. サスペンド状態なのでバッテリが減るまでに時間がかかり,1-2日くらいしか計測していませんが,Arch Linuxのほうが減りが速いのがわかります. MacOSがMacBookに最適化されているであろうことはもちろんのこと,色々Arch Linux用にワークアラウンド(ディープスリープをdisabledにしたり)を行っているのでしょうがないですね. それでも半日でバッテリ0になってしまうというレベルではないので,外出してイベント参加する,などにもまぁまぁ耐えられるかな,という印象でした.
その他 やったけどだめだったこと
うまくサスペンドに入らなかったり,サスペンド復帰後にWi-Fiが繋がらなかったりする症状に対して,試したけどうまくいかなかったことです. (これら単体や組み合わせを色々試したけどダメでした.)
サスペンド復帰後にカーネルモジュールを読み直す
sudo modprobe -r brcmfmac_wcc
sudo modprobe -r brcmfmac
sudo modprobe brcmfmac
sudo modprobe brcmfmac_wccサスペンド復帰後にiwdを再起動
sudo systemcrl restart iwdデバイスのunbind/bind
どれもno such file or directoryになる.(あるのになぜ・・・?)
ehco 0000:02:00.0 | sudo tee /sys/bus/pci/drivers/brcmfmac/unbind
ehco 0000:02:00.0 | sudo tee /sys/bus/pci/drivers/brcmfmac/bind
ehco 0000:02:00.0 | sudo tee /sys/bus/usb/drivers/brcmfmac/unbind
ehco 0000:02:00.0 | sudo tee /sys/bus/usb/drivers/brcmfmac/bind
ehco 0000:02:00.0 | sudo tee /sys/bus/sdio/drivers/brcmfmac/unbind
ehco 0000:02:00.0 | sudo tee /sys/bus/sdio/drivers/brcmfmac/bindrfkillでのblock/unblock
unsudo rfkill block wifiデバイスの抜き差しをエミュレートする
echo 1 | sudo tee /sys/bus/pci/devices/0000:02:00.0/remove
echo 1 | sudo tee /sys/bus/pci/rescan特定デバイスをスリープから外す
systemdのsleep.conf.dにDeviceAllowを書いて試しました.
[Sleep]
DeviceAllow=char-* block-* !sys-subsystem-pci-devices-0000:03:00.0