Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
[script init] choix pilote nvidia/nouveau à chaque boot
View unanswered posts
View posts from last 24 hours

 
Reply to topic    Gentoo Forums Forum Index French
View previous topic :: View next topic  
Author Message
netfab
Veteran
Veteran


Joined: 03 Mar 2005
Posts: 1887
Location: 127.0.0.1

PostPosted: Thu Jan 27, 2011 12:06 pm    Post subject: [script init] choix pilote nvidia/nouveau à chaque boot Reply with quote

À l'origine cette astuce découle du sujet suivant : [nvidia] le nouveaux choix du libre.

Historique :
  • 05/03/2013 : réécriture complète de la technique et du script d'initialisation, permettant ainsi de n'utiliser (et de maintenir) qu'un seul kernel avec des paramètres différents, merci à GentooUser@Clubic plus loin dans le topic pour l'inspiration.


Choix entre nouveau/KMS ou nvidia/uvesafb à chaque boot
J'utilise grub2. Le framebuffer uvesafb est activé si le pilote nvidia est choisi, sinon il est désactivé avec le pilote nouveau.
Si vous préférez utiliser vesafb (qui doit être compatible avec KMS), voyez le post de GentooUser@Clubic plus bas. Je n'ai pas encore essayé avec, j'essaierai à l'occasion et mettrai à jour cette astuce si besoin.

Configuration kernel :
Tout ce qui suit se fait avec un kernel relativement récent configuré de la manière suivante :
Code:

Device Drivers  --->
   Graphics support  --->
      <*> Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)  --->
         <*>   Nouveau (nVidia) cards
      <*> Support for frame buffer devices  --->
         -*-   Enable Video Mode Handling Helpers
         <*>   Userspace VESA VGA graphics support


Au moment de la compilation du kernel il est possible que vous ayez ces avertissements (c'est le cas avec un kernel vanilla-3.4.34) :
Quote:

warning: (DRM_NOUVEAU) selects ACPI_WMI which has unmet direct dependencies (X86 && X86_PLATFORM_DEVICES && ACPI)
warning: (DRM_NOUVEAU) selects MXM_WMI which has unmet direct dependencies (X86 && X86_PLATFORM_DEVICES && ACPI_WMI)

Petit problème de dépendance du pilote nouveau, à rectifier en activant cette option :
Code:

Device Drivers  --->
   [*] X86 Platform Specific Device Drivers  --->


Configuration Xorg :
Pour xorg je crée deux fichiers de configuration indépendants. Lors de l'éxécution du script d'initialisation, je crée un lien symbolique vers l'un de ces fichiers dans le répertoire xorg.conf.d.
Code:

$ ls -l /etc/X11 | grep xorg
-rw-r--r-- 1 root root  235 23 janv. 14:53 xorg-nouveau.conf
-rw-r--r-- 1 root root  322 25 janv. 18:51 xorg-nvidia.conf
drwxr-xr-x 2 root root 4096 25 janv. 23:52 xorg.conf.d


Dans le fichier xorg-nvidia.conf, en plus de ma configuration habituelle pour le driver propriétaire, j'ai ceci, afin d'éviter le chargement automatique du driver nouveau :
Code:

Section "Module"
        Disable     "nouveau"
EndSection


Le fichier xorg-nouveau.conf contient quant à lui :
Code:

Section "Module"
   Disable     "nvidia"
EndSection

Section "Device"
   Identifier  "Card0"
   Driver      "nouveau"
EndSection


Script d'initialisation :
À modifier selon vos besoins (xvmc par exemple) et à lancer au runlevel default :
Code:

#!/sbin/runscript
# Copyright 1999-2013 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $

depend() {
   need localmount
   before xdm
}

_switch_to() {
   local DRIVER=$1 OPENGL=${2:-$1}

   ebegin "Setting up X environment for ${DRIVER} driver"
   ln -snf /etc/X11/xorg-${DRIVER}.conf /etc/X11/xorg.conf.d/99-videocard.conf
   eend $? || return 1

   if [ ! ${OPENGL} = `eselect opengl show` ]; then
      ebegin "Switching to ${OPENGL} OpenGL implementation"
      eselect opengl set "${OPENGL}" >/dev/null 2>&1
      eend $? "Failed to set ${OPENGL} OpenGL interface" || return 1
   fi

   return 0
}

_switch_to_nvidia() {
   _switch_to nvidia
   exit $?
}

_switch_to_nouveau() {
   _switch_to nouveau xorg-x11
   exit $?
}

start() {
   for i in `cat /proc/cmdline` ; do
      case $i in
         nouveau|nvidia) eval _switch_to_$i ;;
      esac
   done

   # default driver if nothing found on kernel command line
   local default=nvidia
   einfo "No X driver asked on kernel command line. Using default : $default"
   eval _switch_to_$default
}




