Power Management: Difference between revisions

Onny (talk | contribs)
Restructuring, add section on hdd power modes
Sandro (talk | contribs)
 
(13 intermediate revisions by 6 users not shown)
Line 3: Line 3:
== Configuration ==
== Configuration ==


=== Hard drive power management ===
=== 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">
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 =  
services.udev.extraRules =  
Line 30: Line 30:


<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
  systemd.services.your-service-name = {  
systemd.services.your-service-name = {  
    description = "Service description here";
  description = "Service description here";
    wantedBy = [ "post-resume.target" ];
  wantedBy = [ "post-resume.target" ];
    after = [ "post-resume.target" ];
  after = [ "post-resume.target" ];
    script = ''
  script = ''
     echo "This should show up in the journal after resuming."
     echo "This should show up in the journal after resuming."
    '';
  '';
    serviceConfig.Type = "oneshot";
  serviceConfig.Type = "oneshot";
  };
};
</syntaxhighlight>
</syntaxhighlight>


=== Hibernation ===
=== 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. An example configuration could look like this:<syntaxhighlight lang="nix">
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 = [
swapDevices = [
   {
   {
     device = "/dev/hda7";
     device = "/dev/VG/SWAP";
   }
   }
];
];
boot.resumeDevice = "/dev/hda7";
</syntaxhighlight>Please note that encrypted swap devices or swap files are not yet supported for hibernation.


Test and use hibernation with following command:<syntaxhighlight lang="nix">
boot.resumeDevice = "/dev/dm-7";
</syntaxhighlight>Derived from a system with the following output from <code>swapon -s</code> :<syntaxhighlight lang="text">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
systemctl hibernate
</syntaxhighlight>
</syntaxhighlight>
Line 62: Line 71:
systemd.sleep.extraConfig = ''
systemd.sleep.extraConfig = ''
   HibernateDelaySec=1h
   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>
</syntaxhighlight>
Line 67: Line 86:
== Troubleshooting ==
== Troubleshooting ==


==== System immediately wakes up from suspend ====
=== System immediately wakes up from suspend ===


Particularly in some Gigabyte motherboards with NVMe drives, the system may immediately wake up from being suspended.
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:
This can be worked around by disabling the wakeup triggers for the offending components:


===== Solution 1: Disabling wakeup triggers for all PCIe devices =====
==== 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.
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.
Line 82: Line 101:
</syntaxhighlight>
</syntaxhighlight>


===== Solution 2: Disable a common NVMe interface =====
==== Solution 2: Disable a common NVMe interface ====


Specifically on Gigabyte motherboards you can try targetting only the NVMe ports.
Specifically on Gigabyte motherboards you can try targetting only the NVMe ports.
Line 92: Line 111:
</syntaxhighlight>
</syntaxhighlight>


===== Solution 3: Disable a single device's wakeup triggers =====
==== 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.
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:
First, list all components and their current wakeup status:
<syntaxhighlight lang="sh">
<syntaxhighlight lang="shell-session">
$ cat /proc/acpi/wakeup
$ cat /proc/acpi/wakeup
Device S-state   Status  Sysfs node
Device S-state   Status  Sysfs node
Line 117: Line 136:
After finding out which component is causing unwanted wakeups you can use the sysfs id to find out the "vendor" and "device" fields:
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">
<syntaxhighlight lang="console">
$ cat /sys/class/pci_bus/0000:04/device/0000:04:00.0/vendor
$ cat /sys/class/pci_bus/0000:04/device/0000:04:00.0/vendor
0x1987
0x1987
Line 131: Line 150:
'';
'';
</syntaxhighlight>
</syntaxhighlight>
=== Suspend blocked by <code>pre-sleep.service</code> ===
Sometimes, the system appears to suspend (Wi-Fi turns off, screen locks), but the hardware does not actually suspend, and all subsequent <code>systemctl suspend</code> or <code>systemctl reboot</code> commands are met with:
<syntaxhighlight lang="console">
# systemctl suspend
Call to Suspend failed: Action suspend already in progress, refusing requested suspend operation.
# systemctl reboot
Call to Reboot failed: Action suspend already in progress, refusing requested reboot operation.
</syntaxhighlight>
If directly telling the kernel to suspend as root works:
<syntaxhighlight lang="console">
# echo mem > /sys/power/state
</syntaxhighlight>
Then a long-running <code>pre-sleep.service</code> might be hanging the sleep. This can be verified with <code>systemctl list-jobs</code>:
<syntaxhighlight lang="console">
# systemctl list-jobs
JOB  UNIT                    TYPE  STATE 
12144 suspend.target          start waiting
12149 pre-sleep.service      start running
12145 systemd-suspend.service start waiting
12268 post-resume.target      start waiting
12148 sleep.target            start waiting
12269 post-resume.service    start waiting
</syntaxhighlight>
Here, the <code>pre-sleep.service</code> is blocking and halting suspend. To see why, we can use <code>systemctl cat pre-sleep.service</code>:
<syntaxhighlight lang="systemd">
# systemctl cat pre-sleep.service
# /etc/systemd/system/pre-sleep.service
[Unit]
Before=sleep.target
Description=Pre-Sleep Actions
[Service]
# <... Omitted Environment directives PATH, LOCALE_ARCHIVE, TZDIR ...>
ExecStart=/nix/store/yzf7cpiqzq49san2frijxsh160zjy6fp-unit-script-pre-sleep-start/bin/pre-sleep-start
Type=oneshot
[Install]
WantedBy=sleep.target
</syntaxhighlight>
In this case, the <code>pre-sleep-start</code> script referenced by <code>ExecStart</code> contained directives installed by the [[Displaylink]] package, that contained a flush operation which hung the suspend action. Starting <code>dlm.service</code> or running <code>sudo DisplayLinkManager</code> unblocks the script and made suspend work normally.
==== Cancelling an existing suspend action ====
An existing suspend operation that is hung may be interrupted using <code>'''systemctl cancel'''</code> in case reboots or internet access is needed.


== See also ==
== See also ==
Line 138: Line 209:


* {{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]]