364.1[2,5] won't compile against latest kernel git tree (patches for 4.6.0-rc3+ included)

There are two separate issues with compiling against latest linux/master tree:

Firstly, VM_FAULT_MINOR was removed from headers, temporary hack is to change it to 0 albeit I didn’t investigate whether this won’t broke something in long turn. Patch:

--- NVIDIA-Linux-x86_64-364.12/kernel/nvidia-uvm/uvm_full_fault_handler.c	2016-03-17 03:59:59.000000000 +0100
+++ NVIDIA-Linux-x86_64-364.12b/kernel/nvidia-uvm/uvm_full_fault_handler.c	2016-03-22 14:52:58.847247949 +0100
@@ -3095,7 +3095,7 @@
         pg = pfn_to_page(cpuPfn);
         UVM_PANIC_ON(!pg);
 
-        ret = VM_FAULT_MINOR;
+        ret = 0;
     }
 
     // Update the gpu state for the given cpu fault only if we have some GPU

diff -ur NVIDIA-Linux-x86_64-364.12/kernel/nvidia-uvm/uvm_lite.c NVIDIA-Linux-x86_64-364.12b/kernel/nvidia-uvm/uvm_lite.c
--- NVIDIA-Linux-x86_64-364.12/kernel/nvidia-uvm/uvm_lite.c	2016-03-17 03:59:59.000000000 +0100
+++ NVIDIA-Linux-x86_64-364.12b/kernel/nvidia-uvm/uvm_lite.c	2016-03-22 14:52:58.847247949 +0100
@@ -1283,7 +1283,7 @@
         // If we already have the page, then we must have earlier copied in the
         // data from the GPU. Therefore, avoid migrating.
         //
-        retValue = VM_FAULT_MINOR;
+        retValue = 0;
     }

Secondly, drm_mode_fb_cmd2 parameter was constified in upstream. Patch:

