電源管理/復帰トリガー
復帰トリガーとは、ハードウェアの任意の省電力状態からシステムを復帰させることのできるイベントソースです。自明な例としては、電源ボタンやスリープボタン、Wake-on-LAN 機能、ノートパソコンのリッドスイッチがあります。復帰トリガーは、以下に挙げる様々なカーネルインターフェイスにより制御できます。すべての可能なトリガーをカバーする統一されたインターフェイスは存在しません。
目次
復帰トリガーインターフェイス
/proc/acpi/wakeup
Reading the /proc/acpi/wakeup
file yields list of ACPI-registered wakeup sources with corresponding sysfs
IDs where available. Writing an entry from the Device column to the file toggles its state. For example, to disable waking on opening the laptop lid, run:
# echo "LID" > /proc/acpi/wakeup
/sys/module/acpi/parameters/ec_no_wakeup
This file represents the value of ACPI kernel module option ec_no_wakeup
, which controls passing the wakeup triggers from embedded controller when the system is in the suspend-to-idle (s2idle
) power state [1]. On modern laptops embedded controller wakeups can cause excessive battery drain in some cases.
/sys/devices/
Each sysfs
device that supports wakeup contains the file wakeup
in a device's power
subdirectory. The file contains wakeup trigger's status and can be written to as well. Bus controllers as well as endpoint devices can be capable of waking up the system. For example, to disable wakeups from the first USB controller (bus), run:
# echo "disabled" > /sys/bus/usb/devices/usb1/power/wakeup
An endpoint device should be able to wake the device if the trigger is enabled regardless of the controller's setting, however this might be hardware-dependent.
Program PowerTOP interfaces with sysfs
, but it only lists wakeup triggers of networking and USB devices by reading /sys/class/net/
and /sys/bus/usb/devices/
(containing symlinks to /sys/devices/
).
/sys/class/wakeup/*
Almost all wakeup triggers can be found in the /sys/class/wakeup
directory, which contains symlinks to all relevant devices. This is useful for finding possible wakeup triggers by going through subdirectories. Some of the triggers can correspond to virtual devices while hardware-related wakeup triggers are the ones that contain at least one of these files:
/sys/class/wakeup/*/device/physical_node/power/wakeup /sys/class/wakeup/*/device/power/wakeup
Some of wakeup triggers in /sys/class/wakeup
also provide a link to the cryptic /proc/acpi/wakeup
names where the following file is present:
/sys/class/wakeup/*/device/path
永続的な設定
The one-time methods should suffice for setting the /proc/acpi/wakeup
states and acpi.ec_no_wakeups
kernel parameter while the event-driven approach with udev is the reliable way to configure the sysfs
devices.
One-time with systemd
The ec_no_wakeups
ACPI kernel module option can be set at boot as described in the article. The standard solution to set the sysfs
values at boot are systemd services such as in this troubleshooting case. Another systemd-based manager for /proc/acpi/wakeup
is wakeup-triggersAUR.
Some systems can override some of the ACPI wakeup triggers upon power state transition(s) in what is more of a bug rather than a feature. If the hardware is overriding triggers at predictable times that can still be solved with appropriately crafted systemd units. The sleep.target
is a generic target covering all different suspended states that might be helpful in this case, but there is no generic wakeup.target
[2].
This method only works reliably with sysfs
devices that are connected all the time.
Event-driven with udev
Setting the wakeup trigger status with udev rules is an event-driven method that works reliably any time the devices with wakeup triggers are connected. The key is to detect an addition of a new device (ACTION=="add"
) in a rule and set the wakeup trigger status with ATTR{power/wakeup}="disabled"
. If the hardware is resetting this setting, udev can try to circumvent it by reapplying rules upon every device change (ACTION=="add|change"
). A device tree with possible parameters for matching a particular device found in sysfs
can be obtained with udevadm info -q all -a /sys/devices/...
.
A representative common example here would be a Logitech Unifying USB receiver. Its wakeup trigger should be enabled by default and if that is not desired, a solution could be an udev rule, as follows:
/etc/udev/rules.d/logitech-unifying.rules
ACTION=="add", SUBSYSTEM=="usb", DRIVERS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c52b", ATTR{power/wakeup}="disabled"
The reverse case to enable the necessary trigger(s) is described in the udev article.
udev triggers so early in the device enumeration that disabling wakeup trigger with the method above causes (some?) disabled triggers to not be listed in /sys/class/wakeup
. That might be dependent on whether the device was already present at boot and needs further clarification.
トラブルシューティング
デバイスやバスのツリーを一覧表示する
これらの補助コマンドは、特定のシステムにあるすべての復帰トリガーを把握したい時や、udev ルールを記述したり、一般的な復帰ソースのトラブルシューティングをしたりする時に便利です:
# lshw -businfo -numeric # lspci -DPPnn # lsusb -tvv
サスペンドからすぐに復帰する
LynxPoint や LynxPoint-LP チップセットが搭載された Intel Haswell の場合、サスペンドからすぐに復帰してしまうと報告されています。BIOS の ACPI 実装に問題があり起動時に xhci_hcd
モジュールによって ACPI イベントが解釈されてしまうのが原因です。解決策としてカーネルによってケースバイケースで問題のあるシステムがブラックリスト (XHCI_SPURIOUS_WAKEUP
) に追加されています [3]。
サスペンド中に USB デバイスを接続したときなどに ACPI の復帰トリガーが有効になって復帰してしまいます。ブラックリストに追加されるまで一時的な応急処置としては復帰トリガーを無効化する方法があります。以下の設定で USB による復帰を無効化することができます [4]。
現在の設定を確認:
$ cat /proc/acpi/wakeup
Device S-state Status Sysfs node ... EHC1 S3 *enabled pci:0000:00:1d.0 EHC2 S3 *enabled pci:0000:00:1a.0 XHC S3 *enabled pci:0000:00:14.0 ...
問題のデバイスは EHC1
, EHC1
, XHC
(USB 3.0) です。状態を変更するには root でデバイス名をファイルに echo してください:
# echo EHC1 > /proc/acpi/wakeup # echo EHC2 > /proc/acpi/wakeup # echo XHC > /proc/acpi/wakeup
上記のコマンドでサスペンドが再度機能するようになります。ただし、設定は一時的なものなので再起動するたびに設定し直す必要があります。自動化したい場合は systemd#ユニットファイルを見てください。詳しくは BBS スレッド を参照。
nouveau ドライバ
nouveau ドライバを使用している場合、サスペンドから即座に復帰してしまう原因はドライバのバグかもしれません(時々 GPU のサスペンドを妨げてしまいます)。回避策は、スリープする直前に nouveau
カーネルモジュールをアンロードして、復帰した時に再びロードすることです。これを行うには、以下のスクリプトを作成してください:
/usr/lib/systemd/system-sleep/10-nouveau.sh
#!/bin/bash case $1/$2 in pre/*) # echo "Going to $2..." /usr/bin/echo "0" > /sys/class/vtconsole/vtcon1/bind /usr/bin/rmmod nouveau ;; post/*) # echo "Waking up from $2..." /usr/bin/modprobe nouveau /usr/bin/echo "1" > /sys/class/vtconsole/vtcon1/bind ;; esac
1つ目の echo 行は、フレームバッファコンソールドライバ(fbcon
)から nouveaufb
をアンバインドします。通常、この例にあるように vtcon1
ですが、他の vtcon*
である場合もあります。どれがフレームバッファデバイスであるかは /sys/class/vtconsole/vtcon*/name
を確認してください[5]。