Skip to content
This repository has been archived by the owner on Jun 1, 2020. It is now read-only.

Commit

Permalink
Summary in comments
Browse files Browse the repository at this point in the history
  • Loading branch information
BobbyWibowo committed Oct 23, 2019
1 parent 7ae51fa commit 6cd80f8
Show file tree
Hide file tree
Showing 7 changed files with 192 additions and 110 deletions.
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,16 @@ It started with a revelation that bumblebee in current state offers very poor pe
1. run `nvidia-xrun [app]`
1. enjoy

Currently sudo is required as the script needs to wake up GPU, modprobe the nvidia driver and perform cleanup afterwards.
### Passwordless `sudo`
Whitelisting `nvidia-toggle` in your sudoer's file allows you to use `nvidia-xrun` without entering your password:

```
%users ALL=(root) NOPASSWD:/usr/bin/nvidia-toggle
```

...where `/usr/bin/nvidia-toggle` is the full path to the `nvidia-toggle` script.

Note: it is a good practice to ensure binaries/scripts/etc. that are whitelisted for passwordless `sudo` are owned by root.

The systemd service can be used to completely remove the card from the kernel
device tree (so that it won't even show in `lspci` output), and this will
Expand Down
8 changes: 8 additions & 0 deletions config/nvidia-xrun
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,16 @@ ENABLE_PM=1
# and some other programs tend to load the nvidia module if they detect a
# nvidia card in the system, and when the module is loaded the card can't save
# power.
#
# USE_BBSWITCH option below can override the behavior of this option.
REMOVE_DEVICE=1

# When enabled, nvidia-xrun will toggle power for the card using bbswitch.
# This *requires* bbswitch to be installed.
#
# Note that this option overrides REMOVE_DEVICE paramter above when enabled.
USE_BBSWITCH=0

# Bus ID of the PCI express controller
CONTROLLER_BUS_ID=0000:00:01.0

Expand Down
147 changes: 147 additions & 0 deletions nvidia-toggle
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
#!/usr/bin/env bash

# avoid tee to print in the stdout
TEE='tee > /dev/null'
VERBOSE=0
DRY_RUN=0

function printHelp {
echo "Utility to toggle discrete Nvidia graphic card"
echo "Usage: "
echo "nvidia-toggle [<options>] [<on|off>]"
echo "Options: "
echo " -d Dry run - prints the final command but does not execute it"
echo " -v Verbose - verbose output"
}

function execute {
if [[ ${DRY_RUN} -ne 0 ]]; then
echo ">>Dry run. Command: $@"
else
eval "$@"
fi
}

function say {
if [[ "$VERBOSE" == '1' ]]; then
echo "$@"
fi
}

function turn_off_gpu {
if [[ "$USE_BBSWITCH" == '1' ]]; then
echo 'Turning off GPU using bbswitch '
execute "sudo tee /proc/acpi/bbswitch <<<'OFF'"
else
if [[ "$REMOVE_DEVICE" == '1' ]]; then
say 'Removing Nvidia bus from the kernel'
execute "$TEE /sys/bus/pci/devices/${DEVICE_BUS_ID}/remove <<<1"
else
say 'Enabling powersave for the graphic card'
execute "$TEE /sys/bus/pci/devices/${DEVICE_BUS_ID}/power/control <<<auto"
fi

say 'Enabling powersave for the PCIe controller'
execute "$TEE /sys/bus/pci/devices/${CONTROLLER_BUS_ID}/power/control <<<auto"
fi
}

function turn_on_gpu {
if [[ "$USE_BBSWITCH" == '1' ]]; then
echo 'Turning on GPU using bbswitch '
execute "sudo tee /proc/acpi/bbswitch <<<'ON'"
else
say 'Turning the PCIe controller on to allow card rescan'
execute "$TEE /sys/bus/pci/devices/${CONTROLLER_BUS_ID}/power/control <<<on"

say 'Waiting 1 second'
execute "sleep 1"

if [[ ! -d "/sys/bus/pci/devices/${DEVICE_BUS_ID}" ]]; then
say 'Rescanning PCI devices'
execute "$TEE /sys/bus/pci/rescan <<<1"
say "Waiting ${BUS_RESCAN_WAIT_SEC} second for rescan"
execute "sleep ${BUS_RESCAN_WAIT_SEC}"
fi

say 'Turning the card on'
execute "$TEE /sys/bus/pci/devices/${DEVICE_BUS_ID}/power/control <<<on"
fi
}

function load_modules {
for module in "${MODULES_LOAD[@]}"
do
say "Loading module ${module}"
execute "modprobe ${module}"
done
}

function unload_modules {
for module in "${MODULES_UNLOAD[@]}"
do
say "Unloading module ${module}"
execute "modprobe -r ${module}"
done
}

# parse command line flags
while [[ "${1:0:1}" == "-" ]]; do
case "$1" in
-d)
DRY_RUN=1
;;
-v)
VERBOSE=1
;;
-*)
printHelp
exit 1
;;
esac
shift 1
done

# allows tee to print in the stdout
if [[ "$VERBOSE" == '1' ]]; then
TEE='tee'
fi

if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root" >&2
exit 1
fi

# load config file
. /etc/default/nvidia-xrun

# this is used by the systemd service to turn off the gpu at boot
if [[ "$TURN_OFF_GPU_ONLY" == '1' ]]; then
turn_off_gpu
exit 0
fi

case $1 in
on)
# --------- TURNING ON GPU -----------
if [[ "$ENABLE_PM" == '1' ]]; then
turn_on_gpu
fi

# ---------- LOADING MODULES ----------
load_modules
;;
off)
# ---------- UNLOADING MODULES --------
unload_modules

# --------- TURNING OFF GPU ----------
if [[ "$ENABLE_PM" == '1' ]]; then
turn_off_gpu
fi
;;
*)
printHelp
exit 1
;;
esac
29 changes: 16 additions & 13 deletions nvidia-xinitrc
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#!/usr/bin/env bash
#!/bin/sh
# NOTICE: Do not use bash syntaxes here.
# At least in my machine (Ubuntu 18.04),
# this script seem to always be executed with sh.

CONFIG_DIR=${XDG_CONFIG_HOME:-$HOME/.config}/X11
userresources=$CONFIG_DIR/xresources
Expand All @@ -8,39 +11,39 @@ sysmodmap=/etc/X11/xinit/.Xmodmap
userxinitrc=$CONFIG_DIR/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}
export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/nvidia:/usr/lib:${LD_LIBRARY_PATH}

# load additional configs
if [[ -d /etc/X11/xinit/nvidia-xinitrc.d ]] ; then
for f in /etc/X11/xinit/nvidia-xinitrc.d/?*.sh ; do
[[ -x "$f" ]] && . "$f"
done
unset f
if [ -d /etc/X11/xinit/nvidia-xinitrc.d ]; then
for f in /etc/X11/xinit/nvidia-xinitrc.d/?*.sh; do
[ -x "$f" ] && . "$f"
done
unset f
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
12 changes: 1 addition & 11 deletions nvidia-xorg.conf
Original file line number Diff line number Diff line change
@@ -1,13 +1,3 @@
Section "Files"
ModulePath "/usr/lib/nvidia"
ModulePath "/usr/lib32/nvidia"
ModulePath "/usr/lib32/nvidia/xorg/modules"
ModulePath "/usr/lib32/xorg/modules"
ModulePath "/usr/lib64/nvidia/xorg/modules"
ModulePath "/usr/lib64/nvidia/xorg"
ModulePath "/usr/lib64/xorg/modules"
EndSection

Section "ServerLayout"
Identifier "layout"
Screen 1 "nvidia"
Expand All @@ -23,7 +13,7 @@ EndSection
Section "Screen"
Identifier "nvidia"
Device "nvidia"
# Option "AllowEmptyInitialConfiguration" "Yes"
# Option "AllowEmptyInitialConfiguration" "yes"
# Option "UseDisplayDevice" "none"
EndSection

Expand Down
93 changes: 9 additions & 84 deletions nvidia-xrun
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
#!/usr/bin/env bash

# avoid tee to print in the stdout
TEE='tee > /dev/null'
VERBOSE=0
DRY_RUN=0