Configuration de grub2 :
Dans la configuration de grub2, je choisis d'activer par défaut nvidia/uvesafb.
Dans le menu de grub, j'ajoute ensuite une entrée supplémentaire avec des paramètres kernel différents pour désactiver uvesafb et activer nouveau.

Dans /etc/default/grub, j'ajoute à la variable GRUB_CMDLINE_LINUX_DEFAULT les paramètres suivants :
Code:
nomodeset nvidia video=uvesafb:mtrr:3,ywrap,1680x1050-32@60

Ainsi, tous les kernels détectés par grub2 booteront avec ces paramètres.

Ensuite je génère la configuration de grub2 :
Code:

# grub2-mkconfig -o /boot/grub2/grub.cfg


Enfin, depuis le fichier de configuration de grub fraîchement généré, je copie la première entrée du menu, qui ressemble à ceci (environ une quinzaine de lignes, dépend de votre configuration grub) :
Code:

menuentry 'Gentoo GNU/Linux' --class gentoo --class gnu-linux [...] {
   [...]
   echo    'Chargement de Linux 3.4.34…'
        linux   /boot/kernel-3.4.34 [...]  nomodeset nvidia video=uvesafb:mtrr:3,ywrap,1680x1050-32@60 [...]
   [...]
}

Je colle donc cette entrée dans le fichier /etc/grub.d/40_custom en modifiant le nom de l'entrée et les paramètres kernel pour désactiver uvesafb et utiliser nouveau :
Code:

menuentry 'Gentoo GNU/Linux -- nouveau' --class gentoo --class gnu-linux [...] {
   [...]
   echo    'Chargement de Linux 3.4.34…'
        linux   /boot/kernel-3.4.34 [...]  video=uvesafb:off nouveau [...]
   [...]
}


Et je régénère la configuration de grub2 pour prendre en compte l'entrée du menu pour nouveau.
Code:

# grub2-mkconfig -o /boot/grub2/grub.cfg


Last edited by netfab on Tue Mar 05, 2013 3:32 pm; edited 4 times in total
Back to top
View user's profile Send private message
Leander256
l33t
l33t


Joined: 05 Jul 2003
Posts: 910
Location: Singapour

PostPosted: Sun Jan 30, 2011 10:05 pm    Post subject: Reply with quote

Merci beaucoup pour cette astuce (que j'ai mise en oeuvre chez moi), je trouve ceci dit un peu dommage de devoir créer 2 runlevels qu'il va falloir garder synchrones avec default. Du coup je me demande si il ne serait pas plus pratique de compiler le noyau avec l'option pour stocker son fichier config dans /proc/config.gz, puis de faire simplement un grep dans le script (qui serait donc dans default) pour déterminer de quel type de noyau il s'agit.
Back to top
View user's profile Send private message
netfab
Veteran
Veteran


Joined: 03 Mar 2005
Posts: 1887
Location: 127.0.0.1

PostPosted: Mon Jan 31, 2011 9:01 am    Post subject: Reply with quote

Alors là, je dois avouer que je n'avais pas pensé une seule seconde à greper la configuration du kernel, j'etais parti directement sur l'option des runlevels, et je dois dire que cela me gênait un peu aussi. J'ai modifié le script et le post original, effectivement çà simplifie tout, merci :D
Back to top
View user's profile Send private message
Leander256
l33t
l33t


Joined: 05 Jul 2003
Posts: 910
Location: Singapour

PostPosted: Tue Feb 01, 2011 5:45 pm    Post subject: Reply with quote

Merci pour la modif, j'ai fait les changements sur mon système mais je n'ai pas encore redémarré l'ordi (puisqu'il a arrêté de planter maintenant que je suis repassé au pilote nvidia :roll: ).
Back to top
View user's profile Send private message
mazes80
n00b
n00b


Joined: 24 Feb 2011
Posts: 13
Location: toulouse - france

PostPosted: Tue May 10, 2011 4:40 pm    Post subject: Reply with quote

Peut être faudrait-il aussi fixer l'implémentation de xvmc (si utilisé):
Code:
eval eselect xvmc "${impl}"

Une alternative au zgrep sur /proc/config.gz peut être utilisé grâce à CONFIG_LOCALVERSION
    _xorg-x11
    _nvidia
On peut ainsi récupérer l'implémentation à utiliser avec:
Code:
uname -r | sed 's/^.*_//'

