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.dst 
    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. 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
  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.