function printHelp {
Expand All @@ -11,7 +8,6 @@ function printHelp {
echo "nvidia-xrun [<options>] [<app>]"
echo "Options: "
echo " -d Dry run - prints the final command but does not execute it"
echo " -v Verbose - verbose output"
}

function execute {
Expand All @@ -22,83 +18,22 @@ function execute {
fi
}

function say {
if [[ "$VERBOSE" == '1' ]]; then
echo $*
fi
}

function turn_off_gpu {
if [[ "$REMOVE_DEVICE" == '1' ]]; then
say 'Removing Nvidia bus from the kernel'
execute "sudo $TEE /sys/bus/pci/devices/${DEVICE_BUS_ID}/remove <<<1"
else
say 'Enabling powersave for the graphic card'
execute "sudo $TEE /sys/bus/pci/devices/${DEVICE_BUS_ID}/power/control <<<auto"
fi

say 'Enabling powersave for the PCIe controller'
execute "sudo $TEE /sys/bus/pci/devices/${CONTROLLER_BUS_ID}/power/control <<<auto"
}

function turn_on_gpu {
say 'Turning the PCIe controller on to allow card rescan'
execute "sudo $TEE /sys/bus/pci/devices/${CONTROLLER_BUS_ID}/power/control <<<on"

say 'Waiting 1 second'
execute "sleep 1"

if [[ ! -d "/sys/bus/pci/devices/${DEVICE_BUS_ID}" ]]; then
say 'Rescanning PCI devices'
execute "sudo $TEE /sys/bus/pci/rescan <<<1"
say "Waiting ${BUS_RESCAN_WAIT_SEC} second for rescan"
execute "sleep ${BUS_RESCAN_WAIT_SEC}"
fi

say 'Turning the card on'
execute "sudo $TEE /sys/bus/pci/devices/${DEVICE_BUS_ID}/power/control <<<on"
}

function load_modules {
for module in "${MODULES_LOAD[@]}"
do
say "Loading module ${module}"
execute "sudo modprobe ${module}"
done
}

function unload_modules {
for module in "${MODULES_UNLOAD[@]}"
do
say "Unloading module ${module}"
execute "sudo modprobe -r ${module}"
done
}

# parse command line flags
while [[ "${1:0:1}" == "-" ]]; do
case "$1" in
-d)
DRY_RUN=1 ;;
-v)
VERBOSE=1 ;;
DRY_RUN=1
;;
-*)
printHelp && exit 1 ;;
printHelp
exit 1
;;
esac
shift 1
done

# load config file
. /etc/default/nvidia-xrun

# this is used by the systemd service to turn off the gpu at boot
if [[ "$TURN_OFF_GPU_ONLY" == '1' ]]; then
turn_off_gpu
exit 0
fi

if [[ $EUID -eq 0 ]]; then
echo "This script must not be run as root unless TURN_OFF_GPU_ONLY=1 is set" >&2
echo "This script must not be run as root" >&2
exit 1
fi

Expand Down Expand Up @@ -140,21 +75,11 @@ 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 -----------
if [[ "$ENABLE_PM" == '1' ]]; then
turn_on_gpu
fi

# ---------- LOADING MODULES ----------
load_modules
# ---------- TURNING ON GPU ------------
execute "sudo nvidia-toggle -v on"

# ---------- EXECUTING COMMAND --------
execute "${COMMAND}"

# ---------- UNLOADING MODULES --------
unload_modules

# --------- TURNING OFF GPU ----------
if [[ "$ENABLE_PM" == '1' ]]; then
turn_off_gpu
fi
execute "sudo nvidia-toggle -v off"
Loading

1 comment on commit 6cd80f8

@BobbyWibowo
Copy link
Owner Author

@BobbyWibowo BobbyWibowo commented on 6cd80f8 Oct 23, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will include rough summary of upstream's PRs that I merged into this fork:

Merged PRs:

Additional changes:

  • Refactored script to be sudoers-friendly.
    Based on Refactor script to be sudoers-friendly Witko/nvidia-xrun#87, but on top of the latest commit (af3b734) + above PRs.
  • Removed Files section from nvidia-xorg.conf.
    This is an intentional change specifically aimed at Ubuntu installations.
    I'm not sure about the specifics, but it seems that the paths will be populated by a bunch of built-in Ubuntu-specific X.org configs anyway.

Please sign in to comment.