Après à chacun d'adapter ce script en fonction de ses besoins et de ses préférences.

Merci pour l'idée.

P.S.: quel est l'intérêt de l'utilisation systématique de eval ?
Back to top
View user's profile Send private message
netfab
Veteran
Veteran


Joined: 03 Mar 2005
Posts: 1887
Location: 127.0.0.1

PostPosted: Mon May 16, 2011 7:38 am    Post subject: Reply with quote

Oui, chacun peut adapter en fonction de ses préférences, j'essaierai avec CONFIG_LOCALVERSION dès que j'aurai 2 minutes.
J'ai ajouté l'eselect pour XvMC, merci.
Quote:
P.S.: quel est l'intérêt de l'utilisation systématique de eval ?

Simple question d'habitude, je t'avouerai que je n'avais même pas remarqué.
Back to top
View user's profile Send private message
GentooUser@Clubic
l33t
l33t


Joined: 01 Nov 2004
Posts: 829

PostPosted: Sun Oct 09, 2011 12:58 am    Post subject: Reply with quote

Up pour dire merci pour ce script :wink:

Par contre je sait pas si c'est chez moi mais je trouve "eselect opengl set xxx" est assez lent à rendre la main :
Quote:

eselect opengl set nvidia 0,40s user 0,12s system 51% cpu 0,997 total
eselect opengl set xorg-x11 0,44s user 0,07s system 52% cpu 0,982 total

J'ai donc un peu modifié le script pour rajouter un test et n’exécuter la commande que si c’est nécessaire :

Code:

        if [ ! "$(eselect opengl show)" = "${impl}" ]; then
                ebegin "Switching to ${impl} OpenGL implementation"
                eval eselect opengl set "${impl}" >/dev/null 2>&1
                eend $? "Failed to set ${impl} OpenGL interface" || return 1
        fi


Si aucun changement n'est nécessaire, c'est tout benef :
Quote:
eselect opengl show 0,01s user 0,01s system 42% cpu 0,032 total
Back to top
View user's profile Send private message
GentooUser@Clubic
l33t
l33t


Joined: 01 Nov 2004
Posts: 829

PostPosted: Sat Mar 02, 2013 11:04 pm    Post subject: Reply with quote

Bon si ça intéresse toujours du monde y'a une nouvelle recette maintenant, avec un seul noyau :D

- Activez nouveau dans le noyau, en dur ou module suivant votre préférence (perso je préfère en dur, pour profiter de la console hd le plus tôt possible)
- Activez vesafb dans le noyau, si vous voulez profiter du framebuffer avec les drivers nvidia (pas uvesafb, j'ai pas testé mais c’est marqué incompatible) et de toute façon :
Quote:

You may have read people use uvesafb over vesafb, as it had better performance. This WAS generally true, but not in a modern distro with modern Hardware. If your Graphics Hardware supports protected mode VESA (VESA >= 2.0 ), and you have a somewhat recent kernel vesafb is now a better choice.

- Bien sûr installez les drivers nvidia et nouveau, mais ça vous savez le faire :lol:

- Pour booter avec nouveau rien à faire : voici ma ligne de commande grub :
Code:

# (0) Gentoo Linux (vmlinuz-3.8.1) (nouveau driver)
menuentry "Gentoo Linux (vmlinuz-3.8.1) (nouveau driver)" {
   linux /vmlinuz-3.8.1 root=UUID=6540fc3c-d0cf-4301-b5c5-e4e8cfb20700 rootfstype=ext4 quiet splash nouveau init=/bin/systemd
   initrd /initramfs-generic.img
}


- Pour booter avec nvidia rajoutez nomodeset à la ligne de commande (ça désactivera nouveau) et si vous voulez vesafb, utilisez set gfxpayload=<resolution> dans grub2 (vga=xxx n'est plus supporté) ou référez vous à la documentation de votre bootloader.
Code:

# (1) Gentoo Linux (vmlinuz-3.8.1) (nvidia-driver)
menuentry "Gentoo Linux (vmlinuz-3.8.1) (nvidia-driver)" {
   set gfxpayload=1920x1200-32
   linux /vmlinuz-3.8.1 root=UUID=6540fc3c-d0cf-4301-b5c5-e4e8cfb20700 rootfstype=ext4 quiet splash nomodeset nvidia init=/bin/systemd
   initrd /initramfs-generic.img
}


Bon comme nouveau est activé même dans le noyau nvidia les scripts qu'on trouves plus haut dans ce topic ne marchent plus, j'en ai fait un nouveau qui cherche "nvidia" ou "nouveau" dans la ligne de commande du noyau et active l’implémentation correspondante :
Code:

#!/bin/sh

set_x11_drv() {
   local _drv=$1
   
   ln -snf ../xorg-${_drv}.conf /etc/X11/xorg.conf.d/99-device.conf
}

set_gl_impl() {
   local _impl=$1
   local _curr=`eselect opengl show`

   [ ! $_curr = $_impl ] && eselect opengl set $_impl >/dev/null 2>&1   
}

x11_drv="nouveau"
gl_impl="xorg-x11"

found=0

for i in `cat /proc/cmdline` ; do
   case $i in
      nouveau)
         x11_drv="nouveau"
         gl_impl="xorg-x11"
         found=1
         ;;         
      nvidia)
         x11_drv="nvidia"
         gl_impl="nvidia"
         found=1
         ;;
   esac
