Enabling deep sleep on notebooks
Deep sleep (suspend to RAM, also called S3 state) is factory disabled on some modern
notebooks, partly due to
modern standby enforced by Intel and Microsoft. As a
result, suspension is non-functional on some notebooks running GNU/Linux,
especially with AMD processors.
Supported sleep states
You can see what sleep states your machine supports by reading
/sys/power/mem_sleep
. On my machine, only
s2idle
was reported, which is the most basic kind of sleep state implemented on a purely software level.
$ cat /sys/power/mem_sleep
[s2idle]
Patching ACPI tables
Fortunately, the Linux kernel has the ability to load patched ACPI tables during the boot process.
- Dump the DSDT table.
$ cat /sys/firmware/acpi/tables/DSDT > dsdt.aml
-
Decompile the dumped table to obtain
dsdt.dsl
.
$ iasl -d dsdt.aml
You need to install the acpica
package for this step.
- Open
dsdt.dsl
with a text editor. Find a line which looks like:
DefinitionBlock ("", "DSDT", 2, "_ASUS_", "Notebook", 0x01072009)
and increment the version number by one:
DefinitionBlock ("", "DSDT", 2, "_ASUS_", "Notebook", 0x01072010)
-
Search for the string "
S3
" and find a block which looks like
Name (XS3, Package (0x04)
{
0x03,
Zero,
Zero,
Zero
})
and change it to
Name (_S3, Package (0x04)
{
0x03,
Zero,
Zero,
Zero
})
if needed. Additionally, if there are any conditionals nested outside the above block, delete them so as to report affirmative S3 support even if the flag checks fail.
-
Recompile the file
$ iasl dsdt.dsl
This will overwrite the old .aml
file.
-
Now we have to create a CPIO archive with the correct directory tree, which your boot loader can load on boot.
$ mkdir -p kernel/firmware/acpi
$ cp dsdt.aml kernel/firmware/acpi/.
$ find kernel | cpio -H newc --create > dsdt-patch.img
- Do one of the following steps, whichever you prefer:
- Tell your boot loader to load the
dsdt-patch.img
file at boot. I use systemd-boot
so I had to do the following:
$ cp dsdt-patch.img /boot/.
and add the line initrd /dsdt-patch.img
to the config file /boot/loader/entries/*.conf
right after
initrd /amd-ucode.img
- Alternatively, you can use mkinitcpio's
acpi_override
hook. $ mkdir /etc/initcpio/acpi_override
$ cp dsdt.aml /etc/initcpio/acpi_override/
Add acpi_override
to the HOOKS
array in
/etc/mkinitcpio.conf
:HOOKS=(... acpi_override)
Finally, regenerate the initramfs:$ mkinitcpio -P
-
Your default setting of sleep state may still be
s2idle
. To fix this, it is recommended to add the kernel parameter
mem_sleep_default=deep
-
Reboot and you should see
$ cat /sys/power/mem_sleep
s2idle [deep]
meaning deep sleep is now enabled.
Keep in mind that after each BIOS update you will need to repeat these steps!
References:
- https://wiki.archlinux.org/title/DSDT
- https://www.kernel.org/doc/Documentation/acpi/initrd_table_override.txt