-
-
Save javanna/38d019a373085e1ba0c784597bc7ec73 to your computer and use it in GitHub Desktop.
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] | |
``` |
I confirm the technique is working as-is on my X1 Yoga 3G on Fedora 28. Thanks a lot!
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.
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?
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!
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
andcpio
. - 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?
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
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.
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
@bprfh I had the same problem just using my laptop, found the solution was uninstalling thermald, this is for ubuntu 18.10
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.
@alexswerner : I had some success with using s0/s2int suspend to re-enable the wacom.
- Wake up from s3.
- suspend it again, but use the following :
echo freeze > /sys/power/state
- 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.
BIOS update 1.34 now available on Lenovo web site... now the legacy sleep available in bios
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.
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!