In November, I got a new laptop, a Dell XPS 15 (also known as model L501X).  It’s a pretty nice laptop, with a very crisp display and some serious horsepower.

I first installed Ubuntu 10.10 on it, and almost everything worked out of the box.  But it would not suspend (save to RAM) or hibernate (save to disk) properly.  I quickly found a solution to this problem on the internet.  It had to do with two drivers that need to be unloaded before suspending/hibernating: the USB3 driver and the Intel “Centrino Advanced-N 6200” wireless a/b/g/n driver.

The solution is to create two files, shown below, that will unload the driver before suspending and reload the driver when it starts back up.

In /etc/pm/config.d/custom-L501X:

# see http://ubuntuforums.org/showthread.php?t=1634301
SUSPEND_MODULES="xhci-hcd iwlagn"

In /etc/pm/sleep.d/20_custom-L501X:

#!/bin/sh
# see http://ubuntuforums.org/showthread.php?t=1634301
case "${1}" in
  hibernate|suspend)
    echo -n "0000:04:00.0" | tee /sys/bus/pci/drivers/iwlagn/unbind
    echo -n "0000:05:00.0" | tee /sys/bus/pci/drivers/xhci_hcd/unbind
    ;;
  resume|thaw)
    echo -n "0000:04:00.0" | tee /sys/bus/pci/drivers/iwlagn/bind
    echo -n "0000:05:00.0" | tee /sys/bus/pci/drivers/xhci_hcd/bind
    ;;
esac

A little while later, I “upgraded” to Ubuntu 11.04, but then suspend/hibernate stopped working. Argh!! I tried a lot of work-arounds, but nothing worked.

What’s particularly frustrating about this sort of problem is that you end up finding a lot of posts on forums where some guy posts a very terse statement like “I put ‘foo’ in my /etc/bar and it worked”. So you end up stabbing a lot of configuration settings into a lot of files without actually understanding how any of it works.

From what I can piece together, it looks like the Linux suspend/hibernate process has been handled by several different subsystems over time. These days, it is handled by the “pm-utils” package and the kernel. PM utils figures out what to do, where to save the disk image (your swap partition), and then it tells the kernel to do the work. There are a lot of other packages that are not used any more: uswsusp, s2disk/s2ram, and others (please correct me if I am wrong).

I never really liked what I saw in Ubuntu 11.04, and so I tried a completely new distro, Linux Mint Debian Edition. This distro combines the freshness of the Debian “testing” software repository with the nice desktop integration of Linux Mint. Admittedly, it may be a little too bleeding edge for some, it’s certainly not for everybody. But so far, I like it.

When I first installed LMDE, suspend and hibernate both worked. But then I updated to a newer kernel and it stopped working. So, just like with Ubuntu, something in the more recent kernel changed and that broke suspend/hibernate.

I tried a few experiments. If I left the two custom config files alone, the system would hang while trying to save to RAM or to disk. If I totally removed my custom config files, I could suspend (to RAM), and I could hibernate (to disk), but I could not wake up from hibernating (called “thawing”). I determined through lots of experiments that the USB3 driver no longer needed to be unloaded, but the wireless driver does need to be unloaded.

So with the newer 2.6.39 kernel, the config files change to this, with the xhci_hcd lines removed.

In /etc/pm/config.d/custom-L501X:

SUSPEND_MODULES="iwlagn"

In /etc/pm/sleep.d/20_custom-L501X:

#!/bin/sh
case "${1}" in
  hibernate|suspend)
    echo -n "0000:04:00.0" | tee /sys/bus/pci/drivers/iwlagn/unbind
    ;;
  resume|thaw)
    echo -n "0000:04:00.0" | tee /sys/bus/pci/drivers/iwlagn/bind
    ;;
esac

At the risk of just saying “I put ‘foo’ in /etc/bar and it worked”, that’s what I did… and it did.


If you have insights on how the overall suspend/hibernate process works, please share. There seems to be a lot of discussion online about particular configuration files and options, but I could not find much info about the overall architecture and the roadmap.