diff --git a/.gitignore b/.gitignore index 2bc7515..505e08f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ # Created by .ignore support plugin (hsz.mobi) nvidia-xrun.iml .idea +test-install.sh +test-cleanup.sh \ No newline at end of file diff --git a/README.md b/README.md index f5fdced..50051d0 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ When the nvidia-xrun command is used, the device is added again to the tree so t * **/etc/X11/xinit/nvidia-xinitrc.d** - custom xinitrc scripts directory * **/etc/X11/nvidia-xorg.conf.d** - custom X config directory * **/etc/systemd/system/nvidia-xrun-pm.service** systemd service +* **/etc/default/nvidia-xrun** - nvidia-xrun config file * **/usr/share/xsessions/nvidia-xrun-openbox.desktop** - xsession file for openbox * **/usr/share/xsessions/nvidia-xrun-plasma.desktop** - xsession file for plasma * **[OPTIONAL] ~/.nvidia-xinitrc** - user-level custom xinit script file. You can put here your favourite window manager for example @@ -59,6 +60,12 @@ Also this way you can adjust some nvidia settings if you encounter issues: # Option "UseDisplayDevice" "none" EndSection +In order to make power management features work properly, you need to make sure +that bus ids in `/etc/default/nvidia-xrun` are correctly set for both the +NVIDIA graphic card and the PCI express controller that hosts it. You should be +able to find both the ids in the output of `lshw`: the PCIe controller is +usually displayed right before the graphic card. + ## Automatically run window manager For convenience you can create `nano ~/.nvidia-xinitrc` and put there your favourite window manager: diff --git a/config/nvidia-xrun b/config/nvidia-xrun new file mode 100644 index 0000000..1c87056 --- /dev/null +++ b/config/nvidia-xrun @@ -0,0 +1,5 @@ +CONTROLLER_BUS_ID=0000:00:01.0 +DEVICE_BUS_ID=0000:01:00.0 +BUS_RESCAN_WAIT_SEC=1 +MODULES_LOAD=(nvidia nvidia_uvm nvidia_modeset "nvidia_drm modeset=1") +MODULES_UNLOAD=(nvidia_drm nvidia_modeset nvidia_uvm nvidia) diff --git a/nvidia-xinitrc b/nvidia-xinitrc index a81eaef..ffa4f11 100644 --- a/nvidia-xinitrc +++ b/nvidia-xinitrc @@ -1,4 +1,5 @@ -#!/bin/bash +#!/usr/bin/env bash + userresources=$HOME/.Xresources usermodmap=$HOME/.Xmodmap sysresources=/etc/X11/xinit/.Xresources @@ -6,28 +7,28 @@ sysmodmap=/etc/X11/xinit/.Xmodmap userxinitrc=$HOME/.nvidia-xinitrc # merge in defaults and keymaps -if [ -f ${sysresources} ]; then +if [[ -f ${sysresources} ]]; then xrdb -merge ${sysresources} fi -if [ -f ${sysmodmap} ]; then +if [[ -f ${sysmodmap} ]]; then xmodmap ${sysmodmap} fi -if [ -f "$userresources" ]; then +if [[ -f "$userresources" ]]; then xrdb -merge "$userresources" fi -if [ -f "$usermodmap" ]; then +if [[ -f "$usermodmap" ]]; then xmodmap "$usermodmap" fi export LD_LIBRARY_PATH=/usr/lib64/nvidia/:/usr/lib32/nvidia:/usr/lib:${LD_LIBRARY_PATH} # load additional configs -if [ -d /etc/X11/xinit/nvidia-xinitrc.d ] ; then +if [[ -d /etc/X11/xinit/nvidia-xinitrc.d ]] ; then for f in /etc/X11/xinit/nvidia-xinitrc.d/?*.sh ; do - [ -x "$f" ] && . "$f" + [[ -x "$f" ]] && . "$f" done unset f fi @@ -35,10 +36,10 @@ fi xrandr --setprovideroutputsource modesetting NVIDIA-0 xrandr --auto -if [ -f "$userxinitrc" ]; then +if [[ -f "$userxinitrc" ]]; then sh ${userxinitrc} $* else - if [ $# -gt 0 ]; then - "$*" + if [[ $# -gt 0 ]]; then + sh -c "exec $*" fi fi diff --git a/nvidia-xrun b/nvidia-xrun old mode 100644 new mode 100755 index f6eda28..2719096 --- a/nvidia-xrun +++ b/nvidia-xrun @@ -1,4 +1,5 @@ -#!/bin/bash +#!/usr/bin/env bash + DRY_RUN=0 function printHelp { echo "Utility to run games and applications in separate X on discrete Nvidia graphic card" @@ -9,7 +10,7 @@ function printHelp { } function execute { - if [ ${DRY_RUN} -eq 1 ] + if [[ ${DRY_RUN} -eq 1 ]] then echo ">>Dry run. Command: $*" else @@ -17,25 +18,40 @@ function execute { fi } +function turn_off_gpu { + echo 'Removing Nvidia bus from the kernel' + execute "sudo tee /sys/bus/pci/devices/${DEVICE_BUS_ID}/remove <<<1" -if [[ $EUID -eq 0 ]]; then - echo "This script must not be run as root" >&2 - exit 1 -fi + echo 'Enabling powersave for the PCIe controller' + execute "sudo tee /sys/bus/pci/devices/${CONTROLLER_BUS_ID}/power/control <<&2 + exit 1 +fi + # calculate current VT LVT=`fgconsole` # calculate first usable display XNUM="-1" SOCK="something" -while [ ! -z "$SOCK" ] +while [[ ! -z "$SOCK" ]] do XNUM=$(( $XNUM + 1 )) SOCK=$(ls -A -1 /tmp/.X11-unix | grep "X$XNUM" ) @@ -43,15 +59,15 @@ done NEWDISP=":$XNUM" -if [ ! -z "$*" ] # generate exec line if arguments are given +if [[ ! -z "$*" ]] # generate exec line if arguments are given then # test if executable exists in path - if [ -x "$(which $1 2> /dev/null)" ] + if [[ -x "$(which $1 2> /dev/null)" ]] then # generate exec line EXECL="$(which $1)" # test if executable exists on disk - elif [ -e "$(realpath "$1")" ] + elif [[ -e "$(realpath "$1")" ]] then # generate exec line EXECL="$(realpath "$1")" @@ -65,54 +81,43 @@ else # prepare to start new X sessions if no arguments passed EXECL="" fi -EXECL="/etc/X11/xinit/nvidia-xinitrc $EXECL" +EXECL="/etc/X11/xinit/nvidia-xinitrc \"$EXECL\"" COMMAND="xinit $EXECL -- $NEWDISP vt$LVT -nolisten tcp -br -config nvidia-xorg.conf -configdir nvidia-xorg.conf.d" # --------- TURNING ON GPU ----------- echo 'Turning the PCIe controller on to allow card rescan' -execute "sudo tee /sys/bus/pci/devices/0000:00:01.0/power/control << /sys/bus/pci/devices/0000:01:00.0/remove' -ExecStart=/bin/bash -c 'echo auto > /sys/bus/pci/devices/0000:00:01.0/power/control' +Environment="TURN_OFF_GPU_ONLY=1" +ExecStart=/usr/bin/nvidia-xrun [Install] WantedBy=multi-user.target