Avoiding spurious wakeups with my ThinkPad X1 Yoga

Last year I bought myself a ThinkPad X1 Yoga to use as my personal laptop - I've been pretty happy with it so far, but there's one problem I've run into that I've noticed a lot more lately - the laptop will sometimes wake up while the lid is closed, go back to sleep, and then repeat that whole process every few minutes. This can't be good for the hardware, so I dug into this issue and wanted to share my findings with anyone who's having the same problem running Linux on this laptop!

tl;dr - disable Thunderbolt wake events by running echo RP13 > /proc/acpi/wakeup - but only if the laptop is plugged in!

A bit of searching around the internet pointed me at /proc/acpi/wakeup, which lists and controls various ACPI devices that can trigger a wake-up, which ACPI state they work with, and whether or not they're currently allowed to wake the device up. I took a quick look to see which devices were allowed to trigger a wake:

$ grep enabled /proc/acpi/wakeup
GLAN    S4  *enabled   pci:0000:00:1f.6
XHC     S3  *enabled   pci:0000:00:14.0
RP09    S4  *enabled   pci:0000:00:1d.0
RP13    S4  *enabled   pci:0000:00:1d.4
PXSX    S4  *enabled   pci:0000:05:00.0
SLPB    S3  *enabled   platform:PNP0C0E:00
LID     S4  *enabled   platform:PNP0C0D:00

I'm pretty sure I want LID to bring my laptop out of sleep, and I don't know what SLPB is. I suspected that the culprit causing the wake-ups was one of the various PCI devices here, so I disabled all of those by running echo $DEVICE > /proc/acpi/wakeup as root for each of them (except for PXSX - for some reason writing that to /proc/acpi/wakeup didn't flip its state. I think it might have something to do with the fact that the writer code only accepts four characters as a command, and that it stops lopping after it finds the first match - upon further inspection I found multiple PXSX devices). I closed my laptop, and it didn't wake until I opened it back up again, huzzah!

I wasn't 100% satisified with this, though - I wanted to know if this showed up again in the future, and I wanted to know which device was causing the wake-ups. I figured that looking for WiFi connection events in my router's logs would serve as a pretty decent proxy for a wake-up event, so I set up grok exporter to look for those in my logs and export those as a counter named pavo_wifi_connections_total ("pavo" being my laptop's hostname). Once I had that metric in Prometheus, I wrote a simple alert rule to ping me if the laptop connected more than six times in the last hour: increase(pavo_wifi_connections_total[1h]) > 6

At this point, I conducted a few experiments by disabling/reenabling devices selectively. After some trial and error, I discovered that I only need to disable the RP13 device - whatever that is - to prevent the false wake-ups! I was curious, so I combed through lshw's output and discovered that RP13 corresponds to the laptop's Thunderbolt bus. So then I just wrote a little systemd service to disable that device upon every boot and called it day!

I'm not sure why that was triggering the wake-ups - maybe there's some weird electrical interference going on, or maybe the touchscreen goes through that bus somehow and there was some gunk on the screen generating events or something. I'm not going to dig into that any more, but if you know the answer or have an idea I'd love to hear about it!

Published on 2022-01-01