Skip to content

Instantly share code, notes, and snippets.

@javanna
Created July 15, 2018 19:02
Show Gist options
  • Star 15 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save javanna/38d019a373085e1ba0c784597bc7ec73 to your computer and use it in GitHub Desktop.
Save javanna/38d019a373085e1ba0c784597bc7ec73 to your computer and use it in GitHub Desktop.
S3 deep sleep for Lenovo yoga X1 3rd Generation on Fedora 28
This is a step-by-step guide on how make sleep mode work with a Lenovo Yoga X1 3rd generation running Fedora 28 (UEFI based system).
Kernel version: 4.17.4-200.fc28.x86_64
Credits: most of this guide comes from `https://delta-xi.net/#056`. The patch I used is a little different though, taken from http://kernel.dk/acpi.patch
(found through https://bbs.archlinux.org/viewtopic.php?pid=1794150#p1794150), and some of the steps slightly differ as well as mine is a UEFI based system.
1. Reboot, enter BIOS/UEFI. Go to Config - Thunderbolt (TM) 3 - set Thunderbolt BIOS Assist Mode to Enabled. Set also Security - Secure Boot to Disabled.
2. Install iasl (Intel's compiler/decompiler for ACPI machine language) and cpio: `sudo yum install acpica-tools cpio`
3. Get a dump of ACPI DSDT table: `cat /sys/firmware/acpi/tables/DSDT > dsdt.aml`
4. Decompile the dump, which will generate a `.dsl` source based on the `.aml` ACPI machine language dump: `iasl -d dsdt.aml`
5. Download the [patch](http://kernel.dk/acpi.patch) and apply it against `dsdt.dsl`: `patch --verbose < acpi.patch`
Hunk 2 failed for me, I manually looked for the following in `dsdt.dsl`:
```
Name (SS1, 0x00)
Name (SS2, 0x00)
Name (SS3, One)
One
Name (SS4, One)
One
```
and replaced it with the following (removing the two "One" lines):
```
Name (SS1, 0x00)
Name (SS2, 0x00)
Name (SS3, One)
Name (SS4, One)
```
6. Recompile your patched version of the .dsl source: `iasl -ve -tc dsdt.dsl`
7. Create a CPIO archive with the correct structure, which GRUB can load on boot. We name the final image `acpi_override` and copy it into `/boot/`:
```
mkdir -p kernel/firmware/acpi
cp dsdt.aml kernel/firmware/acpi
find kernel | cpio -H newc --create > acpi_override
cp acpi_override /boot
```
8. GRUB needs to boot the kernel with a parameter setting the deep sleep state as default. Edit `/etc/default/grub` and add the following:
```
GRUB_CMDLINE_LINUX_DEFAULT="mem_sleep_default=deep"
```
9. Regenerate the GRUB configuration: `grub2-mkconfig -o /boot/efi/EFI/fedora/grub.cfg`
10. Tell GRUB to load the new DSDT table on boot in its configuration file located in `/boot/efi/EFI/fedora/grub.cfg`. Find the relevant GRUB menu entry
and add the new image (`/acpi_override`) to the `initrdefi` line:
```
initrdefi /acpi_override /initramfs-4.17.4-200.fc28.x86_64.img
```
Note: This step needs to be repeated every time the kernel is upgraded and the GRUB configuration is rewritten. Ideally this step would not be needed as
we could instead add `GRUB_EARLY_INITRD_LINUX_CUSTOM="/acpi_override"` to `/etc/default/grub` as part of step 8 which would survive upgrades.
But such line is currently ignored by fedora, see https://bugzilla.redhat.com/show_bug.cgi?id=1600414.
10. Reboot and enjoy having a laptop running Linux again... close the lid and the battery does not get drained in a few hours, also the battery no longer stays warm in sleep mode.
To verify that things are working:
```
dmesg | grep ACPI | grep supports
#[ 0.195933] ACPI: (supports S0 S3 S4 S5)
cat /sys/power/mem_sleep
#s2idle [deep]
```
@lvanderree
Copy link

lvanderree commented Aug 27, 2018

Thanks!
Another X1 Yoga 3g user, running Fedora 28

I made one addition, I added /boot for the override in grub, but beside that didn't had any issues!

@sebastien
Copy link

I confirm the technique is working as-is on my X1 Yoga 3G on Fedora 28. Thanks a lot!

@aernesto
Copy link

aernesto commented Sep 6, 2018

Hi. Thank you so much!
I'll add my own difficulty in the process, in case it helps someone. I wrongly pasted this line in my /boot/efi/EFI/fedora/grub.cfg file. Since my version was initramfs-4.17.19-200.fc28.x86_64.img,
I couldn't boot after this. Luckily, I could boot from a previous entry in GRUB and correct my mistake.

@taaem
Copy link

taaem commented Oct 23, 2018

Thanks for the guide! Unfortunally my touch screen fails to resume from suspend, everything else works fine but the touch screen is broken until I reboot. Does any one here has had this issue and maybe solved it?

@mglevy
Copy link

mglevy commented Oct 25, 2018

Hello! I'm doing this on Mint and had hunk 1 fail and also had to manually install iasl in step 6 as the one with my distribution was not up to date. I don't have grub2-mkconfig on my computer so I used grub-mkconfig instead. Could that be an issue? I think mint maybe stores its grub elsewhere: /boot/grub/grub.cfg was able to insert itself in correctly when I use the command you suggest to augment step 8. Here's what it says:

    linux   /boot/vmlinuz-4.18.6-041806-generic root=UUID=b56057a8-2b3b-4ea5-86f5-ca353f2c9ee6 ro  mem_sleep_default=deep
    initrd  /boot/acpi_override /boot/initrd.img-4.18.6-041806-generic

When i edit /boot/efi/EFI/ubuntu/grub.cfg the file is mostly empty it just has:


search.fs_uuid b56057a8-2b3b-4ea5-86f5-ca353f2c9ee6 root
set prefix=($root)'/boot/grub'
configfile $prefix/grub.cfg

I added the line initrd /acpi_override just in case, but when i reboot I get no deep suspend. Any ideas? Did any of you do this on a computer you could dual boot into windows? Could that be the problem? Thank you for your help and attention! Also, good luck taaem!

@naftulikay
Copy link

I've put all of my work in trying to accomplish this into a repository here.

Here's what I was able/not able to do:

  • Activate Thunderbolt BIOS Assist Mode
  • Install iasl and cpio.
  • Dump ACPI DSDT table.
  • Decompile to DSL.
  • Download and apply patch.
  • Recompile after patching.
  • Create CPIO archive.
  • Add mem_sleep_default=deep kernel parameter on boot.

Everything after this is GRUB-specific and I'm using rEFInd instead, so I haven't got there yet.

I can't seem to compile following the instructions. The full output is available here, but it issues a massive amount of compilation errors which end like this:

dsdt.dsl    426:         External (\_GPE.TBNF, 0x08, 0x00)
Error    6126 -                                  ^ syntax error, unexpected PARSEOP_INTEGER

dsdt.dsl    427:         External (\ADBG, 0x08, 0x01)
Error    6126 -                             ^ syntax error, unexpected PARSEOP_INTEGER

dsdt.dsl    428:         External (\_SB.GGIV, 0x08, 0x01)
Error    6126 -                                 ^ syntax error, unexpected PARSEOP_INTEGER

dsdt.dsl    429: 
Error    6126 - syntax error, unexpected PARSEOP_INTEGER and premature End-Of-File


Intel ACPI Component Architecture
ASL+ Optimizing Compiler version 20160108-64
Copyright (c) 2000 - 2016 Intel Corporation


Maximum error count (200) exceeded

Maximum error count (200) exceeded
ASL Input:     dsdt.dsl - 429 lines, 1122568 bytes, 1 keywords
Hex Dump:      dsdt.hex - 203 bytes

Compilation complete. 201 Errors, 0 Warnings, 0 Remarks, 0 Optimizations

If you visit my repository, I have baked most of the steps into commits so you can walk through the steps one by one, commit by commit.

So I can't get it to compile. Any ideas here?

@stumyp
Copy link

stumyp commented Nov 17, 2018

You can avoid prepending /boot/acpi_override in initrd call every time by including that file into main initrd file

add this script to /etc/initramfs-tools/hooks/

#!/bin/sh

ACPI_OVERRIDE="/boot/acpi_override"

  PREREQ=""

  prereqs()
  {
          echo "$PREREQ"
  }

  case $1 in
  # get pre-requisites
  prereqs)
          prereqs
          exit 0
          ;;
  esac

. /usr/share/initramfs-tools/hook-functions
prepend_earlyinitramfs "${ACPI_OVERRIDE}"

and then run

/usr/sbin/update-initramfs -k all -c

@naftulikay
Copy link

naftulikay commented Nov 29, 2018

After digging in the forum thread, I saw that unless you're running Gentoo or Arch, you need to manually compile iasl: you need a REALLY recent version which you can obtain here. You're gonna need things like build-essential (on Ubuntu), m4, bison, flex, and a few other things, but then just make to build it from source. You'll then have generated/unix/iasl as a binary. Use that to recompile things.

I also had to USB boot into Ubuntu 18.04 to get more recent stuff and I saw that my patch only failed 1/3 hunks rather than 2/3 as before.

I made sure to upgrade to the latest firmware. You can download the ISO from Lenovo, but you need to use geteltorito from genisoimage to generate the actual ISO that you need to burn to a USB partition.

After all this hullabaloo it boots and I see that it supports S0, S3, S4, and S5, and /sys/power/mem_sleep is s2idle [deep].

Thanks everybody! I'm going to test it out now to make sure it really goes the fsck to sleep.

EDIT: It works! See my repository for a full walkthrough for Ubuntu 16.04 using the latest HWE kernel, 4.15.

@bprfh
Copy link

bprfh commented Dec 1, 2018

As soon as I load the custom initdr, my lenovo yoga x1 gen 3 stops the CPU clock at 400Mhz, anyone else experiencing this Problem?
Bios is 1.27

@YOUR-WORST-TACO
Copy link

@bprfh I had the same problem just using my laptop, found the solution was uninstalling thermald, this is for ubuntu 18.10

@yunusbahari
Copy link

@bprfh did your fan works?, it probably because of throttling, you can use this article if it's indeed the problem, the workaround is using thinkfan and manual tweak from lm-sensors

@alexswerner
Copy link

Thanks! This works for me in general, but after resume the xhci USB host controller is unresponsive. This disables the pen input. Do you also see this? I am running kernel 4.20.0-rc4 and BIOS version 1.27 on ubuntu 18.04.

@jmbjorndalen
Copy link

@alexswerner : I had some success with using s0/s2int suspend to re-enable the wacom.

  1. Wake up from s3.
  2. suspend it again, but use the following : echo freeze > /sys/power/state
  3. wake up from s2int

Then again, I now woke it up after > 24H of sleep in S3 (< 10% battery consumed), and the wacom worked without having to use the s2int trick.

@pashok2398
Copy link

BIOS update 1.34 now available on Lenovo web site... now the legacy sleep available in bios

@javanna
Copy link
Author

javanna commented Aug 27, 2019

If only the legacy sleep worked... I've had a lot of problems with it so far. Standby is unreliable, I closed the lid and the laptop drains the battery in a couple of hours. When I reopen it it loses the timezone and goes to the future. And even trying to use the previous acpi_override trick, nothing changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment