Talk:Nouveau & nvidia-drivers switching

From Gentoo Wiki
Jump to:navigation Jump to:search
Note
This is a Talk page - please see the documentation about using talk pages. Add newer comments below older ones, sign comments using four tildes (~~~~), and indent successive comments with colons (:). Add new sections at the bottom of the page, under a heading (== ==). Please remember to mark sections as "open for discussion" using {{talk|open}}, so they will show up in the list of open discussions.

Rondo (talk) 12:11, 13 December 2013 (UTC) The article suggests 2 kernels, why not just blacklist the nvidia/nouveau module on boot and change xorg.conf?

Switching using a single kernel and systemd (but also openrc and maybe others or maybe this is independant from the init system?)

i did successfully blacklist the nvidia-driver via the grub2 modprobe.blacklist=nvidia option and it did work with openrc. this paragraph should not mention systemd as a prerequisite to do this.

Reuben (talk)

Loading modules for the kernel command line is not the issue. You need a mechanism to control switching the opengl/opencl x11 drivers in xorg.conf. The current documentation uses a systemd environment variable. Not sure if openrc supports setting any environment variables from kernel command line. You might be able to change it according to results from querying the kernel command line via /proc/cmdline

e3k (talk)

@Reuben. Thank you for the explanation. I did not go further than changing the grub to mask the driver i do not need. All the other steps like xorg.conf and opengl settings are done manually. It is sufficient for me as the biggest (timeconsuming) problem for me would be the kernel recompilation.

FireFish5000 (talk) 00:08, 31 July 2015 (UTC) I would like to first confirm that blacklisting modules works with both or is independent of init system, second we can access boot parameter with 'get_bootparam' in init scripts. This is exemplified by /etc/init.d/xdm which searches for the nox (No X) parameter.

I am adding an OpenRC single kernel version to the page. I would like to quickly explain the reasoning behind any/all changes made.

First, I moved OpenRC and Systemd versions to the top, as I imagine the majority of the users are not going to want to compile 2 kernels, and thus believe that this puts them in order from most likely to use to least likely.

I opted to keep modules blacklisted in /etc/modprobe.d/, as this removes worry of both modules being loaded if bootloader doesn't get updated or gets replaced(eg. a careless user with dispatch-config, editing grub.cfg directly and then calling update-grub). The modules can then be loaded by the script, and a default can be provided in case of the exemplified error above.

