So recently I noticed that my new Lenovo did not properly enter Hibernation after staying in Suspend for some time.

Looking at the error logs I saw the following.

Dez 09 13:28:49 arthur kernel: xhci_hcd 0000:00:14.0: PM: failed to freeze async: error -16
Dez 09 13:28:49 arthur kernel: xhci_hcd 0000:00:14.0: PM: dpm_run_callback(): pci_pm_freeze+0x0/0xf0 returns -16
Dez 09 13:28:49 arthur kernel: xhci_hcd 0000:00:14.0: PM: pci_pm_freeze(): hcd_pci_suspend+0x0/0x20 returns -16

So what is happening during a suspend-then-hibernate cycle.

  • System enters suspend
  • System wakes from suspend then enters Hibernate

The problem apparently lies with the second step. When the system starts up again the USB subsystem is started up as well and then the systems tries to hibernate before the USB stack is active so it errors out. To work around this issue I added the following small script to my systemd-sleep configuration.

/lib/systemd/systemd-sleep/hibernate

#!/bin/sh
if [ "$SYSTEMD_SLEEP_ACTION" = "hibernate" ] && [ "$1" = "pre" ]; then
  sleep 5;
fi

It more or less adds a sleep between the suspend and the hibernate process giving the USB stack enough time to settle.

A few months ago I bought a used Lenovo T470S and installed Ubuntu 22.04 on it. While the default fprintd daemon did not support the sensor python-validity provided support for it. Following the install instructions resulted in a perfectly working sensor.

With the update to 22.10 the sensor stopped working and it took me some time to find out the root cause and the fix for it. Apparently 22.10 included and upated systemd version which included updated udev hw rules for fingerprint sensors. The fingerprint sensor of my Lenovo was included as well albeit as unsupported. The default configuration for the fingerprint readers set the persist of the USB device to "0". As a result the sensor completely disconnected during suspend and got reconnected instead of reset after a resume.

The Fix

We have to override the settings of the systemd hw.db.

  1. Get the vendor and product ID of your reader by running lsusb

    Look for your validity sensor and note down the Vendor and Product ID.

    ...
    Bus 001 Device 006: ID 138a:0097 Validity Sensors, Inc.
    ...
    

  2. Setup an override file.

    Create a file in /etc/udev/hwdb.d/ and call it 61-autosuspend-fingerprint-reader.hwdb.

    Adapt the USBID based on the device information you looked up before.

    usb:v138Ap0097*
     ID_AUTOSUSPEND=1
     ID_PERSIST=1
    

  3. Finally update the hw database by running sudo systemd-hwdb update

After a reboot your fingerprint reader should survive a suspend/resume cycle again.

When switching to the latest linux kernel I noticed that my T470S sometimes had issues to suspend if a Bluetooth device was connected. Looking through bugzilla I found a bug that referred to this issue which was apparently fixed already. While bug itself was not really helpful it also provided a link to small script which disconnected all Bluetooth devices during the suspend process. This script indeed fixed the issue I was seeing but had one small issue. Since it was a simple shell script bluetooth devices got disabled one after another, which more or less meant the more devices you had the longer it would take.

Just for kicks I tried to speed this up and you can find my script here. I switched to python and parallelized the device disconnects.

To install it just copy it to /usr/lib/systemd/system-sleep/, make it executable and make sure that you have installed the dependencies python-dbus and python3-gi.