電源管理/復帰トリガー

提供: ArchWiki
2022年7月22日 (金) 18:12時点におけるAshMyzk (トーク | 投稿記録)による版 (ページの作成:「Category:ハードウェア検出とトラブルシューティング Category:電源管理 Category:ノートパソコン en:Wakeup triggers {{Related ar…」)
(差分) ← 古い版 | 最新版 (差分) | 新しい版 → (差分)
ナビゲーションに移動 検索に移動

関連記事

復帰トリガーとは、ハードウェアの任意の省電力状態からシステムを復帰させることのできるイベントソースです。自明な例としては、電源ボタンやスリープボタン、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]