Sweet Dreams, My Dear Framework
Setting up sleep on my Framework 13 was a bit annoying but, once set, it worked perfectly. However, the same solution didn’t work on my Framework 16. While my installation is far from standard, the hibernation steps are quite straighforward:
- Setup swap partition RESUME variable in grub loader
- Adjust
sleep.conf
- Disable wakeup for troublesome components so your laptop doesn’t wake immediately
And it was the step 3 that presented the problem - the darn thing kept waking up.
Since I sorted this out with Framework 13, I figured I can do the same for Framework 16. Even better, I found a forum post that actually told me which components need more of a sleep.
echo disabled > /sys/devices/pci0000:00/0000:00:08.1/0000:c1:00.3/usb1/1-4/1-4.3/power/wakeup
echo disabled > /sys/devices/platform/AMDI0010:03/i2c-1/i2c-PIXA3854:00/power/wakeup
echo disabled >/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4b/PNP0C09:00/PNP0C0D:00/power/wakeup
Yes, it was different than my approach of disabling them in udev rules, but the same idea overall. And it even has the same suspects as for Framework 13, most notably Touchpad (i2c_hid_acpi
), lid switch (button
), and USB xHCI (xhci_hcd
). Full of hope, I tried that and my computer still woke up.
My next step was to check the file (yes, I blindly copy/pasted it) and problem was obvious. My devices were at a different path. So I adjusted, tried it again, finished up a blog post, and called it a day. I mean, everything was working perfectly. Or so I thought.
After a few days, I placed computer into hibernate only for the darn thing to wake up on me. What the heck? I though I solved that issue. So I checked and noticed my devices were at slightly different location. Hm, maybe in all the fuss around finishing up blog post I accidentally made an error. So I addjusted paths and, with everything working correctly, called it a day.
But, guess what, in a few days I got the same issue again. And this time I was certain I had it done correctly. However, device paths were changed again. With so many independent USB devices, plug-and-play was moving stuff around every time system was rebooted.
So, I needed to script my /usr/lib/systemd/system-sleep/framework
a bit smarter. At the end I ended up with this:
#!/bin/sh
case $1 in
pre)
for DRIVER_LINK in $(find /sys/devices/ -name "driver" -print); do
DEVICE_PATH=$(dirname $DRIVER_LINK)
if [ ! -f "$DEVICE_PATH/power/wakeup" ]; then continue; fi
DRIVER=$( basename $(readlink -f $DRIVER_LINK) )
if [ "$DRIVER" = "button" ] || [ "$DRIVER" = "i2c_hid_acpi" ] || [ "$DRIVER" = "xhci_hcd" ]; then
echo disabled > $DEVICE_PATH/power/wakeup
fi
done
;;
esac
This will search for naughty devices every time hibernate is called upon and turn off wakeup. If PnP moves them, no worries, script will find them again.
And yes, the same script works for both Framework 13 and 16.