done

[ $found -eq 0 ] && echo "no driver specified in kernel cmdline, using default"
   
echo "configure system to use $x11_drv driver"

set_x11_drv $x11_drv
set_gl_impl $gl_impl

exit 0


Bon par contre c'est pas un rc-script faudra donc en ajouter un (ou un service systemd) pour l’exécuter à chaque boot.
Il faut toujours un /etc/X11/xorg-nouveau.conf et un /etc/X11/xorg-nvidia.conf (voir premier post du topic)
Aussi je change pas l’implémentation d'OpenCL ou vdpau pour des raisons de temps de démarrage, mais vous pouvez le rajouter.

J'ai fait une version C (pour gagner 0,01s à chaque boot :lol:), ça compile avec gcc -std=gnu99 -O3 -Wall
Code:

#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#define SUCCESS 0
#define ERROR   1

int set_x11_drv(const char *drv)
{
   const char fmt[] = "/etc/X11/xorg-%s.conf";
   const char dst[] = "/etc/X11/xorg.conf.d/99-device.conf";

   char src[sizeof(fmt) + strlen(drv) + 1];

   snprintf(src, sizeof(src), fmt, drv);

   /* first try to unlink dst if exist */
   unlink(dst);

   /* make new symlink */
   printf("Symlink %s to %s\n", src, dst);
   
   return symlink(src, dst);
}

int get_gl_impl(char *buffer, size_t size)
{
   const char cmd[] = "eselect opengl show";

   FILE *pipe = NULL;


   pipe = popen(cmd, "r");
   if(!pipe) {
      fprintf(stderr, "ERROR: Failed to execute %s", cmd);
      return ERROR;
   }
   
   if(!fgets(buffer, size, pipe)) {
      pclose(pipe);
      return ERROR;
   }

   /* remove new line */
   buffer[strcspn(buffer, "\n")] = '\0';

   return pclose(pipe);
}

int set_gl_impl(const char *impl)
{
   const char fmt[] = "eselect opengl set %s &>/dev/null 2>&1";

   char cmd[sizeof(fmt) + strlen(impl) + 1];
   char curr[10];

   get_gl_impl(curr, sizeof(curr));

   /* switch implementation if needed */
   if(strcmp(impl, curr) == 0 ){
      return SUCCESS;
   }

   printf("Switch to %s OpenGL implementation\n", impl);
   snprintf(cmd, sizeof(cmd), fmt, impl);

   return system(cmd);
}

int main(int argc, char **argv)
{
   char *x11_drv = "nouveau";
   char *gl_impl = "xorg-x11";

   FILE *fhandle = NULL;
   char *fbuffer = NULL;

   int rcode = 0;
   int found = 0;

   fhandle = fopen("/proc/cmdline", "r");

   if(fhandle == NULL) {
      perror("ERROR: Unable to open /proc/cmdline");
   }
   else {
      while(fscanf(fhandle, "%ms", &fbuffer) == 1) {
         if(strcmp(fbuffer, "nouveau") == 0) {
            x11_drv = "nouveau";
            gl_impl = "xorg-x11";
            found = 1;
         } else if(strcmp(fbuffer, "nvidia") == 0){
            x11_drv = "nvidia";
            gl_impl = "nvidia";
            found = 1;
         }
         free(fbuffer);
      }
      fclose(fhandle);
   }

   if(found == 0) {
      printf("No driver specified in kernel cmdline, using default\n");
   }

   printf("Configure system to use %s X11 video driver\n", x11_drv);

   if(set_x11_drv(x11_drv) != SUCCESS) {
      perror("ERROR: Unable to set X11 video driver");
      rcode = 1;
   }

   if(set_gl_impl(gl_impl) != SUCCESS) {
      fprintf(stderr, "ERROR: Unable to switch OpenGL implementation\n");
      rcode = 1;   
   }

   return rcode;
}




