logo AlexBio's Blog /dev/random

Linux 2.6.31 + RT + nVidia = Fail

Ieri pomeriggio mi sono messo a ricompilare il kernel Linux (ultima versione stabile ovvero 2.6.31) con la patch real-time di Ingo Molnar. Solitamente aspetto che i sorgenti siano disponibili nei repo di Debian con realativa patch ma questa volta non avevo voglia di attendere.

Compilato alla Debian way senza nessun problema, e felice come una pasqua mi apprestavo ad installare i driver nVidia… ed è proprio a questo punto che sono iniziati i problemi.

Primo tentativo usando module-assistant e il pacchetto nvidia-kernel-source (185.18)  da Sid… Fallito.

Secondo tentativo usando l’installer ufficiale nVidia (sempre 185.18)… Fallito.

Senza perdermi d’animo faccio un terzo tentativo usando l’installer nVidia ancora in beta (versione 192.32) ma anche questo fallisce.

A questo punto, insospettito, vado a guardare il log dell’installazione. L’errore riguardava una certa funzione init_MUTEX evidentemente modificata dalla patch RT. Cercando un pò su internet è saltato fuori che nell’ultima versione del kernel la patch non dichiarava più la suddetta funzione, rispetto alla precedente ovvero quella per la versione 2.6.29.

Continuando a cercare ho trovato anche un’ottima patch per risolvere il problema… vediamo ora come installarla.

La patch è la seguente:

diff -Naur NVIDIA-Linux-x86-190.32-orig/usr/src/nv/nv-linux.h NVIDIA-Linux-x86-190.32/usr/src/nv/nv-linux.h
--- NVIDIA-Linux-x86-190.32-orig/usr/src/nv/nv-linux.h	2009-09-02 11:54:49.000000000 +0100
+++ NVIDIA-Linux-x86-190.32/usr/src/nv/nv-linux.h	2009-09-17 21:05:45.000000000 +0100
@@ -742,20 +742,28 @@
 #define nv_down(lock)                   down(&lock)
 #define nv_up(lock)                     up(&lock)
 
+#if defined(CONFIG_PREEMPT_RT) && !defined(init_MUTEX)
+#  define nv_spin_lock_init(lock)              atomic_spin_lock_init(lock)
+#  define nv_spin_lock_irqsave(lock, irq)      atomic_spin_lock_irqsave(lock, irq)
+#  define nv_spin_unlock_irqrestore(lock, irq) atomic_spin_unlock_irqrestore(lock, irq)
+#else
+#  define nv_spin_lock_init(lock)              spin_lock_init(lock)
+#  define nv_spin_lock_irqsave(lock, irq)      spin_lock_irqsave(lock, irq)
+#  define nv_spin_unlock_irqrestore(lock, irq) spin_unlock_irqrestore(lock, irq)
+#endif
+
 #if defined(CONFIG_PREEMPT_RT)
-#define NV_INIT_MUTEX(mutex) init_MUTEX(mutex)
+#  if defined(init_MUTEX)
+#    define nv_spinlock_t raw_spinlock_t
+#  else
+#    define nv_spinlock_t atomic_spinlock_t
+#  endif
 #else
-#if !defined(__SEMAPHORE_INITIALIZER) && defined(__COMPAT_SEMAPHORE_INITIALIZER)
-#define __SEMAPHORE_INITIALIZER __COMPAT_SEMAPHORE_INITIALIZER
-#endif
-#define NV_INIT_MUTEX(mutex)                       \
-    {                                              \
-        struct semaphore __mutex =                 \
-            __SEMAPHORE_INITIALIZER(*(mutex), 1);  \
-        *(mutex) = __mutex;                        \
-    }
+#  define nv_spinlock_t   spinlock_t
 #endif
 
+#define NV_INIT_MUTEX(mutex) sema_init(mutex, 1)
+
 #if defined (KERNEL_2_4)
 #  define NV_IS_SUSER()                 suser()
 #  define NV_PCI_DEVICE_NAME(dev)       ((dev)->name)
diff -Naur NVIDIA-Linux-x86-190.32-orig/usr/src/nv/os-interface.c NVIDIA-Linux-x86-190.32/usr/src/nv/os-interface.c
--- NVIDIA-Linux-x86-190.32-orig/usr/src/nv/os-interface.c	2009-09-02 11:54:48.000000000 +0100
+++ NVIDIA-Linux-x86-190.32/usr/src/nv/os-interface.c	2009-09-17 21:05:45.000000000 +0100
@@ -108,11 +108,7 @@
 {
     nv_stack_t        *sp;
     struct completion  completion;
-#if defined(CONFIG_PREEMPT_RT)
-    raw_spinlock_t     lock;
-#else
-    spinlock_t         lock;
-#endif
+    nv_spinlock_t      lock;
     S032               count;
 } os_sema_t;
 
@@ -148,7 +144,7 @@
     os_sema = (os_sema_t *)*ppSema;
     os_sema->sp = sp;
     init_completion(&os_sema->completion);
-    spin_lock_init(&os_sema->lock);
+    nv_spin_lock_init(&os_sema->lock);
     os_sema->count = 1;
 
     if (nv_os_smp_barrier_init())
@@ -199,18 +195,18 @@
     os_sema_t *os_sema = (os_sema_t *)pSema;
     unsigned long old_irq;
 
-    spin_lock_irqsave(&os_sema->lock, old_irq);
+    nv_spin_lock_irqsave(&os_sema->lock, old_irq);
     if (os_sema->count <= 0)
     {
         os_sema->count--;
-        spin_unlock_irqrestore(&os_sema->lock, old_irq);
+        nv_spin_unlock_irqrestore(&os_sema->lock, old_irq);
         wait_for_completion(&os_sema->completion);
     }
     else
     {
         os_sema->count--;
         rm_disable_interrupts(os_sema->sp);
-        spin_unlock_irqrestore(&os_sema->lock, old_irq);
+        nv_spin_unlock_irqrestore(&os_sema->lock, old_irq);
     }
 
     return RM_OK;
@@ -233,17 +229,17 @@
     os_sema_t *os_sema = (os_sema_t *)pSema;
     unsigned long old_irq;
 
-    spin_lock_irqsave(&os_sema->lock, old_irq);
+    nv_spin_lock_irqsave(&os_sema->lock, old_irq);
     if (os_sema->count <= 0)
     {
-        spin_unlock_irqrestore(&os_sema->lock, old_irq);
+        nv_spin_unlock_irqrestore(&os_sema->lock, old_irq);
         return RM_ERROR;
     }
     else
     {
         os_sema->count--;
         rm_disable_interrupts(os_sema->sp);
-        spin_unlock_irqrestore(&os_sema->lock, old_irq);
+        nv_spin_unlock_irqrestore(&os_sema->lock, old_irq);
         return RM_OK;
     }
 
@@ -267,7 +263,7 @@
     unsigned long old_irq;
     BOOL doWakeup;
 
-    spin_lock_irqsave(&os_sema->lock, old_irq);
+    nv_spin_lock_irqsave(&os_sema->lock, old_irq);
     if (os_sema->count < 0)
     {
         doWakeup = TRUE;
@@ -278,7 +274,7 @@
         rm_enable_interrupts(os_sema->sp);
     }
     os_sema->count++;
-    spin_unlock_irqrestore(&os_sema->lock, old_irq);
+    nv_spin_unlock_irqrestore(&os_sema->lock, old_irq);
 
     if (doWakeup)
         complete(&os_sema->completion);
@@ -1383,7 +1379,7 @@
     unsigned long oldIrql;
 
     os_sema = (os_sema_t *) pSema;
-    spin_lock_irqsave(&os_sema->lock, oldIrql);
+    nv_spin_lock_irqsave(&os_sema->lock, oldIrql);
 
     return oldIrql;
 }
@@ -1394,7 +1390,7 @@
     unsigned long old_irq = (unsigned long) oldIrql;
 
     os_sema = (os_sema_t *) pSema;
-    spin_unlock_irqrestore(&os_sema->lock, old_irq);
+    nv_spin_unlock_irqrestore(&os_sema->lock, old_irq);
 }
 
 RM_STATUS NV_API_CALL os_get_address_space_info(

Si riferisce alla versione beta dei driver (192.32) quindi è necessario scaricarli dal sito ufficiale (ATTENZIONE: come già detto è solo una versione beta… maneggiare con cura ;) ).

Il secondo passo è quello di estrarre i sorgenti, per fare ciò utilizzare l’opzione ‘-x’:

$ sh NVIDIA-Linux-x86-190.32-pkg1.run -x

Che dovrebbe aver creato una cartella omonima (senza il .run). Ora creiamo una copia (non si sa mai):

$ cp -r NVIDIA-Linux-x86-190.32-pkg1 NVIDIA-Linux-x86-190.32-orig

Nel mio caso ho salvato la suddetta patch come ‘patch-2.6.31-nvidia-192.32-rt.patch’ nella stessa cartella di quella estratta prima (es. se ho estratto la cartella dei driver in ‘Downloads/NVIDIA-Linux-x86-190.32-orig’ il percorso della patch dovrà essere ‘Downloads/patch-2.6.31-nvidia-192.32-rt.patch’).

L’ultimo passo è quello di applicare la patch (alla vecchia maniera):

$ cat patch-2.6.31-nvidia-192.32-rt.patch | patch -p0

Il cui output dovrebbe essere qualcosa tipo:

patching file NVIDIA-Linux-x86-190.32-orig/usr/src/nv/nv-linux.h
patching file NVIDIA-Linux-x86-190.32-orig/usr/src/nv/os-interface.c

Se così non fosse, significherebbe che avete sbagliato qualcosa, perciò ripetete il procedimento da capo.

Ed ora possiamo tranquillamente installare i driver (dopo aver terminato Xorg):

$ sudo NVIDIA-Linux-x86-190.32-orig/nvidia-installer

Questo è tutto, dopo aver installato i driver è ovviamente necessario configurare Xorg, ma questa è un’altra storia, su interenet potete trovare pagine e pagine a riguardo.


No Comments Yet


There are no comments yet. You could be the first!

Leave a Comment

Manipolare file audio con SoX Plugin VST su Linux con DSSI-VST


Spread Firefox Affiliate Button