[linux_var] Driver nVidia, kernel >=2.6.13 e sospensioni

Wolf luigi.b a aliceposta.it
Dom 11 Dic 2005 19:48:45 UTC


Alle 10:53, venerdì 9 dicembre 2005, Wolf ha scritto:
> Ieri sera, dopo una lunga battaglia :-D sono riuscito a far andare le
> sospensioni sul mio notebook con i nuovi kernel, infatti c'era una
> incompatibilità tra i driver nVidia e i kernel partendo dai 2.6.13 a causa
> di una modifica dell'implementazione delle sospensioni tramite ACPI negli
> stessi kernel.
> Ieri, dopo molti smadonnamenti e tante glooglate, ho trovato del materiale
> in rete interessante per patchare o i driver o il kernel.
> La mia scelta si è spostata sulla prima opzione, ovvero patchare il driver,
> al proposito sto mettendo assieme alcune cose che ho trovato (tanto per non
> prendermi meriti, sono già delle patch), più che altro per verificare bene
> come funzionano e vedere se alcune parti del codice modificato serva
> realmente allo scopo.
> La mia filosofia in questi tipi di patch è di modificare giusto giusto
> quello che serve e non una riga di codice in più, questo in quanto la mia
> capacità sta al massimo nella modifica di un driver, e non nella scrittura
> da zero!
>
> Sto anche cercando di scrivere la patch in modo tale che il driver patchato
> vada poi bene su tutti i kernel e non soltanto o sui 2.6.13 o superiori o
> sui 2.6.12 o inferiori (o, penso, sui 2.4.x), se ci riesco proporrò poi la
> modifica agli sviluppatori nVidia (e sentirò cosa dicono!!! :-D ).
>
> Purtroppo non riesco ad avere il connubbio "nuovi kernel - ultimo driver
> nVidia", ma questo perchè purtroppo quando esco dalla sospensione (resume)
> mi ritrovo le console virtuali (quelle ottenibili con Ctrl+F1, Ctrl+F2,
> ecc) corrotte, ovvero si vedono 4 piccole console nella parte alta dello
> schermo, ovviamente sono illeggibili! :-S
>
> Per questo sto usando il driver 1.0-7174, l'ultimo driver che non mi dava
> questo problema, mentre l'ultimo è il 1.0-8174, tra l'altro continuerei ad
> usare senza tanti patemi il primo, soltanto che nell'ultimo è stata
> migliorata la funzione del risparmio energetico dello schermo (DPMS), cosa
> che su di un notebook è particolarmente interessante! ;-)
>
> Se a qualcuno interessa questo argomento lo faccia sapere in questo thread.

Mi autoquoto! :-D

Ho finito la mia patch, fa in modo che il driver venga compilato a seconda se 
il kernel caricato è inferiore o superiore al 2.6.13.
In pratica ho preso delle patch esistenti, ho utilizzato il codice che mi 
sembrava valido e ho aggiungo delle istruzioni ad un paio di file per il 
preprocessore che facessero la selezione in base al kernel.

Comunque ho parlato con Zander, che è uno sviluppatore Nvidia, sul loro forum, 
e mi ha indicato una patch che hanno fatto loro che serve a questo scopo.
Io le allego tutte e due in quanto con la loro mi funziona la sospensione su 
RAM, ma mi si blocca il PC se tento di usare quella su disco, con la mia 
funzionano tutte e due le sospensioni, con qualsiasi kernel.
La loro è più complessa (ovviamente!!!).

Un'ultima cosa, le versioni delle patch che posto sono per l'ultimo driver 
Nvidia, il 1.0-8174, però io continuo ad usare il 1.0-7174 per i problemi che 
riportavo nel primo messaggio e che, purtroppo, sono tutt'ora irrisolti.
Le patch si possono comunque adattare ad altre versioni dei driver.

La mia patch è: patch-1.0-8174..... mentre quella Nvidia è NVIDIA_kernel....
Sono tutte e due con l'aggiunta dell'estensione .txt per problemi di allegati.


-- 
bye :-)

Gigi aka Wolf
-------------- parte successiva --------------
diff -ru usr/src/nv/nv.c usr/src/nv-patched/nv.c
--- usr/src/nv/nv.c	2005-11-23 03:22:31.000000000 +0100
+++ usr/src/nv-patched/nv.c	2005-12-10 15:51:47.000000000 +0100
@@ -3851,12 +3851,20 @@
 
     switch (state)
     {
-        case PM_SUSPEND_MEM:
+#ifdef KERNEL_2_6_NEW_ACPI
+		case PM_EVENT_SUSPEND:
+		case PM_EVENT_FREEZE:
+#else
+		case PM_SUSPEND_MEM:
+#endif
             nv_printf(NV_DBG_INFO, "NVRM: ACPI: received suspend event\n");
             status = rm_power_management(nv, 0, NV_PM_ACPI_STANDBY);
             break;
-
+#ifdef KERNEL_2_6_NEW_ACPI
+		case PM_EVENT_ON:
+#else
         case PM_SUSPEND_ON:
+#endif
             nv_printf(NV_DBG_INFO, "NVRM: ACPI: received resume event\n");
             status = rm_power_management(nv, 0, NV_PM_ACPI_RESUME);
             break;
@@ -3888,7 +3896,11 @@
     struct pci_dev *dev
 )
 {
+#ifdef KERNEL_2_6_NEW_ACPI
+    return nv_acpi_event(dev, PM_EVENT_ON);
+#else
     return nv_acpi_event(dev, PM_SUSPEND_ON);
+#endif
 }
 
 #endif
diff -ru usr/src/nv/nv-linux.h usr/src/nv-patched/nv-linux.h
--- usr/src/nv/nv-linux.h	2005-11-23 03:22:31.000000000 +0100
+++ usr/src/nv-patched/nv-linux.h	2005-12-10 15:47:04.000000000 +0100
@@ -31,6 +31,10 @@
 #  error This driver does not support development kernels!
 #endif
 
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 12)
+#define KERNEL_2_6_NEW_ACPI
+#endif
+
 #if defined (CONFIG_SMP) && !defined (__SMP__)
 #define __SMP__
 #endif
-------------- parte successiva --------------
Only in usr/src/nv.1423627: .nv.c.rej.swp
diff -ru usr/src/nv/Makefile.kbuild usr/src/nv.1423627/Makefile.kbuild
--- usr/src/nv/Makefile.kbuild	2005-11-23 03:58:01.000000000 +0100
+++ usr/src/nv.1423627/Makefile.kbuild	2005-12-04 14:56:24.092375500 +0100
@@ -186,6 +186,14 @@
   ifeq ($(shell $(CONFTEST) sysctl_max_map_count), 1)
     EXTRA_CFLAGS += -DNV_SYSCTL_MAX_MAP_COUNT_PRESENT
   endif
+
+  ifeq ($(shell $(CONFTEST) pm_message_t), 1)
+    EXTRA_CFLAGS += -DNV_PM_MESSAGE_T_PRESENT
+  endif
+
+  ifeq ($(shell $(CONFTEST) pci_choose_state), 1)
+    EXTRA_CFLAGS += -DNV_PCI_CHOOSE_STATE_PRESENT
+  endif
 endif
 
 ifeq ($(shell $(CONFTEST) remap_pfn_range), 1)
diff -ru usr/src/nv/conftest.sh usr/src/nv.1423627/conftest.sh
--- usr/src/nv/conftest.sh	2005-11-23 03:58:01.000000000 +0100
+++ usr/src/nv.1423627/conftest.sh	2005-12-04 14:56:24.092375500 +0100
@@ -643,4 +643,47 @@
         fi
     ;;
 
+    pm_message_t)
+        #
+        # Does linux/pm.h declare the pm_message_t type?
+        #
+
+        echo "#include <linux/pm.h>
+        void nv_test_pm_message_t(pm_message_t state) {
+            pm_message_t *p = &state;
+        }" > conftest$$.c
+
+        $CC $CFLAGS -Wno-error -c conftest$$.c > /dev/null 2>&1
+        rm -f conftest$$.c
+
+        if [ -f conftest$$.o ]; then
+            rm -f conftest$$.o
+            echo 1
+        else
+            echo 0
+        fi
+    ;;
+
+    pci_choose_state)
+        #
+        # Determine if pci_choose_state() is present.
+        #
+
+        echo "#include <linux/pci.h>
+        pci_power_t
+        nv_pci_choose_state(struct pci_dev *dev, pm_message_t state) {
+            return pci_choose_state(dev, state);
+        }" > conftest$$.c
+
+        $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
+        rm -f conftest$$.c
+
+        if [ -f conftest$$.o ]; then
+            rm -f conftest$$.o
+            echo 1
+        else
+            echo 0
+        fi
+    ;;
+
 esac
diff -ru usr/src/nv/nv-linux.h usr/src/nv.1423627/nv-linux.h
--- usr/src/nv/nv-linux.h	2005-11-23 03:58:01.000000000 +0100
+++ usr/src/nv.1423627/nv-linux.h	2005-12-04 14:56:24.092375500 +0100
@@ -642,15 +642,49 @@
 #define NV_PRINT_AT(at)
 #endif
 
-// acpi support has been back-ported to the 2.4 kernel, but the 2.4 driver
-// model is not sufficient for full acpi support. it may work in some cases,
-// but not enough for us to officially support this configuration.
-#if defined(CONFIG_ACPI) && defined(KERNEL_2_6)
-#define NV_PM_SUPPORT_ACPI
+/*
+ * On Linux 2.6, we support both APM and ACPI power management. On Linux
+ * 2.4, we support APM, only. ACPI support has been back-ported to the
+ * Linux 2.4 kernel, but the Linux 2.4 driver model is not sufficient for
+ * full ACPI support: it may work with some systems, but not reliably
+ * enough for us to officially support this configuration.
+ *
+ * We support two Linux kernel power managment interfaces: the original
+ * pm_register()/pm_unregister() on Linux 2.4 and the device driver model
+ * backed PCI driver power management callbacks introduced with Linux
+ * 2.6.
+ *
+ * The code below determines which interface to support on this kernel
+ * version, if any; if built for Linux 2.6, it will also determine if the
+ * kernel comes with ACPI or APM power management support.
+ */
+#if defined(KERNEL_2_6) && (defined(CONFIG_APM) || defined(CONFIG_APM_MODULE) || defined(CONFIG_ACPI))
+#define NV_PM_SUPPORT_DEVICE_DRIVER_MODEL
+#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
+#define NV_PM_SUPPORT_NEW_STYLE_APM
+#endif
 #endif
 
-#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
-#define NV_PM_SUPPORT_APM
+/*
+ * On Linux 2.6 kernels >= 2.6.11, the PCI subsystem provides a new 
+ * interface that allows PCI drivers to determine the correct power state
+ * for a given system power state; our suspend/resume callbacks now use
+ * this interface and operate on PCI power state defines.
+ *
+ * Define these new PCI power state #define's here for compatibility with
+ * older Linux 2.6 kernels.
+ */
+#if defined(KERNEL_2_6) && !defined(PCI_D0)
+#define PCI_D0 PM_SUSPEND_ON
+#define PCI_D3hot PM_SUSPEND_MEM
+#endif
+
+#if defined(KERNEL_2_6) && !defined(NV_PM_MESSAGE_T_PRESENT)
+typedef u32 pm_message_t;
+#endif
+
+#if defined(KERNEL_2_4) && (defined(CONFIG_APM) || defined(CONFIG_APM_MODULE))
+#define NV_PM_SUPPORT_OLD_STYLE_APM
 #endif
 
 #ifndef minor
diff -ru usr/src/nv/nv.c usr/src/nv.1423627/nv.c
--- usr/src/nv/nv.c	2005-11-23 03:58:01.000000000 +0100
+++ usr/src/nv.1423627/nv.c	2005-12-04 14:57:13.791481500 +0100
@@ -29,7 +29,7 @@
 
 static nv_linux_state_t nv_linux_devices[NV_MAX_DEVICES];
 
-#if defined(NV_PM_SUPPORT_APM)
+#if defined(NV_PM_SUPPORT_OLD_STYLE_APM)
 static struct pm_dev *apm_nv_dev[NV_MAX_DEVICES] = { 0 };
 #endif
 
@@ -244,8 +244,8 @@
 void          nv_kern_isr_bh(unsigned long);
 irqreturn_t   nv_kern_isr(int, void *, struct pt_regs *);
 void          nv_kern_rc_timer(unsigned long);
-#if defined(NV_PM_SUPPORT_APM)
-int           nv_kern_apm_event(struct pm_dev *dev, pm_request_t rqst, void *data);
+#if defined(NV_PM_SUPPORT_OLD_STYLE_APM)
+static int    nv_kern_apm_event(struct pm_dev *, pm_request_t, void *);
 #endif
 
 static int    nv_kern_read_cardinfo(char *, char **, off_t off, int, int *, void *);
@@ -265,9 +265,10 @@
 unsigned int  nv_kern_ctl_poll(struct file *, poll_table *);
 
 int nv_kern_probe(struct pci_dev *, const struct pci_device_id *);
-#if defined(NV_PM_SUPPORT_ACPI)
-int nv_kern_acpi_standby(struct pci_dev *, u32);
-int nv_kern_acpi_resume(struct pci_dev *);
+
+#if defined(NV_PM_SUPPORT_DEVICE_DRIVER_MODEL)
+static int    nv_kern_suspend(struct pci_dev *, pm_message_t);
+static int    nv_kern_resume(struct pci_dev *);
 #endif
 
 /***
@@ -292,9 +293,9 @@
     .name     = "nvidia",
     .id_table = nv_pci_table,
     .probe    = nv_kern_probe,
-#if defined(NV_PM_SUPPORT_ACPI)
-    .suspend  = nv_kern_acpi_standby,
-    .resume   = nv_kern_acpi_resume,
+#if defined(NV_PM_SUPPORT_DEVICE_DRIVER_MODEL)
+    .suspend  = nv_kern_suspend,
+    .resume   = nv_kern_resume,
 #endif
 };
 
@@ -1299,7 +1300,7 @@
         nv_lock_init_locks(nv_ctl);
     }
 
-#if defined(NV_PM_SUPPORT_APM)
+#if defined(NV_PM_SUPPORT_OLD_STYLE_APM)
     for (i = 0; i < num_nv_devices; i++)
     {
         apm_nv_dev[i] = pm_register(PM_PCI_DEV, PM_SYS_VGA, nv_kern_apm_event);
@@ -1418,7 +1419,7 @@
     if (nv_pte_t_cache != NULL)
         NV_KMEM_CACHE_DESTROY(nv_pte_t_cache);
 
-#if defined(NV_PM_SUPPORT_APM)
+#if defined(NV_PM_SUPPORT_OLD_STYLE_APM)
     for (i = 0; i < num_nv_devices; i++)
         if (apm_nv_dev[i] != NULL) pm_unregister(apm_nv_dev[i]);
 #endif
@@ -1473,10 +1474,10 @@
     inter_module_unregister("nv_linux_devices");
 #endif
 
-#if defined(NV_PM_SUPPORT_APM)
+#if defined(NV_PM_SUPPORT_OLD_STYLE_APM)
     for (i = 0; i < num_nv_devices; i++)
     {
-        pm_unregister(apm_nv_dev[i]);
+        if (apm_nv_dev[i] != NULL) pm_unregister(apm_nv_dev[i]);
     }
 #endif
 
@@ -2429,9 +2430,9 @@
     mod_timer(&nvl->rc_timer, jiffies + HZ);  /* set another timeout in 1 second */
 }
 
-#if defined(NV_PM_SUPPORT_APM)
+#if defined(NV_PM_SUPPORT_OLD_STYLE_APM)
 /* kernel calls us with a power management event */