Perso je suis très soulagé de n'avoir, enfin, plus besoin de maintenir deux noyaux avec des options différentes (pour nouveau et nvidia)
Back to top
View user's profile Send private message
netfab
Veteran
Veteran


Joined: 03 Mar 2005
Posts: 1887
Location: 127.0.0.1

PostPosted: Sun Mar 03, 2013 12:03 pm    Post subject: Reply with quote

GentooUser@Clubic wrote:
Bon si ça intéresse toujours du monde y'a une nouvelle recette maintenant, avec un seul noyau :D

Perso je suis très soulagé de n'avoir, enfin, plus besoin de maintenir deux noyaux avec des options différentes (pour nouveau et nvidia)


Je suis justement en train de concevoir une nouvelle procédure pour n'avoir qu'un seul noyau, je viens ici pour revoir un truc, et je découvre ton post :lol:

GentooUser@Clubic wrote:
- Activez vesafb dans le noyau, si vous voulez profiter du framebuffer avec les drivers nvidia (pas uvesafb, j'ai pas testé mais c’est marqué incompatible)

J'utilise justement uvesafb, je vais voir pour faire avec :)

En revanche, ce que je cherche à faire, c'est de pouvoir switcher entre nvidia et nouveau sans avoir à rebooter. Je donnerai des nouvelles si j'y parviens.
Back to top
View user's profile Send private message
GentooUser@Clubic
l33t
l33t


Joined: 01 Nov 2004
Posts: 829

PostPosted: Sun Mar 03, 2013 3:47 pm    Post subject: Reply with quote

uvesafb en dur en tout cas je vient de tester, ça marche pas, il se charge inconditionnellement et empêche nouveau de se lancer, même avec video=none. Après en module ça doit pouvoir être jouable avec modprobe.blacklist=.

Pour switcher juste en relançant X j'ai vu un tuto pour Ubuntu y'a quelques temps, faut compiler nouveau en module et jouer avec modprobe -r, perso je suis pas intéressé quitte à relancer X, avec systemd, kexec et un SSD autant relancer le système.
Back to top
View user's profile Send private message
netfab
Veteran
Veteran


Joined: 03 Mar 2005
Posts: 1887
Location: 127.0.0.1

PostPosted: Mon Mar 04, 2013 7:00 pm    Post subject: Reply with quote

GentooUser@Clubic wrote:
uvesafb en dur en tout cas je vient de tester, ça marche pas, il se charge inconditionnellement et empêche nouveau de se lancer, même avec video=none. Après en module ça doit pouvoir être jouable avec modprobe.blacklist=.

Le paramètre pour désactiver uvesafb sur la ligne de commande du kernel est le suivant : video=uvesafb:off

GentooUser@Clubic wrote:

Pour switcher juste en relançant X j'ai vu un tuto pour Ubuntu y'a quelques temps, faut compiler nouveau en module et jouer avec modprobe -r


Bon, j'ai effectué diverses expériences. J'arrive sans problème à passer de nouveau/kms à nvidia/uvesafb, mais lors de l'opération inverse, çà coince.
En fait, une fois que le pilote nvidia a été chargé puis déchargé, plus moyen de relancer nouveau, çà se termine invariablement par :
Code:

nouveau: probe of 0000:01:00.0 failed with error -16

Et à partir de là, si j'essaie de persévérer en jouant à l'apprenti-sorcier, au bout d'un moment l'écran passe au noir (plus de signal) et les ventilos de la carte graphique se mettent à turbiner au max :lol:
Alors pour le moment je me contenterai d'un reboot pour passer de nvidia/uvesafb vers nouveau/kms et vice-versa: en m'inspirant de ta technique et de ton code ci-dessus, j'ai recompilé mon kernel avec les options adéquat et réécrit le service à lancer, çà fonctionne parfaitement, je posterai tout çà un peu plus tard et en profiterai pour éditer le premier post du topic.
Back to top
View user's profile Send private message
GentooUser@Clubic
l33t
l33t


Joined: 01 Nov 2004
Posts: 829

PostPosted: Fri Mar 29, 2013 10:12 pm    Post subject: Reply with quote

netfab wrote:

Le paramètre pour désactiver uvesafb sur la ligne de commande du kernel est le suivant : video=uvesafb:off


Merci ! Je suis passé de Grub à Syslinux et n'ayant pas trouver comment passer le "gfxpayload" au noyau avec Syslinux j'en suis revenu à uvesab.
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index French All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum