Getting suspend in Linux working on a MacBook Pro

A lot of my distro hopping as of late has been due to my inability to get my
daily driver, a MacBook Pro 12,1 (2015) to suspend correctly.

Each distro resulted in the same. Close the lid, the Apple logo goes dark and
within a few seconds, it lights back up.

If I am in a hurry and didn’t realize it, the system would hang out in my laptop
bag and run super hot until the battery runs out.

BUT NO MORE!

As of my recent switch to Debian Stretch (Testing, and currently on a full
freeze), I have been able to get suspend working properly!

That’s not to say that Debian worked better out of the box than the four other
distributions I have used recently. I do feel that the shear volume of
documentation that’s out there for Debian is what finally allowed me to find the
appropriate information to concoct a fix.

So what was the culprit? Turns out it’s something funky with USB 3.0 ports that
end up waking up the machine immediately after it goes to sleep. I was able to
disable the USB event and all started to work as expected.

To check and see if you have USB 3.0 on your system, run lsusb and look for a
line like this:

Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub

If you’re on USB 3.0, you’ll see a 3.0 in there. Otherwise, you’ll see whatever
USB version your system has.

You can follow up that command with cat /proc/acpi/wakeup which will list the
devices with wakeup events and whether or not they are enabled.

On my system I had a few things enabled. The device for the USB port(s) is XHC1.
You can try disabling it by running the following:

echo XHC1 > /proc/acpi/wakeup

Note, I had read that the lid can play some tricks as well. If you want to
disable the lid as well, you can run this:

echo LID0 > /proc/acpi/wakeup

If you disable the lid, you’ll need to hit the power button to resume.

At this point, everything should be working as expected. Only issue is that the
commands we just ran aren’t persistent and will need to be run after every boot.
The quick fix is to dump those commands into /etc/rc.local. It should look
something like this:

#!/bin/sh -e
echo LID0 > /proc/acpi/wakeup
echo XHC1 > /proc/acpi/wakeup
exit 0

You could also go through the trouble of setting up a systemd service, if you’re
into that 😉

Josh Sherman - The Man, The Myth, The Avatar

About Josh

Husband. Father. Pug dad. Musician. Founder of Holiday API, Head of Engineering and Emoji Specialist at Mailshake, and author of the best damn Lorem Ipsum Library for PHP.


If you found this article helpful, please consider buying me a coffee.