Ayan Nath

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.
  1. Dump the DSDT table.
    $ cat /sys/firmware/acpi/tables/DSDT > dsdt.aml
    
  2. Decompile the dumped table to obtain dsdt.dsl.
    $ iasl -d dsdt.aml 
    You need to install the acpica package for this step.

  3. 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)
  4. 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.
  5. Recompile the file
    $ iasl dsdt.dsl 
    This will overwrite the old .aml file.
  6. 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
    
  7. Do one of the following steps, whichever you prefer:
  8. 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
  9. 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:

  1. https://wiki.archlinux.org/title/DSDT
  2. https://www.kernel.org/doc/Documentation/acpi/initrd_table_override.txt