Power Management: Difference between revisions

imported>Samueldr
Created page with "{{expansion}} == Suspend == === Suspend hooks === NixOS provides the {{nixos:option|powerManagement.resumeCommands}} option which defines commands that are added to a globa..."
 
m remove some whitespace and fix typo
 
(8 intermediate revisions by 6 users not shown)
Line 1: Line 1:
{{expansion}}
This article covers configurations related to power management in terms of energy saving modes of various devices and components.


== Suspend ==
== Configuration ==
 
=== Hard drives ===
Following snippet configures [[Udev]] rules which automatically run the program <code>hdparm</code> to enable power saving modes for hard disks, especially rotational drives mapped to <code>/dev/sd*</code>.<syntaxhighlight lang="nix">
services.udev.extraRules =
  let
    mkRule = as: lib.concatStringsSep ", " as;
    mkRules = rs: lib.concatStringsSep "\n" rs;
  in mkRules ([( mkRule [
    ''ACTION=="add|change"''
    ''SUBSYSTEM=="block"''
    ''KERNEL=="sd[a-z]"''
    ''ATTR{queue/rotational}=="1"''
    ''RUN+="${pkgs.hdparm}/bin/hdparm -B 90 -S 41 /dev/%k"''
  ])]);
</syntaxhighlight>The <code>hdparm</code> parameters <code>-B</code> and <code>-S</code> define power saving modes and in case of <code>-S</code> the standby (spindown) timeout. The number 41 means therefore: Turn off the motor after 205 = 41*5 seconds.


=== Suspend hooks ===
=== Suspend hooks ===
NixOS provides the {{nixos:option|powerManagement.resumeCommands}} option which defines commands that are added to a global script that will be executed after resuming.
NixOS provides the {{nixos:option|powerManagement.resumeCommands}} option which defines commands that are added to a global script that will be executed after resuming.


Line 13: Line 27:
</syntaxhighlight>
</syntaxhighlight>


It is also possible, to use the <code>post-resume</code> target directly to make a service.
It is also possible to use the <code>post-resume</code> target directly to make a service.
Refer to the [[Systemd Services]] article for details about writing systemd services for NixOS.


<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
Line 28: Line 41:
</syntaxhighlight>
</syntaxhighlight>


=== Hibernation ===
Hibernation requires a configured swap device. See [https://nixos.org/manual/nixos/stable/#ch-installation installation instructions] on how to create a swap partition.
Please note that <code>resumeDevice</code> must match the output of  <code>swapon -s</code> especially if you're dealing with mapped volumes (LUKS, logical volumes, logical volumes under LUKS, etc.). If you're using a swapfile, you must also [https://search.nixos.org/options?channel=unstable&show=boot.resumeDevice&from=0&size=50&sort=relevance&type=packages&query=resume+offset specify the offset to it.]
Therefore, an example configuration could look like this:<syntaxhighlight lang="nix">
/*
  I'm hibernating into a logical volume that's also under LUKS. Pretty cool, right?
*/
swapDevices = [
  {
    device = "/dev/VG/SWAP";
  }
];
boot.resumeDevice = "/dev/dm-7";
</syntaxhighlight>Derived from a system with the following output from <code>swapon -s</code> :<syntaxhighlight>
Filename                                Type            Size          Used            Priority
/dev/dm-7                              partition      67108860      00
/dev/zram0                              partition      32881148      032767
</syntaxhighlight>
Test and use hibernation with the following command:<syntaxhighlight lang="nix">
systemctl hibernate
</syntaxhighlight>
== Tips and tricks ==
=== Go into hibernate after specific suspend time ===
Using following configuration, your system will go from suspend into hibernate after 1 hour:<syntaxhighlight lang="nix">
systemd.sleep.extraConfig = ''
  HibernateDelaySec=1h
'';
</syntaxhighlight>
Or, to disable suspend entirely, consider a configuration like this:
<syntaxhighlight lang="nix">
systemd.sleep.extraConfig = ''
  AllowSuspend=no
  AllowHibernation=no
  AllowHybridSleep=no
  AllowSuspendThenHibernate=no
'';
</syntaxhighlight>
== Troubleshooting ==
==== System immediately wakes up from suspend ====
Particularly in some Gigabyte motherboards with NVMe drives, the system may immediately wake up from being suspended.
This can be worked around by disabling the wakeup triggers for the offending components:
===== Solution 1: Disabling wakeup triggers for all PCIe devices =====
If you don't need your system to wakeup via PCIe components you can simply disable it for all without needing to determine which component is causing problems.
<syntaxhighlight lang="nix">
services.udev.extraRules = ''
  ACTION=="add", SUBSYSTEM=="pci", DRIVER=="pcieport", ATTR{power/wakeup}="disabled"
'';
</syntaxhighlight>
===== Solution 2: Disable a common NVMe interface =====
Specifically on Gigabyte motherboards you can try targetting only the NVMe ports.
<syntaxhighlight lang="nix">
services.udev.extraRules = ''
  ACTION=="add" SUBSYSTEM=="pci" ATTR{vendor}=="0x1022" ATTR{device}=="0x1483" ATTR{power/wakeup}="disabled"
'';
</syntaxhighlight>
===== Solution 3: Disable a single device's wakeup triggers =====
If you wish to be more granular in what components should no longer be able to wakeup your system, you can find out which component is causing the wakeup events.
First, list all components and their current wakeup status:
<syntaxhighlight lang="sh">
$ cat /proc/acpi/wakeup
Device S-state   Status  Sysfs node
GP12   S4 *enabled  pci:0000:00:07.1
GP13   S4 *disabled  pci:0000:00:08.1
XHC0   S4 *enabled  pci:0000:0a:00.3
GP30   S4 *disabled
....
PT27   S4 *disabled
PT28   S4 *disabled
PT29   S4 *disabled  pci:0000:03:09.0
</syntaxhighlight>
You can temporarily toggle a device by writing its "Device" name back into <code>/proc/acpi/wakeup</code>
<syntaxhighlight lang="sh">
echo GPP0 | sudo tee /proc/acpi/wakeup
</syntaxhighlight>
After finding out which component is causing unwanted wakeups you can use the sysfs id to find out the "vendor" and "device" fields:
<syntaxhighlight lang="sh">
$ cat /sys/class/pci_bus/0000:04/device/0000:04:00.0/vendor
0x1987
$ cat /sys/class/pci_bus/0000:04/device/0000:04:00.0/device
0x5013
</syntaxhighlight>
And finally use those values in a <code>udev</code> rule:
<syntaxhighlight lang="nix">
services.udev.extraRules = ''
  ACTION=="add" SUBSYSTEM=="pci" ATTR{vendor}=="0x1987" ATTR{device}=="0x5013" ATTR{power/wakeup}="disabled"
'';
</syntaxhighlight>
== See also ==
* [[Laptop]]


== External resources ==
== External resources ==


* {{manual:nixos|sec=#sec-rebooting|chapter=Chapter 23. Rebooting and Shutting Down}}
* {{manual:nixos|sec=#sec-rebooting|chapter=Chapter 23. Rebooting and Shutting Down}}
[[Category:Configuration]]