-
-
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] | |
``` |
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.
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:
iasl
andcpio
.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:
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?