core-agent-linux/qubes-rpc/prepare-suspend
Marek Marczykowski-Górecki ee122eefef
Detach all drivers from PCI devices before suspend
The most common thing to fix S3 sleep is to unload PCI devices drivers
before suspend. Instead of having every user figuring out what drivers
needs to be blacklisted, detach all drivers from actual PCI devices.
Exclude qemu emulated devices.

Fixes QubesOS/qubes-issues#3486
2018-01-22 21:53:03 +01:00

83 lines
2.8 KiB
Bash
Executable File

#!/bin/bash
# Source Qubes library.
# shellcheck source=init/functions
. /usr/lib/qubes/init/functions
action=$1
[ -z "$action" ] && action=suspend
MODULES_BLACKLIST=""
if [ -r /etc/qubes-suspend-module-blacklist ]; then
MODULES_BLACKLIST="$MODULES_BLACKLIST $(grep -v '^#' /etc/qubes-suspend-module-blacklist)"
fi
if [ -r /rw/config/suspend-module-blacklist ]; then
MODULES_BLACKLIST="$MODULES_BLACKLIST $(grep -v '^#' /rw/config/suspend-module-blacklist)"
fi
if [ x"$action" = x"suspend" ]; then
if qsvc network-manager ; then
dbus-send --system --print-reply \
--dest=org.freedesktop.NetworkManager \
/org/freedesktop/NetworkManager \
org.freedesktop.NetworkManager.Sleep boolean:true || \
service NetworkManager stop
fi
# Force interfaces down, just in case when NM didn't done it
for intf in /sys/class/net/*; do
intf=$(basename "$intf")
if [ "$intf" = "lo" ] || [[ "$intf" = "vif"* ]]; then
continue
fi
if [ "$(cat "/sys/class/net/$intf/device/devtype" 2>/dev/null$)" = "vif" ]; then
continue
fi
ip l s "$intf" down
done
# detach all drivers from PCI devices (the real ones, not emulated by qemu)
echo -n > /var/run/qubes-suspend-pci-devs-detached
for dev_path in /sys/bus/pci/devices/*; do
# skip qemu emulated devs
subsystem_vendor=$(cat "$dev_path/subsystem_vendor")
if [ "$subsystem_vendor" = "0x1af4" ] || [ "$subsystem_vendor" = "0x5853" ]; then
continue
fi
if ! [ -e "$dev_path/driver" ]; then
continue
fi
bdf=$(basename "$dev_path")
driver_path=$(readlink -f "$dev_path/driver")
echo "$bdf" > "$driver_path/unbind"
echo "$bdf $driver_path" >> /var/run/qubes-suspend-pci-devs-detached
done
LOADED_MODULES=""
for mod in $MODULES_BLACKLIST; do
if lsmod |grep -q "$mod"; then
LOADED_MODULES="$LOADED_MODULES $mod"
modprobe -r "$mod"
fi
done
echo "$LOADED_MODULES" > /var/run/qubes-suspend-modules-loaded
else
# shellcheck disable=SC2013
for mod in $(cat /var/run/qubes-suspend-modules-loaded); do
modprobe "$mod"
done
rm -f /var/run/qubes-suspend-modules-loaded
while read -r dev driver_path; do
echo "$dev" > "$driver_path/bind"
done < /var/run/qubes-suspend-pci-devs-detached
rm -f /var/run/qubes-suspend-pci-devs-detached
if qsvc network-manager ; then
dbus-send --system --print-reply \
--dest=org.freedesktop.NetworkManager \
/org/freedesktop/NetworkManager \
org.freedesktop.NetworkManager.Sleep boolean:false || \
{ under_systemd && systemctl start NetworkManager.service; } || service qubes-core-netvm start
fi
fi