UP | HOME

Date: [2020-05-26 Tue]

Nvidia

Table of Contents

1. Arch Linux Current Setup

  • Install `nvidia' and `nvidia-lts'
  • Install `nvidia-prime'
  • Mkinitcpio
  • /etc/X11/xorg.conf
  • Done
< Collapse code block> Expand code block
Section "Device"
  Identifier "iGPU"
  Driver "intel"
EndSection

Section "Screen"
  Identifier "iGPU"
  Device "iGPU"
EndSection

Section "Device"
  Identifier "dGPU"
  Driver "nvidia"
EndSection

This allows me to use CUDA and PRIME (e.g. prime-run unigine-heaven) but has the following cons:

  • laptop battery is used more
  • resuming from suspend doesn't work

So, I blacklist the nvidia drivers and comment out nvidia device from xorg config. Then only when needed remove the comments and , restart xorg (systemctl restart display-manager).

/etc/X11/xorg.conf

< Collapse code block> Expand code block
Section "Device"
  Identifier "iGPU"
  Driver "intel"
EndSection

Section "Screen"
  Identifier "iGPU"
  Device "iGPU"
EndSection

#Section "Device"
#  Identifier "dGPU"
#  Driver "nvidia"
#EndSection

/etc/modprobe.d/blacklist.conf

< Collapse code block> Expand code block
# nvidia uses a lot of cpu
blacklist nvidia
blacklist nvidia-drm
blacklist nvidia-modeset
blacklist nvidia-uvm
blacklist nouveau

1.1. nvidia-xrun

< Collapse code block> Expand code block
#!/usr/bin/env bash

DRY_RUN=0
function printHelp {
  echo "Utility to run games and applications in separate X on discrete Nvidia graphic card"
  echo "Usage: "
  echo "nvidia-xrun [<options>] [<app>]"
  echo "Options: "
  echo "  -d    Dry run - prints the final command but does not execute it"
}

function execute {
  if [[ ${DRY_RUN} -eq 1 ]]
    then
    echo ">>Dry run. Command: $*"
  else
    eval $*
  fi
}

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

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

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

  echo 'Waiting 1 second'
  execute "sleep 1"

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

  echo '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
    echo "Loading module ${module}"
    execute "sudo modprobe ${module}"
  done
}

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

if [[ "$1" == "-d" ]]
  then
    DRY_RUN=1
    shift 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

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

# calculate current VT
LVT=`fgconsole`

# calculate first usable display
XNUM="-1"
SOCK="something"
while [[ ! -z "$SOCK" ]]
do
  XNUM=$(( $XNUM + 1 ))
  SOCK=$(ls -A -1 /tmp/.X11-unix | grep "X$XNUM" )
done

NEWDISP=":$XNUM"

if [[ ! -z "$*" ]] # generate exec line if arguments are given
then
  # test if executable exists in path
  if [[ -x "$(which $1 2> /dev/null)" ]]
  then
    # generate exec line
    EXECL="$(which $1)"
  # test if executable exists on disk
  elif [[ -e "$(realpath "$1")" ]]
  then
    # generate exec line
    EXECL="$(realpath "$1")"
  else
    echo "$1: No such executable!"
    exit 1
  fi
  shift 1
  EXECL="$EXECL $*"
else # prepare to start new X sessions if no arguments passed
  EXECL=""
fi

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

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

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

# --------- TURNING OFF GPU ----------
if [[ "$ENABLE_PM" == '1' ]]; then
  turn_off_gpu
fi

1.2. DRM kernel mode setting

nvidia 364.16 adds support for DRM (Direct Rendering Manager) kernel mode setting. To enable this feature, add the nvidia-drm.modeset=1 to Kernel Parameter. For basic functionality that should suffice, if you want to ensure it's loaded at the earliest possible occasion, or are noticing startup issues you can add nvidia, nvidiamodeset, nvidiauvm and nvidiadrm to the initramfs according to Mkinitcpio#MODULES.

2. What I had done

This is a good setup. It uses nouveau as the nvidia driver and uses modesetting intel driver. With the DRI_PRIME=1, option I can use nvidia as the renderer. But this setup has some cons:

  • the rendering in nouveau is slow
  • CUDA is not available. For CUDA, it is necessary to install nvidia drivers.

but the good thing is, its very energy efficient. i.e. nvidia graphics card is not used when not required which is good for laptop battery.

no `nvidia` or `nvidia-lts` no `xf86-video-intel`

pacman -Qi xf86-
xf86-input-libinput  xf86-video-nouveau

just the modesetting intel driver and nouveau driver

xrandr --listproviders

Providers: number : 2
Provider 0: id: 0x45 cap: 0xf, Source Output, Sink Output, Source Offload, Sink Offload crtcs: 3 outputs: 3 associated providers: 1 name:modesetting
Provider 1: id: 0xec cap: 0x7, Source Output, Sink Output, Source Offload crtcs: 4 outputs: 1 associated providers: 1 name:nouveau

and nothing inside the /etc/X11/xorg.conf.d/ directory and

ls /usr/share/X11/xorg.conf.d
10-quirks.conf	40-libinput.conf

3. See also

I think I am using PRIME https://wiki.freedesktop.org/nouveau/Optimus/


Backlinks


You can send your feedback, queries here