# Calculate format=diff pkg(sys-kernel/calculate-sources)=>5.4,5.5&&merge(x11-drivers/nvidia-drivers)=>340.107,340.108
diff --git a/kernel/conftest.sh b/kernel/conftest.sh
index 64d75a1..6f9bc3b 100755
--- a/kernel/conftest.sh
+++ b/kernel/conftest.sh
@@ -264,6 +264,23 @@ build_cflags() {
     if [ -n "$BUILD_PARAMS" ]; then
         CFLAGS="$CFLAGS -D$BUILD_PARAMS"
     fi
+
+    # Check if gcc supports asm goto and set CC_HAVE_ASM_GOTO if it does.
+    # Older kernels perform this check and set this flag in Kbuild, and since
+    # conftest.sh runs outside of Kbuild it ends up building without this flag.
+    # Starting with commit e9666d10a5677a494260d60d1fa0b73cc7646eb3 this test
+    # is done within Kconfig, and the preprocessor flag is no longer needed.
+
+    GCC_GOTO_SH="$SOURCES/build/gcc-goto.sh"
+
+    if [ -f "$GCC_GOTO_SH" ]; then
+        # Newer versions of gcc-goto.sh don't print anything on success, but
+        # this is okay, since it's no longer necessary to set CC_HAVE_ASM_GOTO
+        # based on the output of those versions of gcc-goto.sh.
+        if [ `/bin/sh "$GCC_GOTO_SH" "$CC"` = "y" ]; then
+            CFLAGS="$CFLAGS -DCC_HAVE_ASM_GOTO"
+        fi
+    fi
 }
 
 CONFTEST_PREAMBLE="#include \"conftest.h\"
@@ -1520,6 +1537,35 @@ compile_test() {
             compile_check_conftest "$CODE" "NV_DRM_AVAILABLE" "" "generic"
         ;;
 
+        drm_driver_prime_flag_present)
+            #
+            # Determine whether driver feature flag DRIVER_PRIME is present.
+            #
+            # The DRIVER_PRIME flag was added by commit 3248877ea179 (drm:
+            # base prime/dma-buf support (v5)) in v3.4 (2011-11-25) and is
+            # removed by commit 0424fdaf883a (drm/prime: Actually remove
+            # DRIVER_PRIME everywhere) on 2019-06-17.
+            #
+            # DRIVER_PRIME definition moved from drmP.h to drm_drv.h by
+            # commit 85e634bce01a (drm: Extract drm_drv.h) in v4.10
+            # (2016-11-14).
+            #
+            # DRIVER_PRIME define is changed to enum value by commit
+            # 0e2a933b02c9 (drm: Switch DRIVER_ flags to an enum) in v5.1
+            # (2019-01-29).
+            #
+            CODE="
+            #include <drm/drmP.h>
+            #if defined(NV_DRM_DRM_DRV_H_PRESENT)
+            #include <drm/drm_drv.h>
+            #endif
+            unsigned int drm_driver_prime_flag_present_conftest(void) {
+                return DRIVER_PRIME;
+            }"
+
+            compile_check_conftest "$CODE" "NV_DRM_DRIVER_PRIME_FLAG_PRESENT" "" "types"
+        ;;
+
         proc_create_data)
             #
             # Determine if the proc_create_data() function is present.
diff --git a/kernel/nv-drm.c b/kernel/nv-drm.c
index 0eb72e4..78664d5 100644
--- a/kernel/nv-drm.c
+++ b/kernel/nv-drm.c
@@ -146,11 +146,14 @@ static const struct file_operations nv_drm_fops = {
 };
 
 static struct drm_driver nv_drm_driver = {
-#if defined(DRIVER_LEGACY)
-    .driver_features = DRIVER_GEM | DRIVER_PRIME | DRIVER_LEGACY,
-#else
-    .driver_features = DRIVER_GEM | DRIVER_PRIME,
+    .driver_features =
+#if defined(NV_DRM_DRIVER_PRIME_FLAG_PRESENT)
+                       DRIVER_PRIME |
+#endif
+#if defined(DRIVER_LEGACY) || LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0)
+                       DRIVER_LEGACY |
 #endif
+                       DRIVER_GEM,
     .load = nv_drm_load,
     .unload = nv_drm_unload,
     .fops = &nv_drm_fops,
@@ -252,7 +255,11 @@ RM_STATUS NV_API_CALL nv_alloc_os_descriptor_handle(
         goto done;
     }
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)
     drm_gem_object_unreference_unlocked(&nv_obj->base);
+#else
+    drm_gem_object_put_unlocked(&nv_obj->base);
+#endif
 
     status = RM_OK;
 
