context: my laptop recently started to fail staying in sleep mode, waking up instantly after sleep.
note: I've tackeled a quite similar subject in this gist.
I've agregated many posts from various places online to make a hopefully easy way to find the culprit and permanently disabling it, without side effect nor hacks.
- list your devices that have the authority to wake up your computer:
grep enable /proc/acpi/wakeupYou should get a somewhat short list like this:
FOO0 S4 *enabled pci:0000:00:05.0
FOO1 S4 *enabled pci:0000:00:05.1
BAR0 S3 *enabled pci:0000:00:07.0
BAZ0 S3 *enabled pci:0000:00:d1.0
...
PWRB S4 *enabled platform:PNP0C0C:00
If you glanced at my other gist I mentioned earlier, you should remember that the columns are Device, S-state (sleep state), Status and Sysfs node respectively.
The S-state refers to the different existing System Sleep States. Knowing that, you may think that the column indicates the mode the devices has authority to trigger a wake up. In my observation, it does jack-shit, but I may have made you click on kernel documentation so it's a win in my book!
More seriously, here comes the tidious part: you need to check each device, using their 4 characters "device code" (first column), to pin point which one makes your computer insomniac. If you got a large number of devices listed, you can check in batches (don't worry I'll show you at the end, but don't skip! read the following first to not mess things up).
Just know that the device PWRB if the computer power button, you can leave him alone since he can't be our culprit.
Now lets see how you can actually expose the mischievous bastard. Again, if you read my other gist you already know about /etc/tmpfiles.d/ (see systemd-tmpfiles).
Create a new conf file inside /etc/tmpfiles.d/, as always try to name it something easy to understand (mine was disable-device-preventing-sleep.conf), then put the following inside:
# Path Mode UID GID Age Argument
w+ /proc/acpi/wakeup - - - - <device code>
After that, I can run sudo systemd-tmpfiles --create to apply the new config. Changes take effect immediately, no need to reboot.
Try to put you computer to sleep: if it worked, congrats! you found the bastard; if not, it's between the remaining devices.
Before you try the next device in the list, you need to re-run the sudo systemd-tmpfiles --create to undo the change, no need to modify anything in the file yet.
Then, you can change the device code in the file, run the command again, and try to sleep one more time.
Did not work? run again to revert the change, then repeat the procedure for the next device, then the one after... until sleep works as intended.
When sleep is working OK: you're done! Congrats! Keep the file as is in case the change get reverted by something (prehaps an update), tho it will unlikely be needed.
I'll now go over how you can test devices by batch, and how to actually find the name of the culprit device.
As an example, lets say after running grep enable /proc/acpi/wakeup you got 8 devices in the list:
FOO0 S4 *enabled pci:0000:00:05.0
FOO1 S4 *enabled pci:0000:00:05.1
FOO2 S3 *enabled pci:0000:00:05.2
FOO3 S3 *enabled pci:0000:00:05.3
BAR0 S3 *enabled pci:0000:00:07.4
BAR1 S4 *enabled pci:0000:00:07.8
BAZ0 S4 *enabled pci:0000:00:d1.0
BAZ1 S3 *enabled pci:0000:00:d2.0
To try in batch you first need to understand that each line in the conf file act as an on-off switch. So to try the first 4 devices at once, the conf file should look like this:
# Path Mode UID GID Age Argument
w+ /proc/acpi/wakeup - - - - FOO0
w+ /proc/acpi/wakeup - - - - FOO1
w+ /proc/acpi/wakeup - - - - FOO2
w+ /proc/acpi/wakeup - - - - FOO3
Run sudo systemd-tmpfiles --create then try to sleep. If it worked, I know the culprit is between devices nb 1 and 4; conversely, I then know it's between nb 5 and 8.
Lets say it did not work. As explained before, re-run the command to revert the change. Then, knowing it's between BAR0, BAR1, BAZ0 and BAZ1, you can just put BAR0 and BAR1 in the conf before trying again.
This time it worked, I now know it's between BAR0 and BAR1! re-run to revert change, remove one of the two before trying again.
If it work, you're done! it was BAR0! If not, you're sure it's BAR1: revert one last time, change the file, run the command and you should be all set!
Finding the real name of the device is pretty straight forward. Run udevadm info --tree and scroll for three hours until you see the Sysfs node of the culprit (the last column mentioned earlier), and you should find its real name somewhere (usually next to ID_MODEL_FROM_DATABASE).
To find it more easily, pipe the output of the command to a text editor with search capability, like so:
# with kwrite
udevadm info --tree | kwrite -i
# with nano
udevadm info --tree | nano -Then search for the Sysfs node (e.g. 00:1c.0) and the ID_MODEL_FROM_DATABASE should be close. If you want, you can rename the conf file to reflect this new discovery.