 ee122eefef
			
		
	
	
		ee122eefef
		
			
		
	
	
	
	
		
			
			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
		
			
				
	
	
		
			83 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			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
 |