Desktop Linux is getting more and more user friendly, but it’s still a bit picky about its friends. One Linux distribution that gets a lot of things right, however, is Pop!_OS from System76. But there are still things that doesn’t work as you expect them to out of the box. Properly putting your computer to sleep can be one of them, and Pop!_OS just won’t properly suspend my Dell XPS 12 9Q23. The laptop sleeps for about a second before it wakes up again.

When looking for a solution on the internet, I found a lot of blah, blah, blah, hardware, blah, blah, which is probably correct, but that suspending doesn’t work is still a bit of an annoying surprise. That said, like most things on Linux systems, you can get it to work if you just bang your head against the wall long enough.

To save you from the headaches I got when trying to get my Dell laptop to suspend properly, I put together this guide. I hope you find it useful.

It’s written for Pop!_OS 20.04 LTS, but might work on other versions of Pop!_OS, as well as other Ubuntu-based distributions and perhaps even Ubuntu itself.

What Keeps Pop!_OS from Suspending?

The short answer is that the problem is hardware related, and finding out exactly what hardware requires some detective work.

First, let’s see what hardware is currently allowed to wake up your computer from sleep:

sudo grep enabled /proc/acpi/wakeup

This will return a list, which might look something like this:

EHC1  S0  *enabled   pci:0000:00:1d.0
EHC2  S4  *enabled   pci:0000:00:1a.0
XHC   S0  *enabled   pci:0000:00:14.0
LID0  S3  *enabled   platform:PNP0C0D:00

To find out exactly what piece of hardware that’s the problem, disable one of the items in the list.

To disable the wake-up functionality for a specific piece of hardware, you need root privileges:

sudo su

And then you turn off the hardware’s ability to wake up your computer like this:

echo EHC2 > /proc/acpi/wakeup

To turn it on again, you simply run the same command again. Note that you’re not disabling the hardware, you’re only revoking its privilege to wake up your computer from sleep.

Now try to put your computer to sleep, and see what happens. If it doesn’t wake up again immediately, you’re (probably) golden. In my case, EHC2 was preventing my computer to go to sleep, so you might try that first as well. If you’re lucky, it’s a hole in one.

If you’re not so lucky, disable the next item in the list. Note that there might be multiple items that prevent your computer from suspending, so you might have to mix and match until you find the right combination of enabled and disabled hardware.

How to Make the new Settings Permanent?

Now that we’ve find the culprit, everything is OK, yes? No, it’s not. For some moronic reason, the settings you’ve just changed will revert back to its original value when you reboot your computer. To prevent this from happening, we need to create a service that disables hardware wake up for the offending hardware every time Pop!_OS boots.

Create the the file /etc/systemd/system/disable-hardware-wakeup.service with the following content:

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/disable-hardware-wakeup.sh

[Install]
WantedBy=multi-user.target

Then create the file /usr/local/disable-hardware-wakeup.sh with the following content:

#!/bin/sh
for device in EHC2
do
    if grep -q "$device.*enabled" /proc/acpi/wakeup
    then
        echo $device > /proc/acpi/wakeup
    fi
done

If it turns out you have multiple devices that prevents your computer from going to sleep, you can add more devices by changing the first line in the code: for device in EHC1 EHC2 XHC USB1 and so on.

Make the file with the shell script executable:

sudo chmod +x /usr/local/disable-hardware-wakeup.sh

Finally, enable the service:

sudo systemctl enable disable-hardware-wakeup.service

And that’s it. Pop!_OS should now be able to properly suspend your computer even after you reboot.