I am moving the init script to /etc/init.d/nv-selector for two reasons.

  1. nvidia.start seems to imply nvidia driver. I am hoping nv makes nvidia and nouveau equally likely, and selector shows we are selecting the driver. nvidia-nouveau or another name may be better.
  2. It was the only script in my local.d directory. Unless there is an explicit reason for separating it into local.d (some standard for loading drivers? Can't load faster since it depends on a boot-service.), I would prefer to have it grouped with all the other init scripts.

I am setting two NON-dot-conf files in /etc/X11/xorg.conf.d/ for the init script to link to. The reason being that with multihead setups, the work needed to be done may be more complex than just sed 's/nvidia/nouveau/'. We may want to change options like referesh rate, vsync, twinview, dpi, etc depending on driver for a better experience. I use it for naming the monitors which I configure in other files, because for some reason nvidia indexes the ports on 0 while nouveau starts at 1...

The two kernel method is being modified to explicitly recommend builtin nouveau support on one of them, since it makes no sense to have two kernels otherwise. (though it did make sense when written, we now know of a better way)

NOTE: The changes to the wiki proposed below are posted here partially for testing (moving to laptop to reproduce), but mostly to save the changes externaly in case something goes wrong with my computer. Still revising

Module Based Switching

With module based switching, a single kernel is setup to be used with both nvidia and nouveau modules, the bootloader is configured to specify which module to load, and an init script does everything necessary to get the driver and system to work together.

Configure the System

Before switching is possible, the system must be properly configured to support it.

To do this, first make sure the nouveau driver is built as a module:

KERNEL
Device Drivers  --->
    Graphics support  --->
        <*> Direct Rendering Manager (XFree86 4.1.0 and higher DRI support) --->
            <M> Nouveau (nVidia) cards

Then recompile and install the kernel and kernel modules.

Next set the VIDEO_CARDS variable to support both nvidia and nouveau drivers.

FILE /etc/portage/make.confSet VIDEO_CARDS to nvidia nouveau
VIDEO_CARDS="... nvidia nouveau ..."

After setting or altering VIDEO_CARDS values remember to update the system using the following command so the changes take effect:

root #emerge --ask --changed-use --deep @world

And blacklist the nvidia and nouveau modules as you don't want udev to try and autoload them.

root #echo -e "blacklist nouveau\nblacklist nvidia" >> /etc/modprobe.d/nvidia-n-nouveau.conf

If X11 is used on the system, then two config files need to be setup in /etc/X11/xorg.conf.d/. These files, /etc/X11/xorg.conf.d/00-nv.nvidia and /etc/X11/xorg.conf.d/00-nv.nouveau (name does not matter), will specify settings necessary for nvidia and nouveau drivers respectively. Note they mustn't end in '.conf', as they are not to be loaded themselves. /etc/X11/xorg.conf.d/00-nv.conf will link to the file in use.

FILE /etc/X11/xorg.conf.d/00-nv.nvidia
Section "Device"
	Identifier	"nvidia"
	Driver		"nvidia"
EndSection
</nowiki>
FILE /etc/X11/xorg.conf.d/00-nv.nouveau
Section "Device"
	Identifier	"nouveau"
	Driver		"nouveau"
EndSection
</nowiki>

If driver specific settings need to be supplied, these files would be the place to put them. Some options which may be of interest include TwinView(NVidia only), DPI, monitor-* on multihead systems.

With this, the system should be capable of switching between the two. However, there is nothing currently telling it to automatically load either. To get it loading one on boot, an init script is needed.

Init Scripts

These scripts check for the boot parameters that will be set in the bootloader and setup the system appropriately. Specifically, these scripts load the drivers modules, switch to it's opengl and opencl implementation, and tell xorg which driver to use. With this, driver switching can easily be done with OpenRC and Systemd based init systems. Just follow the instructions relative to the system's setup.

OpenRC

OpenRC is Gentoo's default init system, and thus the one most people will be using. Most of the scripts it uses are located in /etc/init.d/. These scripts are intended to be static, and as such, variables are usualy defined in /etc/conf.d/ in a file of the same name. This script is written keeping that in mind, so hopefully there will be no need to edit it.

FILE /etc/init.d/nv-selector
#!/sbin/runscript
# Copyright 2015 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

Prefix="[NV-Driver] "
depend() {
	need localmount
	before xdm
}

nvidia_start() {
		einfo "${Prefix}Loading NVIDIA driver"
		modprobe -q nvidia
		ln -f /etc/X11/xorg.conf.d/00-nv.nvidia /etc/X11/xorg.conf.d/00-nv.conf
		eselect opengl set nvidia &>/dev/null
		eselect opencl set nvidia &>/dev/null
		echo 'nvidia' > '/CURRENT_NV_DRIVER'
		einfo "${Prefix}Loaded NVIDIA driver"
}

nouveau_start() {
		einfo "${Prefix}Loading NOUVEAU driver"
		modprobe -q nouveau
		ln -f /etc/X11/xorg.conf.d/00-nv.nouveau /etc/X11/xorg.conf.d/00-nv.conf
		eselect opengl set xorg-x11 &>/dev/null
		/etc/init.d/consolefont restart
#		eselect opencl set mesa &>/dev/null
		echo 'nouveau' > '/CURRENT_NV_DRIVER'
		einfo "${Prefix}Loaded NOUVEAU driver"
}
show() {
	Driver="$(cat /CURRENT_NV_DRIVER)"
	if [[ -n "$Driver" ]] ; then
		einfo "${Prefix}Using NV-Driver '$Driver'"
	else
		einfo "${Prefix}No NV-Driver Found '$Driver'"
	fi
}
boot_start() {
	if get_bootparam "use_nvidia" ; then
		nvidia_start
	else
		nouveau_start
	fi
	eend $?
}
start() {
	ebegin "${Prefix}Loading driver"
	boot_start
	eend $?
}

Copy it to /etc/init.d/nv-selector and set the executable bit:

root #chmod +x /etc/init.d/nv-selector

Then add it as a boot level service.

root #rc-update add nv-selector boot

Systemd

Add the systemd switching script

FILE /etc/local.d/nvidia.startOpenGL + OpenCL
#!/bin/bash

if [[ "$GPUMOD" == "nvidia" ]] ; then
        if [[ $(eselect opengl show) != nvidia ]] ; then
                eselect opengl set nvidia &&gt;/dev/null
                eselect opencl set nvidia &&gt;/dev/null
        fi
cat &gt; /etc/X11/xorg.conf.d/01-nv.conf &lt;&lt; EOF
Section "Device"
  Identifier   "Device0"
  Driver       "nvidia"
  Option       "NoLogo" "True"
EndSection
EOF
else
        if [[ $(eselect opengl show) != xorg-x11 ]] ; then
                eselect opengl set xorg-x11 &&gt;/dev/null
                eselect opencl set mesa &&gt;/dev/null
        fi
cat &gt; /etc/X11/xorg.conf.d/01-nv.conf &lt;&lt; EOF
Section "Device"
  Identifier   "Device0"
  Driver       "nouveau"
EndSection
EOF
fi

Remember to set the executable bit.

root #chmod +x /etc/local.d/nvidia.start

To have this script get called during the systemd init process, you can create a service file for it, but it's just as effective to integrate it into the currently existing xdm | gdm | kdm | other(?) display manager service file. You don't want to edit the service file directly, since that will get overwritten the next time that package is merged that the service file belongs to. Instead you create an override for the service file, placed in /etc/systemd/system/service-name.d

So for example if you use kdm.service you would create the directory /etc/systemd/system/kdm.service.d and place a file in it with a .conf file extension. Add a "[Service]" section that has an entry for ExecStartPre to call nvidia.start before kdm itself is started.

root #mkdir /etc/systemd/system/kdm.service.d && touch /etc/systemd/system/kdm.service.d/nv.conf
FILE /etc/systemd/system/kdm.service.d/nv.confActual contents may vary
[Service]
ExecStartPre=/etc/local.d/nvidia.start

Bootloader

It should be possible to pass boot parameters with most bootloader, however, the means of doing it may differ. Please read other documentation for bootloaders not specified here. Note the instructions here are made to be as simple as possible. Configurations vary, please consult the existing configuration and adapt the instructions to the system.

Grub

Note
The grub2 menu items shown are for demonstrating the changes to be made. Hopefully you have the common sense not to just copy and paste them verbatim into your grub.cfg.

Within the grub.cfg file you need to duplicate the desired menu item and then edit the two versions to set a boot parameter.

FILE /boot/grub2/grub.cfgBefore:
menuentry 'Gentoo Linux' {
        root=hd0,1
        linux /boot/bzImage root=PARTUUID=11111111-2222-3333-4444-555555555555 init=/usr/lib/systemd/systemd console=tty1
}
FILE /boot/grub2/grub.cfgAfter:
menuentry 'Gentoo Linux - Nouveau' {
        root=hd0,1
        linux /boot/bzImage root=PARTUUID=11111111-2222-3333-4444-555555555555 init=/usr/lib/systemd/systemd console=tty1 modprobe.blacklist=nvidia systemd.setenv=GPUMOD=nouveau
}

menuentry 'Gentoo Linux - Nvidia' {
        root=hd0,1
        linux /boot/bzImage root=PARTUUID=11111111-2222-3333-4444-555555555555 init=/usr/lib/systemd/systemd console=tty1 modprobe.blacklist=nouveau systemd.setenv=GPUMOD=nvidia
}

Efibootmgr

Before altering anything, it is a probably good idea to read and backup the current configuration. Do this by running:

root #efibootmgr -v | tee ~/EfiBootMgr_settings

Now, review the settings and alter accordingly. Below shows how one may be setup when there are no pre-existing boot entries.

Note
PARTUUID can be found with ls -l /dev/disk/by-partuuid. NOT the same as UUID. root=UUID may or may not work

Note the current efi boot settings, it will aid in the process. It may be a good idea to copy them just in case something goes wrong

root #efibootmgr -c -L "Gentoo Linux (nouveau)" --loader '\efi\partition\relitive\path\to\Kernel.efi' -u 'root=PARTUUID=01234567-89ab-cdef-0123-456789abcdef use_nouveau'
root #efibootmgr -c -L "Gentoo Linux (nvidia)" --loader '\efi\partition\relitive\path\to\Kernel.efi' -u 'root=PARTUUID=01234567-89ab-cdef-0123-456789abcdef use_nvidia'
root #efibootmgr --bootorder 0000,0001


Using Two Kernels

One may also setup two kernels, one with nouveau built-in and the other without it or with it built as a module. Note there is little reason to use two kernels unless nouveau is compiled-in one of them. To do this, First compile two kernels, One with Nouveau built-in

KERNEL
Device Drivers  --->
    Graphics support  --->
        <*> Direct Rendering Manager (XFree86 4.1.0 and higher DRI support) --->
            <*> Nouveau (nVidia) cards

And one without or as a module

KERNEL
Device Drivers  --->
    Graphics support  --->
        <*> Direct Rendering Manager (XFree86 4.1.0 and higher DRI support) --->
            < > Nouveau (nVidia) cards

Next, Follow the same steps as above for the bootloader, changing the path/name for the nvidia and nouveau entries to point to the respective kernels.

Then refer to Init systems for seting up the script which will handle loading nvidia, changing opengl, opencl, and x11 config files .

Possibility of Live (no reboot) switching

--FireFish5000 (talk) 08:29, 10 August 2015 (UTC) It may be possible, with difficulty, to switch between nouveau and nvidia drivers without a reboot (it's GNU/Linux, the real question is how practical such a solution would be).

The instructions below should lead you to the little I currently have. It works for X11(loosing console) from nouveau to nvidia. But from nvidia to nouveau, it corrupts the display completely and goes blank/freezes with x11 (though x11 does start, ie. I can type startx, open firefox and listen to youtube videos blind).

First Ensure module unloading is supported

KERNEL
[*] Enable loadable module support  --->
    [*]   Module unloading

Then add/modify the nv-driver switcher.

FILE /etc/init.d/nv-switcher
#!/sbin/runscript
# Copyright 1999-2009 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/x11-base/xorg-server/files/xdm-setup.initd-1,v 1.1 2010/04/13 10:07:39 scarabeus Exp $

extra_commands="nvidia nouveau show"
#extra_started_commands="nvidia"
depend() {
	need localmount
	before xdm
}

nvidia_start() {
		einfo "[NV-Driver] Loading NVIDIA driver"
		modprobe -q nvidia
		ln -f /etc/X11/xorg.conf.d/00-nv.conf.DISABLED /etc/X11/xorg.conf.d/00-nvidia.conf
		eselect opengl set nvidia &&gt;/dev/null
		eselect opencl set nvidia &&gt;/dev/null
		echo 'nvidia' &gt; '/CURRENT_NV_DRIVER'
		einfo "[NV-Driver] Loaded NVIDIA driver"
}

nouveau_start() {
		einfo "[NV-Driver] Loading NOUVEAU driver"
		modprobe -q nouveau
		ln -f /etc/X11/xorg.conf.d/00-nouveau.conf.DISABLED /etc/X11/xorg.conf.d/00-nvidia.conf
		eselect opengl set xorg-x11 &&gt;/dev/null
		/etc/init.d/consolefont restart
#		eselect opencl set mesa &&gt;/dev/null
		echo 'nouveau' &gt; '/CURRENT_NV_DRIVER'
		einfo "[NV-Driver] Loaded NOUVEAU driver"
}
nvidia_stop() {
		einfo "[NV-Driver] Unloading NVIDIA driver"
		# TODO Close x11 and all using driver. Or ensure that they have closed
		modprobe -q -r nvidia
		einfo "[NV-Driver] Unloaded NVIDIA driver"
}
nouveau_stop() {
		einfo "[NV-Driver] Unloading NOUVEAU driver"
		# TODO Close x11 and all using driver. Or ensure that they have closed
		echo 0 &gt; /sys/class/vtconsole/vtcon1/bind
		#modprobe -q -r nouveau ttm drm_kms_helper drm
		modprobe -q -r nouveau
		/etc/init.d/consolefont restart
		modprobe -q -r ttm drm_kms_helper drm
		einfo "[NV-Driver] Unloaded NOUVEAU driver"
}

nvidia() {
	ebegin "[NV-Driver] Switching to NVIDIA driver"
	nouveau_stop
	nvidia_start
	eend $?
}
nouveau() {
	ebegin "[NV-Driver] Switching to NOUVEAU driver"
	nvidia_stop
	nouveau_start
	eend $?
}
show() {
	Driver="$(cat /CURRENT_NV_DRIVER)"
	if [[ -n "$Driver" ]] ; then
		einfo "Using NV-Driver '$Driver'"
	else
		einfo "No NV-Driver Found '$Driver'"
	fi
}
boot_start() {
	if get_bootparam "use_nvidia" ; then
		nvidia_start
	else
		nouveau_start
	fi
	eend $?
}
start() {
	if get_bootparam "use_nvidia" ; then
		ebegin "[NV-Driver] Loading NVIDIA driver"
		modprobe -q nvidia
		ln -f /etc/X11/xorg.conf.d/00-nv.conf.DISABLED /etc/X11/xorg.conf.d/00-nvidia.conf
		eselect opengl set nvidia &&gt;/dev/null
		eselect opencl set nvidia &&gt;/dev/null
		echo 'nvidia' &gt; '/CURRENT_NV_DRIVER'
	else
		ebegin "[NV-Driver] Loading NOUVEAU driver"
		modprobe -q nouveau
		ln -f /etc/X11/xorg.conf.d/00-nouveau.conf.DISABLED /etc/X11/xorg.conf.d/00-nvidia.conf
		eselect opengl set xorg-x11 &&gt;/dev/null
#		eselect opencl set mesa &&gt;/dev/null
		echo 'nouveau' &gt; '/CURRENT_NV_DRIVER'
	fi
	eend $?
}

With the above script, '/etc/init.d/nv-switcher nvidia' would switch to nvidia if run from shell while x11 isn't running (Checking if in use is in TODO. lsmod seems to be a good indicator, Do NOT try this script while X11 is running or if you do not understand what it is doing). Howver, shell would be blank and '/etc/init.d/nv-switcher nouveau' Would leave you in said state where nothing shows up but blind x11 will nonetheless start. This incomplete and potential harmful script was adapted from the scripts given on this page combined with the scripts here https://askubuntu.com/questions/16998/switch-between-nvidia-current-and-nouveau-without-a-reboot/17068#17068 and the suggestion here https://askubuntu.com/questions/16998/switch-between-nvidia-current-and-nouveau-without-a-reboot/381689#381689. Perhaps someone with more experience dealing with nvidia, nouveau, kernel modules, drivers, or the kernel will have a better idea on how to accomplish this.

Again, this script does NOT currently check if drivers are in use, and WILL lead to both nvidia and Nouveau drivers being loaded if you do not know what you are doing. Don't try this unless you understand the risk.

If you know a way to do this, please tell us. If you add a check for if mods are in use/successfully unloaded, feel free to edit my script to add them.