diff --git a/kernel/nv-linux.h b/kernel/nv-linux.h
index 4043bf1..fce074f 100644
--- a/kernel/nv-linux.h
+++ b/kernel/nv-linux.h
@@ -757,11 +757,18 @@ extern nv_spinlock_t km_lock;
                         0, 0, NULL, NULL);                      \
     }
 #elif (NV_KMEM_CACHE_CREATE_ARGUMENT_COUNT == 5)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
+#define NV_KMEM_CACHE_CREATE(kmem_cache, name, type)            \
+    {                                                           \
+        kmem_cache = kmem_cache_create_usercopy(name, sizeof(type), 0, 0, 0, sizeof(type), NULL); \
+    }
+#else
 #define NV_KMEM_CACHE_CREATE(kmem_cache, name, type)            \
     {                                                           \
         kmem_cache = kmem_cache_create(name, sizeof(type),      \
                         0, 0, NULL);                            \
     }
+#endif
 #else
 #error "NV_KMEM_CACHE_CREATE_ARGUMENT_COUNT value unrecognized!"
 #endif
@@ -877,12 +884,21 @@ extern void *nv_stack_t_cache;
         __ret;                                               \
      })
 #elif (NV_SMP_CALL_FUNCTION_ARGUMENT_COUNT == 3)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 3, 0)
 #define NV_SMP_CALL_FUNCTION(func, info, wait)               \
     ({                                                       \
         int __ret = smp_call_function(func, info, wait);     \
         __ret;                                               \
      })
 #else
+#define NV_SMP_CALL_FUNCTION(func, info, wait)               \
+    ({                                                       \
+        int __ret = 0;                                       \
+        smp_call_function(func, info, wait);                 \
+        __ret;                                               \
+     })
+#endif
+#else
 #error "NV_SMP_CALL_FUNCTION_ARGUMENT_COUNT value unrecognized!"
 #endif
 #elif defined(CONFIG_SMP)
@@ -897,12 +913,21 @@ extern void *nv_stack_t_cache;
         __ret;                                         \
      })
 #elif (NV_ON_EACH_CPU_ARGUMENT_COUNT == 3)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 3, 0)
 #define NV_ON_EACH_CPU(func, info, wait)               \
     ({                                                 \
         int __ret = on_each_cpu(func, info, wait);     \
         __ret;                                         \
      })
 #else
+#define NV_ON_EACH_CPU(func, info, wait)               \
+    ({                                                 \
+        int __ret = 0;                                 \
+        on_each_cpu(func, info, wait);                 \
+        __ret;                                         \
+    })
+#endif
+#else
 #error "NV_ON_EACH_CPU_ARGUMENT_COUNT value unrecognized!"
 #endif
 #elif defined(CONFIG_SMP)
diff --git a/kernel/nvidia-modules-common.mk b/kernel/nvidia-modules-common.mk
index 918e8a9..a90b4e8 100644
--- a/kernel/nvidia-modules-common.mk
+++ b/kernel/nvidia-modules-common.mk
@@ -176,7 +176,7 @@ ifndef NV_VERBOSE
 endif
 
 KBUILD_PARAMS += KBUILD_VERBOSE=$(NV_VERBOSE)
-KBUILD_PARAMS += -C $(KERNEL_SOURCES) SUBDIRS=$(PWD)
+KBUILD_PARAMS += -C $(KERNEL_SOURCES) M=$(PWD)
 KBUILD_PARAMS += ARCH=$(ARCH)
 
 #
diff --git a/kernel/os-interface.c b/kernel/os-interface.c
index 7e3d362..26ec234 100644
--- a/kernel/os-interface.c
+++ b/kernel/os-interface.c
@@ -14,6 +14,16 @@
 #include "os-interface.h"
 #include "nv-linux.h"
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
+static inline void do_gettimeofday(struct timeval *tv)
+{
+    struct timespec64 now;
+    ktime_get_real_ts64(&now);
+    tv->tv_sec = now.tv_sec;
+    tv->tv_usec = now.tv_nsec/1000;
+}
+#endif
+
 RM_STATUS NV_API_CALL os_disable_console_access(void)
 {
     NV_ACQUIRE_CONSOLE_SEM();
diff --git a/kernel/uvm/nvidia_uvm_lite.c b/kernel/uvm/nvidia_uvm_lite.c
index 246ed04..da42552 100644
--- a/kernel/uvm/nvidia_uvm_lite.c
+++ b/kernel/uvm/nvidia_uvm_lite.c
@@ -30,6 +30,16 @@
 #include "nvidia_uvm_lite_counters.h"
 #include "ctrl2080mc.h"
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
+static inline void do_gettimeofday(struct timeval *tv)
+{
+    struct timespec64 now;
+    ktime_get_real_ts64(&now);
+    tv->tv_sec = now.tv_sec;
+    tv->tv_usec = now.tv_nsec/1000;
+}
+#endif
+
 //
 // nvidia_uvm_lite.c
 // This file contains code that is specific to the UVM-Lite mode of operation.
