Galère avec les drivers NVidia sous Linux?

Retour à la page Systèmes

Motivation

NVidia met quelques jours (et parfois beaucoup plus) pour publier des versions de ses drivers qui soient compatibles avec les derniers noyaux Linux.

Les adaptations d'une version de noyau à l'autre ne concernent cependant que quelques appels système, que l'on peut adapter manuellement.

Cet article a été entamé le 20/10/2013 sur une distribution Fedora 18 avec un bureau GNOME 3.6.
L'auteur l'a fait (une fois de plus) pour résoudre rapidement son propre problème, et n'exclut nullement qu'il existe des solutions plus élégantes.

Les pistes proposées ici sont directement inspirées des discussions du forum NVidia/Linux (NVIDIA/DevZone/Forums/GPU Unix/Linux)

Prérequis

Afin d'éviter les malentendus, voici ce qui est supposé à propos du lecteur:

Le principe

Prendre un driver de base

Télécharger le driver drvversion.runqui fonctionnait sur le noyau le plus récent: c'est lui que l'on va essayer de patcher.

Puis extraire les sources (eh oui il y a une option pour ça)

% ./drvversion.run -x
% cd drvversion

Suivre les changements de code

On peut utiliser git pour suivre les changements de code (une autre méthode consisterait à ré-extraire les sources ailleurs à partir du .run, puis à faire un diff)

% git init .
% cd kernel/
% git add *.c *.h
% git commit -a

Changer ou Patcher le code

% who -r
         run-level 3  2013-03-10 14:18                   last=3
% cd drvversion
% ./nvidia-installer
% #Si ça marche passer à la section qui suit ...
% #Sinon:
% #  Chercher 'error:' dans /var/log/nvidia-installer.log
% # corriger les erreurs mentionnées dans /var/log/nvidia-installer.log
% # --* patch -p1 <telechargement_forum>
% # --* ou bien bricolage manuel

Archiver le patch

% git commit -a
% git diff <initial> HEAD > mon-patch.txt

Donner un nom raisonnable au patch, comme NVidia_drvversion_noyau.patch

Exemple

Voici ce que j'ai fait pour faire fonctionner le driver 319.17 sur un noyau 3.11.4

Essai naïf

% ./NVIDIA-Linux-x86-319.17.run -x
% cd NVIDIA-Linux-x86-319.17
% ./nvidia-installer

Après échec de l'installation, nvidia-installer.log contient:

NVIDIA-Linux-x86_64-325.08/kernel/nv-i2c.c:252:14: error: void value not ignored as it ought to be

Recherche d'une solution prète à consommer

Une recherche Google sur le message d'erreur envoie rapidement à la page de forum où l'intervenant du 7/2/2013 à 5h36 propose un patch (adapté de 319.23) pour compiler le driver 319.17 sur un noyau 3.10.

nvidia-drivers-linux-3.10.patch.txt

Le noyau 3.10 n'est évidemment pas 3.11.4, mais on s'en rapproche.
On commence donc par essayer d'appliquer le patch:

patch --dry-run -p1 < nvidia-drivers-linux-3.10.patch.txt
patching file kernel/nv-i2c.c
patching file kernel/nv-procfs.c
Hunk #9 FAILED at 424.
1 out of 15 hunks FAILED -- saving rejects to file kernel/nv-procfs.c.rej

Qu'est-ce que ça veut dire?

git commit -a -m 'patch1-fail9'

On édite "à la main" nv-procfs.c selon les indications de nv-procfs.c.rej, puis on contrôle que les modifications n'ont pas été oubliées

% git diff >modifs.txt
% diff modifs.txt nv-procfs.c.rej 
1,5c1,3
< diff --git a/kernel/nv-procfs.c b/kernel/nv-procfs.c
< index 8a16c8d..e754e9f 100644
< --- a/kernel/nv-procfs.c
< +++ b/kernel/nv-procfs.c
< @@ -424,122 +424,81 @@ done:
---
> --- kernel/nv-procfs.c	2013-04-26 00:22:30.000000000 -0400
> +++ kernel/nv-procfs.c	2013-05-22 04:52:45.229495748 -0400
> @@ -424,121 +502,80 @@
47d44
<  
104a102,103
> -
> -    bytes_left = (NV_PROC_WRITE_BUFFER_SIZE - nvfp->off - 1);
107,108d105
< -    bytes_left = (NV_PROC_WRITE_BUFFER_SIZE - nvfp->off - 1);
< -

Il semble vraiment que la différence ne tenait qu'à de malheureux espaces blancs. On peut retenir ce changement:

% git commit -a 'patch1-ok'

Et on reessaye:

% cd drvversion
% ./nvidia-installer

Enfer et damnation! Il y a cette fois-ci une erreur dans os-interface.c, où num_physpages n'est pas défini.

Bricolage manuel

Les patches récents trouvés çà et là sur le net suggèrent que num_physpages doit être remplacé par get_num_physpages() dans nv-linux.h.
On edite donc le fichier manuellement, et on regarde la différence à la fin:

.
% git diff
diff --git a/kernel/nv-linux.h b/kernel/nv-linux.h
index 2055d3e..48105c3 100644
--- a/kernel/nv-linux.h
+++ b/kernel/nv-linux.h
@@ -1025,7 +1025,7 @@ static inline int nv_execute_on_all_cpus(void (*func)(void
 #endif
 
 #if !defined(NV_VMWARE)
-#define NV_NUM_PHYSPAGES                num_physpages
+#define NV_NUM_PHYSPAGES                get_num_physpages()
 #define NV_GET_CURRENT_PROCESS()        current->tgid
 #define NV_IN_ATOMIC()                  in_atomic()
 #define NV_LOCAL_BH_DISABLE()           local_bh_disable()

Le patch final

% cd drvversion
% ./nvidia-installer

Là ça marche (chez moi au moins). Après test, reboot, etc. retour au répertoire des sources pour le patch définitif.

% cd drvversion
% git commit -a -m 'patch-final'
% git diff HEAD^^^ HEAD > ../NVidia_319.17_3.11.4.patch

Dernière modification: 20 octobre 2013