diff -ur NVIDIA-Linux-x86_64-364.12/kernel/nvidia-drm/nvidia-drm-fb.c NVIDIA-Linux-x86_64-364.12b/kernel/nvidia-drm/nvidia-drm-fb.c
--- NVIDIA-Linux-x86_64-364.12/kernel/nvidia-drm/nvidia-drm-fb.c	2016-03-17 03:57:24.000000000 +0100
+++ NVIDIA-Linux-x86_64-364.12b/kernel/nvidia-drm/nvidia-drm-fb.c	2016-03-26 22:49:05.949366359 +0100
@@ -199,7 +199,8 @@
 struct drm_framebuffer *nvidia_drm_framebuffer_create
 (
     struct drm_device *dev,
-    struct drm_file *file, struct drm_mode_fb_cmd2 *cmd
+    struct drm_file *file,
+    const struct drm_mode_fb_cmd2 *cmd
 )
 {
     return internal_framebuffer_create(dev, file, cmd, 0, 0);
diff -ur NVIDIA-Linux-x86_64-364.12/kernel/nvidia-drm/nvidia-drm-fb.h NVIDIA-Linux-x86_64-364.12b/kernel/nvidia-drm/nvidia-drm-fb.h
--- NVIDIA-Linux-x86_64-364.12/kernel/nvidia-drm/nvidia-drm-fb.h	2016-03-17 03:57:24.000000000 +0100
+++ NVIDIA-Linux-x86_64-364.12b/kernel/nvidia-drm/nvidia-drm-fb.h	2016-03-26 21:48:58.261462832 +0100
@@ -45,7 +45,8 @@
 struct drm_framebuffer *nvidia_drm_framebuffer_create
 (
     struct drm_device *dev,
-    struct drm_file *file, struct drm_mode_fb_cmd2 *cmd
+    struct drm_file *file,
+    const struct drm_mode_fb_cmd2 *cmd
 );
 
 int nvidia_drm_add_nvkms_fb(

As far I can tell nothing broke by these dirty fixes, feel free to test.

Confirm. I’ve built nvidia 364.12 against 4.6-rc1. Everything is good including CUDA computations.

rc2+ renamed page_cache_release() -> put_page();

https://lkml.org/lkml/2016/3/20/141

Patch here:

diff -ur NVIDIA-Linux-x86_64-364.12/kernel/nvidia-uvm/uvm_full_pagetbl_mgmt.c NVIDIA-Linux-x86_64-364.12b/kernel/nvidia-uvm/uvm_full_pagetbl_mgmt.c
--- NVIDIA-Linux-x86_64-364.12/kernel/nvidia-uvm/uvm_full_pagetbl_mgmt.c	2016-03-17 03:59:59.000000000 +0100
+++ NVIDIA-Linux-x86_64-364.12b/kernel/nvidia-uvm/uvm_full_pagetbl_mgmt.c	2016-04-04 23:57:29.510053491 +0200
@@ -2939,7 +2939,7 @@
                     set_page_dirty_lock(tempUserPageArray[i]);
 
             UVM_PANIC_ON(tempUserPageArray[i] == 0);
-            page_cache_release(tempUserPageArray[i]);
+            put_page(tempUserPageArray[i]);
             tempUserPageArray[i] = 0;
         }

diff -ur NVIDIA-Linux-x86_64-364.12/kernel/nvidia/os-mlock.c NVIDIA-Linux-x86_64-364.12b/kernel/nvidia/os-mlock.c
--- NVIDIA-Linux-x86_64-364.12/kernel/nvidia/os-mlock.c	2016-03-17 03:58:29.000000000 +0100
+++ NVIDIA-Linux-x86_64-364.12b/kernel/nvidia/os-mlock.c	2016-04-04 23:56:48.806055480 +0200
@@ -129,7 +129,7 @@
     else if (pinned < page_count)
     {
         for (i = 0; i < pinned; i++)
-            page_cache_release(user_pages[i]);
+            put_page(user_pages[i]);
         os_free_mem(user_pages);
         return NV_ERR_INVALID_ADDRESS;
     }
@@ -156,7 +156,7 @@
     {
         if (write)
             set_page_dirty_lock(user_pages[i]);
-        page_cache_release(user_pages[i]);
+        put_page(user_pages[i]);
     }
 
     os_free_mem(user_pages);

Weird. With rc1 and the patches the driver built just fine, but now on rc2 (drm-intel-nightly, actually), ‘make’ skips compiling entirely and instantly tries to link after the CONFTESTs, which fails accordingly. Does anyone else have this?

From make -n (abbreviated), prior to the “set” lines everything is the same as with 4.5:

cat /tmp/build/src/NVIDIA-Linux-x86_64-364.12-no-compat32/kernel-4.6.0-1-ck/conftest/compile-tests/dom0_kernel_present.h …
set -e;  echo '  SYMLINK /tmp/build/src/NVIDIA-Linux-x86_64-364.12-no-compat32/kernel-4.6.0-1-ck/nvidia/nv-kernel.o'; …
set -e;  echo '  LD [M]  /tmp/build/src/NVIDIA-Linux-x86_64-364.12-no-compat32/kernel-4.6.0-1-ck/nvidia.o'; ld -m elf_x86_64   -r -o /tmp/build/src/NVIDIA-Linux-x86_64-364.12-no-compat32/kernel-4.6.0-1-ck/nvidia.o /tmp/build/src/NVIDIA-Linux-x86_64-364.12-no-compat32/kernel-4.6.0-1-ck/nvidia/nv-frontend.o …

Could somebody who’s trying rc2 please report whether they can still build the module or get the same failure?

I’m at my wit’s end. Searched make -n, NV_VERBOSE=1 and strace for cues, nothing. Disabled ccache, tried to have the kernel filed under a different path, nothing.

I’m building against current rc2+ just fine with patches I posted before.

Your log looks pretty weird, especially the “kernel-4.6.0-1-ck” part which sounds to me like you are building against con-kolivas tree (albeit to my best knowledge ck patchsets have little to do with drm, merely scheduler patches).

Thanks for the verify. So it’s a particular problem, ugh. (My kernel build script was indeed originally for con-kolivas, I just kept the name.)

I honestly don’t know what’s going on. There’s no error before the failure apparent anywhere, make just jumps to linking right away and that’s it.

The second and third patch are needed on the latest 364.15 driver as well

The VM_FAULT_MINOR issue was fixed

// We used to return VM_FAULT_MINOR here. However, that was deprecated
        // in the kernel, and the new guideline is to return 0 in case of a
        // minor fault. The VM_FAULT_MINOR symbol itself was removed in
        // March, 2016 with commit 0e8fb9312fbaf1a687dd731b04d8ab3121c4ff5a.
        ret = 0;

const struct drm_mode_fb_cmd2 *cmd still needed

This was actually merged after rc2 was released so will be needed for rc3+
(You confused me haha, I built fine w/o it for rc2. Thanks in advance for the patch though)

Alright, I’m getting closer to the issue. It’s got something to do with my custom kernel config, since if I use the (unofficial) full one from Arch’s linux-git, the driver compiles as usual. The driver script’s conftests just don’t find it.

Anyway, here’s the full patch I’m using at the moment, which has one or two more diffs than those above:

I fixed all remaining warnings since a few turned fatal with drm-next.

edit: Is there a concise list of which kernel options the driver requires? I’m seeing bits and pieces of the net, but nothing complete nor official. Asking since I can’t find anything off / missing in mine.

edit2: Alright, I’ve isolated it to /usr/lib/modules/4.6.0-1-ck/build/include/config/auto.conf.

edit3: Finally. It’s the new CONFIG_STACK_VALIDATION line. Doesn’t matter what its value is, as long as its in auto.conf, the driver won’t be compiled. Removing it makes the compile finish (and function) normally, afterwards it doesn’t matter if it’s restored.

My bad, should have said “rc2+”, I pulled rc2 along with other stuff that was merged post rc2.

Works beautifully on 4.6.0-rc3, thanks.

Any chance of re-posting that patch? The pastebin has expired.

For convenience I’ve compiled the patch together for ease of use

364.12 (Have work against 4.6.0-rc2-1/2 and -rc2-3/4)
https://dav.ioda.net/index.php/s/8Coy2ISON1hTipB/download

364.15 (Tested against 4.6.0-rc2-3/4)
https://dav.ioda.net/index.php/s/eq6F9PFhoeNcpYX/download

Have been used for example like this

./NVIDIA-Linux-x86_64-364.15.run -a -no-x-check -k uname -r --apply-patch 364.15-kernel-4.6.patch

then simply applied
./NVIDIA-Linux-x86_64-364.15-custom.run

Work great here under openSUSE Tumbleweed (Xorg 1.18 / kernel 4.6.0 ) on a Dell Precision M7510
(Quadro M2000M and hidpi screen)

Couldn’t get 364.15 to compile on 4.6.0-rc3 on my Gentoo laptop.

Had to add one bit extra to the patch, not sure if it works yet

--- os-mlock.c.orig     2016-04-16 21:00:46.550236535 +0100
+++ os-mlock.c  2016-04-16 21:01:15.691237060 +0100
@@ -129,7 +129,7 @@ NV_STATUS NV_API_CALL os_lock_user_pages
     else if (pinned < page_count)
     {
         for (i = 0; i < pinned; i++)
-            page_cache_release(user_pages[i]);
+            put_page(user_pages[i]);
         os_free_mem(user_pages);
         return NV_ERR_INVALID_ADDRESS;
     }

It’s basically an exact copy of what you did around line 156.

get_user_pages API changed in c12d2da56d0e07d230968ee2305aaa86b93a6832

--- NVIDIA-Linux-x86_64-364.15/kernel/nvidia-uvm/uvm_full_pagetbl_mgmt.c	2016-04-03 05:08:49.000000000 +0200
+++ NVIDIA-Linux-x86_64-364.15b/kernel/nvidia-uvm/uvm_full_pagetbl_mgmt.c	2016-04-17 00:48:05.050300392 +0200
@@ -2909,7 +2909,7 @@
 
         // get userPA for this range
         down_read(&current->mm->mmap_sem);
-        returnVal = get_user_pages(current, current->mm, (unsigned long)(UVM_ALIGN_ADDR(userCopyBuffer, PAGE_SIZE_4K)),
+        returnVal = get_user_pages((unsigned long)(UVM_ALIGN_ADDR(userCopyBuffer, PAGE_SIZE_4K)),
             userPagesReq, 1, 0, tempUserPageArray, NULL);
         up_read(&current->mm->mmap_sem);


--- NVIDIA-Linux-x86_64-364.15/kernel/nvidia-uvm/uvm8_tools.c	2016-04-03 05:08:49.000000000 +0200
+++ NVIDIA-Linux-x86_64-364.15b/kernel/nvidia-uvm/uvm8_tools.c	2016-04-17 00:48:36.801297977 +0200
@@ -158,7 +158,7 @@
     }
 
     down_read(&current->mm->mmap_sem);
-    ret = get_user_pages(current, current->mm, user_va, num_pages, 1, 0, *pages, NULL);
+    ret = get_user_pages(user_va, num_pages, 1, 0, *pages, NULL);
     up_read(&current->mm->mmap_sem);
     if (ret != num_pages) {
         status = NV_ERR_INVALID_ARGUMENT;

--- NVIDIA-Linux-x86_64-364.15/kernel/nvidia-drm/nvidia-drm-linux.c	2016-04-03 05:05:22.000000000 +0200
+++ NVIDIA-Linux-x86_64-364.15b/kernel/nvidia-drm/nvidia-drm-linux.c	2016-04-17 00:49:10.378295423 +0200
@@ -121,8 +121,7 @@
 
     down_read(&mm->mmap_sem);
 
-    pages_pinned = get_user_pages(current, mm,
-                                  address, pages_count, write, force,
+    pages_pinned = get_user_pages(address, pages_count, write, force,
                                   user_pages, NULL);
     up_read(&mm->mmap_sem);

--- NVIDIA-Linux-x86_64-364.15/kernel/nvidia/os-mlock.c	2016-04-03 05:07:03.000000000 +0200
+++ NVIDIA-Linux-x86_64-364.15b/kernel/nvidia/os-mlock.c	2016-04-17 00:46:54.758305738 +0200
@@ -116,7 +116,7 @@
     }
 
     down_read(&mm->mmap_sem);
-    ret = get_user_pages(current, mm, (unsigned long)address,
+    ret = get_user_pages((unsigned long)address,
             page_count, write, force, user_pages, NULL);
     up_read(&mm->mmap_sem);
     pinned = ret;

I’m still getting an error

/tmp/selfgz3413/NVIDIA-Linux-x86_64-364.15-custom/kernel/nvidia-drm/nvidia-drm-drv.c:67:18: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
     .fb_create = nvidia_drm_framebuffer_create,

What is needed to fix it ?

— nvidia-drm-fb.c.orig 2016-04-02 22:35:22.000000000 -0430
+++ nvidia-drm-fb.c 2016-04-06 19:19:06.520502593 -0430
@@ -21,7 +21,7 @@
*/

#include “conftest.h” /* NV_DRM_ATOMIC_MODESET_AVAILABLE */

+#include <linux/version.h>
#if defined(NV_DRM_ATOMIC_MODESET_AVAILABLE)

#include “nvidia-drm-priv.h”
@@ -77,7 +77,12 @@
static struct drm_framebuffer *internal_framebuffer_create
(
struct drm_device *dev,

  • struct drm_file *file, struct drm_mode_fb_cmd2 *cmd,
  • struct drm_file *file,
    +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,5,0)
  • const struct drm_mode_fb_cmd2 *cmd,
    +#else
  • struct drm_mode_fb_cmd2 *cmd,
    +#endif
    uint64_t nvkms_params_ptr,
    uint64_t nvkms_params_size
    )
    @@ -199,7 +204,12 @@
    struct drm_framebuffer *nvidia_drm_framebuffer_create
    (
    struct drm_device *dev,
  • struct drm_file *file, struct drm_mode_fb_cmd2 *cmd
  • struct drm_file *file,
    +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,5,0)
  • const struct drm_mode_fb_cmd2 *cmd
    +#else
  • struct drm_mode_fb_cmd2 *cmd
    +#endif
    )
    {
    return internal_framebuffer_create(dev, file, cmd, 0, 0);

Now, with 4.6-rc4 building is failing again.

/var/lib/dkms/nvidia/364.15/build/nvidia/os-mlock.c: In function ‘os_lock_user_pages’:
./arch/x86/include/asm/current.h:17:17: warning: passing argument 1 of ‘get_user_pages’ makes integer from pointer without a cast [-Wint-conversion]
 #define current get_current()

Hopefully anyone can make a patch.

--- nvidia/os-mlock.c.orig	2016-04-18 19:13:17.893556127 -0430
+++ nvidia/os-mlock.c	2016-04-18 19:13:42.725031536 -0430
@@ -116,7 +116,7 @@
     }
 
     down_read(&mm->mmap_sem);
-    ret = get_user_pages(current, mm, (unsigned long)address,
+    ret = get_user_pages((unsigned long)address,
             page_count, write, force, user_pages, NULL);
     up_read(&mm->mmap_sem);
     pinned = ret;
--- nvidia-drm/nvidia-drm-linux.c.orig	2016-04-18 19:19:00.166109078 -0430
+++ nvidia-drm/nvidia-drm-linux.c	2016-04-18 19:19:32.119720844 -0430
@@ -121,8 +121,7 @@
 
     down_read(&mm->mmap_sem);
 
-    pages_pinned = get_user_pages(current, mm,
-                                  address, pages_count, write, force,
+    pages_pinned = get_user_pages(address, pages_count, write, force,
                                   user_pages, NULL);
     up_read(&mm->mmap_sem);
 
--- nvidia-uvm/uvm8_tools.c.orig	2016-04-18 19:16:41.591456009 -0430
+++ nvidia-uvm/uvm8_tools.c	2016-04-18 19:17:18.443161550 -0430
@@ -158,7 +158,7 @@
     }
 
     down_read(&current->mm->mmap_sem);
-    ret = get_user_pages(current, current->mm, user_va, num_pages, 1, 0, *pages, NULL);
+    ret = get_user_pages(user_va, num_pages, 1, 0, *pages, NULL);
     up_read(&current->mm->mmap_sem);
     if (ret != num_pages) {
         status = NV_ERR_INVALID_ARGUMENT;
--- nvidia-uvm/uvm_full_pagetbl_mgmt.c.orig	2016-04-18 19:15:19.964893234 -0430
+++ nvidia-uvm/uvm_full_pagetbl_mgmt.c	2016-04-18 19:15:49.226453459 -0430
@@ -2909,7 +2909,7 @@
 
         // get userPA for this range
         down_read(&current->mm->mmap_sem);
-        returnVal = get_user_pages(current, current->mm, (unsigned long)(UVM_ALIGN_ADDR(userCopyBuffer, PAGE_SIZE_4K)),
+        returnVal = get_user_pages( (unsigned long)(UVM_ALIGN_ADDR(userCopyBuffer, PAGE_SIZE_4K)),
             userPagesReq, 1, 0, tempUserPageArray, NULL);
         up_read(&current->mm->mmap_sem);

Any chance of another combined patch? :) I can’t get most of these to apply now, probably doing the wrong ones or in the wrong order.