Nvidia driver 340.102 for kernel 4.9, 4.10, 4.11

Материал из support.qbpro.ru

[Источник]

Введение в ситуацию

Линус Торвальдс о качестве драйверов Nvidia










Решение

Патч

--- kernel/nv-linux.h
+++ kernel/nv-linux.h
@@ -2082,6 +2082,8 @@ static inline NvU64 nv_node_end_pfn(int nid)
  *    2016 Dec 14:5b56d49fc31dbb0487e14ead790fc81ca9fb2c99
  */

+#include <linux/version.h>
+
 #if defined(NV_GET_USER_PAGES_REMOTE_PRESENT)
     #if defined(NV_GET_USER_PAGES_HAS_WRITE_AND_FORCE_ARGS)
         #define NV_GET_USER_PAGES           get_user_pages
@@ -2129,8 +2131,13 @@ static inline NvU64 nv_node_end_pfn(int nid)

         #else

+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)
                return get_user_pages_remote(tsk, mm, start, nr_pages, flags,
                                             pages, vmas);
+#else
+               return get_user_pages_remote(tsk, mm, start, nr_pages, flags,
+                                            pages, vmas, NULL);
+#endif

         #endif

--- kernel/nv-pat.c
+++ kernel/nv-pat.c
@@ -203,6 +203,7 @@ void nv_disable_pat_support(void)
 }

 #if defined(NV_ENABLE_PAT_SUPPORT) && defined(NV_ENABLE_HOTPLUG_CPU)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)
 static int
 nvidia_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
 {
@@ -234,6 +235,34 @@ static struct notifier_block nv_hotcpu_nfb = {
     .notifier_call = nvidia_cpu_callback,
     .priority = 0
 };
+#else
+static int nvidia_cpu_online(unsigned int hcpu)
+{
+    unsigned int cpu = get_cpu();
+    if (cpu == hcpu)
+        nv_setup_pat_entries(NULL);
+    else
+        NV_SMP_CALL_FUNCTION(nv_setup_pat_entries, (void *)(long int)hcpu, 1);
+
+    put_cpu();
+
+    return 0;
+}
+
+static int nvidia_cpu_down_prep(unsigned int hcpu)
+{
+    unsigned int cpu = get_cpu();
+    if (cpu == hcpu)
+        nv_restore_pat_entries(NULL);
+    else
+        NV_SMP_CALL_FUNCTION(nv_restore_pat_entries, (void *)(long int)hcpu, 1);
+
+    put_cpu();
+
+    return 0;
+}
+#endif
+
 #endif

 int nv_init_pat_support(nv_stack_t *sp)
@@ -255,7 +284,14 @@ int nv_init_pat_support(nv_stack_t *sp)
 #if defined(NV_ENABLE_PAT_SUPPORT) && defined(NV_ENABLE_HOTPLUG_CPU)
         if (nv_pat_mode == NV_PAT_MODE_BUILTIN)
         {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)
             if (register_hotcpu_notifier(&nv_hotcpu_nfb) != 0)
+#else
+            if (cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
+                                  "gpu/nvidia:online",
+                                  nvidia_cpu_online,
+                                  nvidia_cpu_down_prep) != 0)
+#endif
             {
                 nv_disable_pat_support();
                 nv_printf(NV_DBG_ERRORS,
@@ -280,7 +316,11 @@ void nv_teardown_pat_support(void)
     {
         nv_disable_pat_support();
 #if defined(NV_ENABLE_PAT_SUPPORT) && defined(NV_ENABLE_HOTPLUG_CPU)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)
         unregister_hotcpu_notifier(&nv_hotcpu_nfb);
+#else
+        cpuhp_remove_state_nocalls(CPUHP_AP_ONLINE_DYN);
+#endif
 #endif
     }
 }
--- kernel/uvm/nvidia_uvm_lite.c
+++ kernel/uvm/nvidia_uvm_lite.c
@@ -820,7 +820,11 @@ done:
 #if defined(NV_VM_OPERATIONS_STRUCT_HAS_FAULT)
 int _fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)
     unsigned long vaddr = (unsigned long)vmf->virtual_address;
+#else
+    unsigned long vaddr = (unsigned long)vmf->address;
+#endif
     struct page *page = NULL;
     int retval;

--- kernel/nv-drm.c	2017-03-31 03:42:21.000000000 +0200
+++ kernel/nv-drm.c	2017-04-06 23:53:14.273356795 +0200
@@ -48,7 +48,7 @@
     return -ENODEV;
 }

-static int nv_drm_unload(
+static void nv_drm_unload(
     struct drm_device *dev
 )
 {
@@ -60,7 +60,7 @@
         {
             BUG_ON(nvl->drm != dev);
             nvl->drm = NULL;
-            return 0;
+            return;
         }
     }

@@ -64,7 +64,7 @@
         }
     }

-    return -ENODEV;
+    return;
 }

 static void nv_gem_free(
--- kernel/uvm/nvidia_uvm_linux.h  2017-03-31 03:42:21.000000000 +0200
+++ kernel/uvm/nvidia_uvm_linux.h  2017-04-06 23:53:14.273356795 +0200
@@ -124,6 +124,7 @@
 #include <linux/delay.h>            /* mdelay, udelay                   */

 #include <linux/sched.h>            /* suser(), capable() replacement   */
+#include <linux/sched/signal.h>
 #include <linux/moduleparam.h>      /* module_param()                   */
 #if !defined(NV_VMWARE)
 #include <asm/tlbflush.h>           /* flush_tlb(), flush_tlb_all()     */
@@ -362,17 +363,6 @@
     void address_space_init_once(struct address_space *mapping);
 #endif

-#if !defined(NV_FATAL_SIGNAL_PENDING_PRESENT)
-    static inline int __fatal_signal_pending(struct task_struct *p)
-    {
-        return unlikely(sigismember(&p->pending.signal, SIGKILL));
-    }
-
-    static inline int fatal_signal_pending(struct task_struct *p)
-    {
-        return signal_pending(p) && __fatal_signal_pending(p);
-    }
-#endif

 //
 // Before the current->cred structure was introduced, current->euid,
--- kernel/uvm/nvidia_uvm_lite.c  2017-03-31 03:42:21.000000000 +0200
+++ kernel/uvm/nvidia_uvm_lite.c  2017-04-06 23:53:14.273356795 +0200
@@ -818,7 +818,7 @@
 }

 #if defined(NV_VM_OPERATIONS_STRUCT_HAS_FAULT)
-int _fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+int _fault(struct vm_fault *vmf)
 {
     unsigned long vaddr = (unsigned long)vmf->virtual_address;
     struct page *page = NULL;
@@ -828,7 +828,7 @@
     struct page *page = NULL;
     int retval;

-    retval = _fault_common(vma, vaddr, &page, vmf->flags);
+    retval = _fault_common(NULL, vaddr, &page, vmf->flags);

     vmf->page = page;

@@ -866,7 +866,7 @@
 // it's dealing with anonymous mapping (see handle_pte_fault).
 //
 #if defined(NV_VM_OPERATIONS_STRUCT_HAS_FAULT)
-int _sigbus_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+int _sigbus_fault(struct vm_fault *vmf)
 {
     vmf->page = NULL;
     return VM_FAULT_SIGBUS;
--- kernel/nv-drm.c
+++ kernel/nv-drm.c
@@ -115,7 +115,11 @@ static const struct file_operations nv_drm_fops = {
 };

 static struct drm_driver nv_drm_driver = {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
+    .driver_features = DRIVER_GEM | DRIVER_PRIME | DRIVER_LEGACY,
+#else
     .driver_features = DRIVER_GEM | DRIVER_PRIME,
+#endif
     .load = nv_drm_load,
     .unload = nv_drm_unload,
     .fops = &nv_drm_fops,

Инструкция

For those who would like to immediately begin using Nvidia Driver 340.102 with Linux Kernel 4.11-rcX / 4.11, apply the fully working patch provided here:

  • Name of the patch file is: "nv_patch_340.102_linux_kernel_4.11", see direct links or extract from attached "patch.zip" file below
  • The patch is a cleaned-up combination of 3 individual patches for Linux Kernels 4.9, 4.10, & 4.11
  • I have fully tested the patch and it works well without any issues
  • 100% FULL CREDIT and MANY THANKS for those original, individual patches go out to: Alberto Milone, Michael Marley, & Robert Hooker

Instructions for Applying Patch [nv_patch_340.102_linux_kernel_4.11] to Nvidia Driver Compiler/Installer 340.102 used with Linux Kernel 4.11 in CLI/Terminal:

  1. Download the following NVIDIA Driver Compiler/Installer file from NVIDIA website for Linux: [NVIDIA-Linux-x86_64-340.102.run]
  2. Go into CLI/Terminal, and SU into root(#)
  3. Completely Exit Xorg Server: The command "systemctl isolate multi-user.target" usually followed by "CTL+ALT+[F1 to F6]" will do this
  4. In CLI, go into root then provide execution permissions: "chmod 755 NVIDIA-Linux-x86_64-340.102.run"
  5. Extract the Nvidia Driver Compiler/Installer Contents & Source Files: "./NVIDIA-Linux-x86_64-340.102.run --extract-only"
  6. Copy [cp] Patch File "nv_patch_340.102_linux_kernel_4.11" into "NVIDIA-Linux-x86_64-340.102" directory
  7. Go into [cd] "NVIDIA-Linux-x86_64-340.102" directory where patch file is now located
  8. Apply Patch in that directory: "patch -p0 < nv_patch_340.102_linux_kernel_4.11"
  9. Proceed with NVIDIA Driver Compilation & Installation by running "./nvidia-installer". Important: Make sure the Nouveau Driver is disabled-blacklisted and modeset set to 0 in /etc/modprobe.d with "blacklist nouveau" & "options nouveau modeset=0", and the Initial RAM Disk (initrd) is created prior to compiling, installing & rebooting. Enjoy!

Note: You may wish to test out the patch first by executing a Dry-Run with: "patch --dry-run -p0 < nv_patch_340.102_linux_kernel_4.11"