-int
+static int
 nv_kern_apm_event(
     struct pm_dev *dev,
     pm_request_t rqst,
@@ -2466,7 +2467,6 @@
 
     switch (rqst)
     {
-#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
         case PM_RESUME:
             nv_printf(NV_DBG_INFO, "NVRM: APM: received resume event\n");
             status = rm_power_management(nv, 0, NV_PM_APM_RESUME);
@@ -2476,15 +2476,12 @@
             nv_printf(NV_DBG_INFO, "NVRM: APM: received suspend event\n");
             status = rm_power_management(nv, 0, NV_PM_APM_SUSPEND);
             break;
-#endif
 
-#if defined(KERNEL_2_4)
         // 2.4 kernels sent a PM_SAVE_STATE request when powering down via
         // ACPI. just ignore it and return success so the power down works
         case PM_SAVE_STATE:
             status = RM_OK;
             break;
-#endif
 
         default:
             nv_printf(NV_DBG_WARNINGS, "NVRM: APM: unsupported event: %d\n", rqst);
@@ -2496,7 +2493,7 @@
 
     return status;
 }
-#endif
+#endif /* defined(NV_PM_SUPPORT_OLD_STYLE_APM) */
 
 /*
 ** nv_kern_ctl_open
@@ -3739,6 +3736,7 @@
     nvl = &nv_linux_devices[num_nv_devices];
     nv  = NV_STATE_PTR(nvl);
 
+    pci_set_drvdata(dev, (void *)nvl);
     nvl->dev          = dev;
     nv->vendor_id     = dev->vendor;
     nv->device_id     = dev->device;
@@ -3816,11 +3814,10 @@
 #endif
 }
 
-#if defined(NV_PM_SUPPORT_ACPI)
+#if defined(NV_PM_SUPPORT_DEVICE_DRIVER_MODEL)
 
-int
-nv_acpi_event
-(
+static int
+nv_power_management(
     struct pci_dev *dev, 
     u32 state
 )
@@ -3828,70 +3825,77 @@
     nv_state_t *nv;
     nv_linux_state_t *lnv = NULL;
     int status = RM_OK;
-    U032 i;
-
-    nv_printf(NV_DBG_INFO, "NVRM: nv_acpi_event: %d\n", state);
 
-    for (i = 0; i < num_nv_devices; i++)
-    {
-        if (nv_linux_devices[i].dev == dev)
-        {
-            lnv = &nv_linux_devices[i];
-            break;
-        }
-    }
+    nv_printf(NV_DBG_INFO, "NVRM: nv_power_management: %d\n", state);
+    lnv = pci_get_drvdata(dev);
 
     if ((!lnv) || (lnv->dev != dev))
     {
-        nv_printf(NV_DBG_WARNINGS, "NVRM: ACPI: invalid device!\n");
+        nv_printf(NV_DBG_WARNINGS, "NVRM: PM: invalid device!\n");
         return -1;
     }
 
     nv = NV_STATE_PTR(lnv);
+    nv_verify_pci_config(NV_STATE_PTR(lnv), TRUE);
 
     switch (state)
     {
-        case PM_SUSPEND_MEM:
+#if defined(NV_PM_SUPPORT_NEW_STYLE_APM)
+        case PCI_D3hot:
+            nv_printf(NV_DBG_INFO, "NVRM: APM: received suspend event\n");
+            status = rm_power_management(nv, 0, NV_PM_APM_SUSPEND);
+            break;
+
+        case PCI_D0:
+            nv_printf(NV_DBG_INFO, "NVRM: APM: received resume event\n");
+            status = rm_power_management(nv, 0, NV_PM_APM_RESUME);
+            break;
+#else
+        case PCI_D3hot:
             nv_printf(NV_DBG_INFO, "NVRM: ACPI: received suspend event\n");
             status = rm_power_management(nv, 0, NV_PM_ACPI_STANDBY);
             break;
 
-        case PM_SUSPEND_ON:
+        case PCI_D0:
             nv_printf(NV_DBG_INFO, "NVRM: ACPI: received resume event\n");
             status = rm_power_management(nv, 0, NV_PM_ACPI_RESUME);
             break;
-
+#endif
         default:
-            nv_printf(NV_DBG_WARNINGS, "NVRM: ACPI: unsupported event: %d\n", state);
+            nv_printf(NV_DBG_WARNINGS, "NVRM: PM: unsupported event: %d\n", state);
             return -1;
     }
 
     if (status != RM_OK)
-        nv_printf(NV_DBG_ERRORS, "NVRM: ACPI: failed event: %d\n", state);
+        nv_printf(NV_DBG_ERRORS, "NVRM: PM: failed event: %d\n", state);
 
     return status;
 }
 
-int
-nv_kern_acpi_standby
-(
-    struct pci_dev *dev, 
-    u32 state
+static int nv_kern_suspend(
+    struct pci_dev *dev,
+    pm_message_t state
 )
 {
-    return nv_acpi_event(dev, state);
+    int power_state = -1;
+
+#if !defined(NV_PM_MESSAGE_T_PRESENT)
+    power_state = state;
+#elif defined(NV_PCI_CHOOSE_STATE_PRESENT)
+    power_state = pci_choose_state(dev, state);
+#endif
+
+    return nv_power_management(dev, power_state);
 }
 
-int
-nv_kern_acpi_resume
-(
+static int nv_kern_resume(
     struct pci_dev *dev
 )
 {
-    return nv_acpi_event(dev, PM_SUSPEND_ON);
+    return nv_power_management(dev, PCI_D0);
 }
 
-#endif
+#endif /* defined(NV_PM_SUPPORT_DEVICE_DRIVER_MODEL) */
 
 void* NV_API_CALL nv_get_adapter_state(
     U016 bus,


More information about the Talking mailing list