commit 237841e565428e8c8735a8addb3670afbb64075b
Author: Thaison Nguyen <thieson08(a)me.com>
Date: Sun Jun 27 21:09:03 2021 +0200
Fix patch for kernel-5.11.0 (Thanks at Łukasz Wojniłowicz
<lukasz.wojnilowicz(a)gmail.com>)
kernel-5.11.patch | 8636 +++++++++++++++++++++++++++++++++++++++++++++++-
nvidia-340xx-kmod.spec | 6 +-
2 files changed, 8633 insertions(+), 9 deletions(-)
---
diff --git a/kernel-5.11.patch b/kernel-5.11.patch
index 5a24317..c503e7f 100644
--- a/kernel-5.11.patch
+++ b/kernel-5.11.patch
@@ -1,27 +1,8649 @@
+diff -Naur a/kernel/conftest.h b/kernel/conftest.h
+--- a/kernel/conftest.h 1970-01-01 01:00:00.000000000 +0100
++++ b/kernel/conftest.h 2021-06-09 21:37:47.508578460 +0200
+@@ -0,0 +1,11 @@
++#ifndef _CONFTEST_H
++#define _CONFTEST_H
++
++#include "conftest/headers.h"
++#include "conftest/functions.h"
++#include "conftest/generic.h"
++#include "conftest/macros.h"
++#include "conftest/symbols.h"
++#include "conftest/types.h"
++
++#endif
+diff -Naur a/kernel/conftest.sh b/kernel/conftest.sh
+--- a/kernel/conftest.sh 2021-06-09 20:45:03.126250601 +0200
++++ b/kernel/conftest.sh 2021-06-09 21:37:47.510578416 +0200
+@@ -24,7 +24,6 @@
+ OUTPUT=$5
+ XEN_PRESENT=1
+ PREEMPT_RT_PRESENT=0
+-COMPILE_TEST_HEADERS="macros functions symbols types generic headers"
+ KERNEL_ARCH="$ARCH"
+
+ if [ "$ARCH" = "i386" -o "$ARCH" = "x86_64" ];
then
+@@ -35,7 +34,9 @@
+
+ HEADERS_ARCH="$SOURCES/arch/$KERNEL_ARCH/include"
+
+-# VGX_BUILD parameter defined only for VGX builds
++# VGX_BUILD parameter defined only for VGX builds (vGPU Host driver)
++# VGX_KVM_BUILD parameter defined only vGPU builds on KVM hypervisor
++# GRID_BUILD parameter defined only for GRID builds (GRID Guest driver)
+
+ test_xen() {
+ #
+@@ -55,12 +56,13 @@
+
+ append_conftest() {
+ #
+- # Append data from stdin to a temporary conftest/*.h file.
++ # Echo data from stdin: this is a transitional function to make it easier
++ # to port conftests from drivers with parallel conftest generation to
++ # older driver versions
+ #
+- TEMPORARY_HEADER=conftest/$1-$$.h
+
+ while read LINE; do
+- echo ${LINE} >> $TEMPORARY_HEADER
++ echo ${LINE}
+ done
+ }
+
+@@ -81,67 +83,13 @@
+ for file in $@; do
+ local file_define=NV_`echo $file | tr '/.' '_' | tr '-'
'_' | tr 'a-z' 'A-Z'`_PRESENT
+ if [ -f $parent_dir/$file -o -f $OUTPUT/include/$file ]; then
+- echo "#define $file_define" | append_conftest "headers"
++ echo "#define $file_define"
+ else
+- echo "#undef $file_define" | append_conftest "headers"
++ echo "#undef $file_define"
+ fi
+ done
+ }
+
+-compare_files() {
+- #
+- # Compare two files. Return 0 if checksums and sizes match; 1 otherwise.
+- # In case of any errors, assume the files differ, just to be safe.
+- #
+- FILE_1_CKSUM_RESULT=`cksum $1` || return 1
+- FILE_2_CKSUM_RESULT=`cksum $2` || return 1
+-
+- FILE_1_SUM=`echo $FILE_1_CKSUM_RESULT | cut -f 1 -d ' '` || return 1
+- FILE_2_SUM=`echo $FILE_2_CKSUM_RESULT | cut -f 1 -d ' '` || return 1
+- if ! [ $FILE_1_SUM = $FILE_2_SUM ]; then
+- return 1
+- fi
+-
+- FILE_1_SIZE=`echo $FILE_1_CKSUM_RESULT | cut -f 2 -d ' '` || return 1
+- FILE_2_SIZE=`echo $FILE_2_CKSUM_RESULT | cut -f 2 -d ' '` || return 1
+- if ! [ $FILE_1_SIZE = $FILE_2_SIZE ]; then
+- return 1
+- fi
+-
+- return 0
+-}
+-
+-update_conftest() {
+- #
+- # Check for a generated temporary header file generated by append_conftest:
+- # if present, compare against any existing header file of the same type.
+- # Update the header using the temporary one if no existing header is present
+- # or the existing header differs from the newly generated one. Otherwise,
+- # delete the temporary header. If the header is newly generated, then also
+- # regenerate the master conftest.h file.
+- #
+- TEMPORARY_HEADER=conftest/$1-$$.h
+- HEADER=conftest/$1.h
+-
+- if ! [ -f $TEMPORARY_HEADER ]; then
+- return
+- fi
+-
+- if ! [ -f $HEADER ] || ! compare_files $TEMPORARY_HEADER $HEADER; then
+- mv $TEMPORARY_HEADER $HEADER
+-
+- # regenerate conftest.h to include any include existing subheaders
+- rm -f conftest.h
+- for i in $COMPILE_TEST_HEADERS; do
+- if [ -f conftest/$i.h ]; then
+- echo "#include \"conftest/$i.h\"" >>
conftest.h
+- fi
+- done
+- else
+- rm -f $TEMPORARY_HEADER
+- fi
+-}
+-
+ test_headers() {
+ #
+ # Determine which header files (of a set that may or may not be
+@@ -149,12 +97,23 @@
+ #
+ FILES="asm/system.h"
+ FILES="$FILES drm/drmP.h"
++ FILES="$FILES drm/drm_auth.h"
+ FILES="$FILES drm/drm_gem.h"
++ FILES="$FILES drm/drm_crtc.h"
++ FILES="$FILES drm/drm_atomic.h"
++ FILES="$FILES drm/drm_atomic_helper.h"
++ FILES="$FILES drm/drm_encoder.h"
++ FILES="$FILES drm/drm_atomic_uapi.h"
+ FILES="$FILES drm/drm_drv.h"
++ FILES="$FILES drm/drm_framebuffer.h"
++ FILES="$FILES drm/drm_connector.h"
++ FILES="$FILES drm/drm_probe_helper.h"
+ FILES="$FILES drm/drm_prime.h"
++ FILES="$FILES drm/drm_plane.h"
++ FILES="$FILES drm/drm_vblank.h"
+ FILES="$FILES drm/drm_file.h"
+ FILES="$FILES drm/drm_ioctl.h"
+- FILES="$FILES drm/drm_pci.h"
++ FILES="$FILES drm/drm_device.h"
+ FILES="$FILES generated/autoconf.h"
+ FILES="$FILES generated/compile.h"
+ FILES="$FILES generated/utsrelease.h"
+@@ -162,7 +121,6 @@
+ FILES="$FILES linux/kconfig.h"
+ FILES="$FILES linux/screen_info.h"
+ FILES="$FILES linux/semaphore.h"
+- FILES="$FILES linux/nvmap.h"
+ FILES="$FILES linux/printk.h"
+ FILES="$FILES linux/ratelimit.h"
+ FILES="$FILES linux/prio_tree.h"
+@@ -171,28 +129,22 @@
+ FILES="$FILES linux/bug.h"
+ FILES="$FILES linux/sched/signal.h"
+ FILES="$FILES linux/sched/task.h"
++ FILES="$FILES linux/sched/task_stack.h"
+ FILES="$FILES xen/ioemu.h"
+ FILES="$FILES linux/fence.h"
+ FILES="$FILES linux/ktime.h"
+- FILES="$FILES linux/file.h"
++ FILES="$FILES linux/dma-resv.h"
++ FILES="$FILES linux/dma-map-ops.h"
+
+- FILES_ARCH="$FILES_ARCH asm/pgtable.h"
++ # Arch specific headers which need testing
++ FILES_ARCH="asm/book3s/64/hash-64k.h"
+ FILES_ARCH="$FILES_ARCH asm/set_memory.h"
++ FILES_ARCH="$FILES_ARCH asm/powernv.h"
++ FILES_ARCH="$FILES_ARCH asm/tlbflush.h"
++ FILES_ARCH="$FILES_ARCH asm/pgtable_types.h"
+
+ translate_and_find_header_files $HEADERS $FILES
+ translate_and_find_header_files $HEADERS_ARCH $FILES_ARCH
+-
+- update_conftest "headers"
+-}
+-
+-create_skeleton_headers() {
+- mkdir -p conftest
+-
+- for header in $COMPILE_TEST_HEADERS; do
+- if [ ! -f conftest/$header.h ]; then
+- touch conftest/$header.h
+- fi
+- done
+ }
+
+ build_cflags() {
+@@ -203,72 +155,61 @@
+ if [ "$OUTPUT" != "$SOURCES" ]; then
+ OUTPUT_CFLAGS="-I$OUTPUT/include2 -I$OUTPUT/include"
+ if [ -f "$OUTPUT/include/generated/autoconf.h" ]; then
+- AUTOCONF_CFLAGS="-include $OUTPUT/include/generated/autoconf.h"
++ AUTOCONF_FILE="$OUTPUT/include/generated/autoconf.h"
+ else
+- AUTOCONF_CFLAGS="-include $OUTPUT/include/linux/autoconf.h"
++ AUTOCONF_FILE="$OUTPUT/include/linux/autoconf.h"
+ fi
+ else
+ if [ -f "$HEADERS/generated/autoconf.h" ]; then
+- AUTOCONF_CFLAGS="-include $HEADERS/generated/autoconf.h"
++ AUTOCONF_FILE="$HEADERS/generated/autoconf.h"
+ else
+- AUTOCONF_CFLAGS="-include $HEADERS/linux/autoconf.h"
++ AUTOCONF_FILE="$HEADERS/linux/autoconf.h"
+ fi
+ fi
+
+- CFLAGS="$CFLAGS $OUTPUT_CFLAGS -I$HEADERS $AUTOCONF_CFLAGS"
+-
+ test_xen
+
+- if [ "$OUTPUT" != "$SOURCES" ]; then
+- MACH_CFLAGS="-I$HEADERS/asm-$ARCH/mach-default"
+- if [ "$ARCH" = "i386" -o "$ARCH" =
"x86_64" ]; then
+- MACH_CFLAGS="$MACH_CFLAGS -I$HEADERS/asm-x86/mach-default"
+- MACH_CFLAGS="$MACH_CFLAGS
-I$SOURCES/arch/x86/include/asm/mach-default"
+- MACH_CFLAGS="$MACH_CFLAGS -I$HEADERS/arch/x86/include/uapi"
+- elif [ "$ARCH" = "arm" ]; then
+- MACH_CFLAGS="$MACH_CFLAGS -D__LINUX_ARM_ARCH__=7"
+- MACH_CFLAGS="$MACH_CFLAGS -I$SOURCES/arch/arm/mach-tegra/include"
+- MACH_CFLAGS="$MACH_CFLAGS -I$HEADERS/arch/arm/include/uapi"
+- elif [ "$ARCH" = "arm64" -o "$ARCH" =
"powerpc" ]; then
+- MACH_CFLAGS="$MACH_CFLAGS -I$HEADERS/arch/$ARCH/include"
+- MACH_CFLAGS="$MACH_CFLAGS -I$HEADERS/arch/$ARCH/include/uapi"
+- fi
+- if [ "$XEN_PRESENT" != "0" ]; then
+- MACH_CFLAGS="-I$HEADERS/asm-$ARCH/mach-xen $MACH_CFLAGS"
+- fi
+- else
+- MACH_CFLAGS="-I$HEADERS/asm/mach-default"
+- if [ "$ARCH" = "i386" -o "$ARCH" =
"x86_64" ]; then
+- MACH_CFLAGS="$MACH_CFLAGS -I$HEADERS/asm-x86/mach-default"
+- MACH_CFLAGS="$MACH_CFLAGS
-I$SOURCES/arch/x86/include/asm/mach-default"
+- MACH_CFLAGS="$MACH_CFLAGS -I$HEADERS/arch/x86/include/uapi"
+- elif [ "$ARCH" = "arm" ]; then
+- MACH_CFLAGS="$MACH_CFLAGS -D__LINUX_ARM_ARCH__=7"
+- MACH_CFLAGS="$MACH_CFLAGS -I$SOURCES/arch/arm/mach-tegra/include"
+- MACH_CFLAGS="$MACH_CFLAGS -I$HEADERS/arch/arm/include/uapi"
+- elif [ "$ARCH" = "arm64" -o "$ARCH" =
"powerpc" ]; then
+- MACH_CFLAGS="$MACH_CFLAGS -I$HEADERS/arch/$ARCH/include"
+- MACH_CFLAGS="$MACH_CFLAGS -I$HEADERS/arch/$ARCH/include/uapi"
+- fi
+- if [ "$XEN_PRESENT" != "0" ]; then
+- MACH_CFLAGS="-I$HEADERS/asm/mach-xen $MACH_CFLAGS"
+- fi
++ if [ "$XEN_PRESENT" != "0" ]; then
++ MACH_CFLAGS="-I$HEADERS/asm/mach-xen"
+ fi
+
+- CFLAGS="$BASE_CFLAGS $MACH_CFLAGS $OUTPUT_CFLAGS $AUTOCONF_CFLAGS"
+- CFLAGS="$CFLAGS -I$HEADERS -I$HEADERS/uapi
-I$OUTPUT/include/generated/uapi"
++ SOURCE_HEADERS="$HEADERS"
++ SOURCE_ARCH_HEADERS="$SOURCES/arch/$KERNEL_ARCH/include"
++ OUTPUT_HEADERS="$OUTPUT/include"
++ OUTPUT_ARCH_HEADERS="$OUTPUT/arch/$KERNEL_ARCH/include"
++
++ # Look for mach- directories on this arch, and add it to the list of
++ # includes if that platform is enabled in the configuration file, which
++ # may have a definition like this:
++ # #define CONFIG_ARCH_<MACHUPPERCASE> 1
++ for _mach_dir in `ls -1d $SOURCES/arch/$KERNEL_ARCH/mach-* 2>/dev/null`; do
++ _mach=`echo $_mach_dir | \
++ sed -e "s,$SOURCES/arch/$KERNEL_ARCH/mach-,," | \
++ tr 'a-z' 'A-Z'`
++ grep "CONFIG_ARCH_$_mach \+1" $AUTOCONF_FILE > /dev/null
2>&1
++ if [ $? -eq 0 ]; then
++ MACH_CFLAGS="$MACH_CFLAGS -I$_mach_dir/include"
++ fi
++ done
+
+- if [ "$ARCH" = "i386" -o "$ARCH" = "x86_64"
]; then
+- CFLAGS="$CFLAGS -I$SOURCES/arch/x86/include"
+- CFLAGS="$CFLAGS -I$SOURCES/arch/x86/include/uapi"
+- CFLAGS="$CFLAGS -I$OUTPUT/arch/x86/include/generated"
+- CFLAGS="$CFLAGS -I$OUTPUT/arch/x86/include/generated/uapi"
+- elif [ "$ARCH" = "arm" -o "$ARCH" = "arm64"
-o "$ARCH" = "powerpc" ]; then
+- CFLAGS="$CFLAGS -I$SOURCES/arch/$ARCH/include"
+- CFLAGS="$CFLAGS -I$SOURCES/arch/$ARCH/include/uapi"
+- CFLAGS="$CFLAGS -I$OUTPUT/arch/$ARCH/include/generated"
+- CFLAGS="$CFLAGS -I$OUTPUT/arch/$ARCH/include/generated/uapi"
++ if [ "$ARCH" = "arm" ]; then
++ MACH_CFLAGS="$MACH_CFLAGS -D__LINUX_ARM_ARCH__=7"
+ fi
++
++ # Add the mach-default includes (only found on x86/older kernels)
++ MACH_CFLAGS="$MACH_CFLAGS
-I$SOURCE_HEADERS/asm-$KERNEL_ARCH/mach-default"
++ MACH_CFLAGS="$MACH_CFLAGS -I$SOURCE_ARCH_HEADERS/asm/mach-default"
++
++ CFLAGS="$BASE_CFLAGS $MACH_CFLAGS $OUTPUT_CFLAGS -include $AUTOCONF_FILE"
++ CFLAGS="$CFLAGS -I$SOURCE_HEADERS"
++ CFLAGS="$CFLAGS -I$SOURCE_HEADERS/uapi"
++ CFLAGS="$CFLAGS -I$SOURCE_HEADERS/xen"
++ CFLAGS="$CFLAGS -I$OUTPUT_HEADERS/generated/uapi"
++ CFLAGS="$CFLAGS -I$SOURCE_ARCH_HEADERS"
++ CFLAGS="$CFLAGS -I$SOURCE_ARCH_HEADERS/uapi"
++ CFLAGS="$CFLAGS -I$OUTPUT_ARCH_HEADERS/generated"
++ CFLAGS="$CFLAGS -I$OUTPUT_ARCH_HEADERS/generated/uapi"
++
+ if [ -n "$BUILD_PARAMS" ]; then
+ CFLAGS="$CFLAGS -D$BUILD_PARAMS"
+ fi
+@@ -289,9 +230,31 @@
+ CFLAGS="$CFLAGS -DCC_HAVE_ASM_GOTO"
+ fi
+ fi
++
++ #
++ # If CONFIG_HAVE_FENTRY is enabled and gcc supports -mfentry flags then set
++ # CC_USING_FENTRY and add -mfentry into cflags.
++ #
++ # linux/ftrace.h file indirectly gets included into the conftest source and
++ # fails to get compiled, because conftest.sh runs outside of Kbuild it ends
++ # up building without -mfentry and CC_USING_FENTRY flags.
++ #
++ grep "CONFIG_HAVE_FENTRY \+1" $AUTOCONF_FILE > /dev/null 2>&1
++ if [ $? -eq 0 ]; then
++ echo "" > conftest$$.c
++
++ $CC -mfentry -c -x c conftest$$.c > /dev/null 2>&1
++ rm -f conftest$$.c
++
++ if [ -f conftest$$.o ]; then
++ rm -f conftest$$.o
++
++ CFLAGS="$CFLAGS -mfentry -DCC_USING_FENTRY"
++ fi
++ fi
+ }
+
+-CONFTEST_PREAMBLE="#include \"conftest.h\"
++CONFTEST_PREAMBLE="#include \"conftest/headers.h\"
+ #if defined(NV_LINUX_KCONFIG_H_PRESENT)
+ #include <linux/kconfig.h>
+ #endif
+@@ -357,6 +320,47 @@
+ fi
+ }
+
++export_symbol_present_conftest() {
++ #
++ # Check Module.symvers to see whether the given symbol is present.
++ #
++
++ SYMBOL="$1"
++ TAB=' '
++
++ if grep -e "${TAB}${SYMBOL}${TAB}.*${TAB}EXPORT_SYMBOL.*\$" \
++ "$OUTPUT/Module.symvers" >/dev/null 2>&1; then
++ echo "#define NV_IS_EXPORT_SYMBOL_PRESENT_$SYMBOL 1" |
++ append_conftest "symbols"
++ else
++ # May be a false negative if Module.symvers is absent or incomplete,
++ # or if the Module.symvers format changes.
++ echo "#define NV_IS_EXPORT_SYMBOL_PRESENT_$SYMBOL 0" |
++ append_conftest "symbols"
++ fi
++}
++
++export_symbol_gpl_conftest() {
++ #
++ # Check Module.symvers to see whether the given symbol is present and its
++ # export type is GPL-only (including deprecated GPL-only symbols).
++ #
++
++ SYMBOL="$1"
++ TAB=' '
++
++ if grep -e "${TAB}${SYMBOL}${TAB}.*${TAB}EXPORT_\(UNUSED_\)*SYMBOL_GPL\$"
\
++ "$OUTPUT/Module.symvers" >/dev/null 2>&1; then
++ echo "#define NV_IS_EXPORT_SYMBOL_GPL_$SYMBOL 1" |
++ append_conftest "symbols"
++ else
++ # May be a false negative if Module.symvers is absent or incomplete,
++ # or if the Module.symvers format changes.
++ echo "#define NV_IS_EXPORT_SYMBOL_GPL_$SYMBOL 0" |
++ append_conftest "symbols"
++ fi
++}
++
+ get_configuration_option() {
+ #
+ # Print the value of given configuration option, if defined
+@@ -425,6 +429,9 @@
+ #
+ CODE="
+ #if defined(NV_ASM_SET_MEMORY_H_PRESENT)
++ #if defined(NV_ASM_PGTABLE_TYPES_H_PRESENT)
++ #include <asm/pgtable_types.h>
++ #endif
+ #include <asm/set_memory.h>
+ #else
+ #include <asm/cacheflush.h>
+@@ -441,10 +448,10 @@
+ # Determine if the set_memory_array_uc() function is present.
+ #
+ CODE="
+- #if defined(NV_ASM_PGTABLE_H_PRESENT)
+- #include <asm/pgtable.h>
+- #endif
+ #if defined(NV_ASM_SET_MEMORY_H_PRESENT)
++ #if defined(NV_ASM_PGTABLE_TYPES_H_PRESENT)
++ #include <asm/pgtable_types.h>
++ #endif
+ #include <asm/set_memory.h>
+ #else
+ #include <asm/cacheflush.h>
+@@ -456,12 +463,50 @@
+ compile_check_conftest "$CODE"
"NV_SET_MEMORY_ARRAY_UC_PRESENT" "" "functions"
+ ;;
+
++ sysfs_slab_unlink)
++ #
++ # Determine if the sysfs_slab_unlink() function is present.
++ #
++ # This test is useful to check for the presence a fix for the deferred
++ # kmem_cache destroy feature (see nvbug: 2543505).
++ #
++ # Added by commit d50d82faa0c9 ("slub: fix failure when we delete and
++ # create a slab cache") in 4.18 (2018-06-27).
++ #
++ CODE="
++ #include <linux/slab.h>
++ void conftest_sysfs_slab_unlink(void) {
++ sysfs_slab_unlink();
++ }"
++
++ compile_check_conftest "$CODE"
"NV_SYSFS_SLAB_UNLINK_PRESENT" "" "functions"
++ ;;
++
++ list_is_first)
++ #
++ # Determine if the list_is_first() function is present.
++ #
++ # Added by commit 0d29c2d43753 ("mm, compaction: Use free lists to
quickly
++ # locate a migration source -fix") in linux-next tree
++ #
++ CODE="
++ #include <linux/list.h>
++ void conftest_list_is_first(void) {
++ list_is_first();
++ }"
++
++ compile_check_conftest "$CODE"
"NV_LIST_IS_FIRST_PRESENT" "" "functions"
++ ;;
++
+ set_pages_uc)
+ #
+ # Determine if the set_pages_uc() function is present.
+ #
+ CODE="
+ #if defined(NV_ASM_SET_MEMORY_H_PRESENT)
++ #if defined(NV_ASM_PGTABLE_TYPES_H_PRESENT)
++ #include <asm/pgtable_types.h>
++ #endif
+ #include <asm/set_memory.h>
+ #else
+ #include <asm/cacheflush.h>
+@@ -495,9 +540,7 @@
+ #include <linux/version.h>
+ #include <linux/utsname.h>
+ #include <linux/mm.h>
+- #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+- #include <asm/cacheflush.h>
+- #endif
++ #include <asm/cacheflush.h>
+ void conftest_change_page_attr(void) {
+ change_page_attr();
+ }"
+@@ -558,6 +601,20 @@
+ fi
+ ;;
+
++ pci_bus_address)
++ #
++ # Determine if the pci_bus_address() function is
++ # present.
++ #
++ CODE="
++ #include <linux/pci.h>
++ void conftest_pci_bus_address(void) {
++ pci_bus_address();
++ }"
++
++ compile_check_conftest "$CODE"
"NV_PCI_BUS_ADDRESS_PRESENT" "" "functions"
++ ;;
++
+ remap_pfn_range)
+ #
+ # Determine if the remap_pfn_range() function is
+@@ -572,61 +629,37 @@
+ compile_check_conftest "$CODE"
"NV_REMAP_PFN_RANGE_PRESENT" "" "functions"
+ ;;
+
+- vmap)
++ hash__remap_4k_pfn)
+ #
+- # Determine if the vmap() function is present and how
+- # many arguments it takes.
++ # Determine if the hash__remap_4k_pfn() function is
++ # present.
++ # hash__remap_4k_pfn was added by this commit:
++ # 2016-04-29 6cc1a0ee4ce29ad1cbdc622db6f9bc16d3056067
+ #
+- echo "$CONFTEST_PREAMBLE
+- #include <linux/vmalloc.h>
+- void conftest_vmap(void) {
+- vmap();
+- }" > conftest$$.c
+-
+- $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
+- rm -f conftest$$.c
+-
+- if [ -f conftest$$.o ]; then
+- echo "#undef NV_VMAP_PRESENT" | append_conftest
"functions"
+- rm -f conftest$$.o
+- return
+- fi
+-
+- echo "$CONFTEST_PREAMBLE
+- #include <linux/vmalloc.h>
+- void *conftest_vmap(struct page **pages, int count) {
+- return vmap(pages, count);
+- }" > conftest$$.c
+-
+- $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
+- rm -f conftest$$.c
++ CODE="
++ #if defined(NV_ASM_BOOK3S_64_HASH_64K_H_PRESENT)
++ #include <linux/mm.h>
++ #include <asm/book3s/64/hash-64k.h>
++ #endif
++ void conftest_hash__remap_4k_pfn(void) {
++ hash__remap_4k_pfn();
++ }"
+
+- if [ -f conftest$$.o ]; then
+- echo "#define NV_VMAP_PRESENT" | append_conftest
"functions"
+- echo "#define NV_VMAP_ARGUMENT_COUNT 2" | append_conftest
"functions"
+- rm -f conftest$$.o
+- return
+- fi
++ compile_check_conftest "$CODE"
"NV_HASH__REMAP_4K_PFN_PRESENT" "" "functions"
++ ;;
+
+- echo "$CONFTEST_PREAMBLE
+- #include <linux/vmalloc.h>
++ follow_pfn)
++ #
++ # Determine if the follow_pfn() function is
++ # present.
++ #
++ CODE="
+ #include <linux/mm.h>
+- void *conftest_vmap(struct page **pages, int count) {
+- return vmap(pages, count, 0, PAGE_KERNEL);
+- }" > conftest$$.c
+-
+- $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
+- rm -f conftest$$.c
++ void conftest_follow_pfn(void) {
++ follow_pfn();
++ }"
+
+- if [ -f conftest$$.o ]; then
+- echo "#define NV_VMAP_PRESENT" | append_conftest
"functions"
+- echo "#define NV_VMAP_ARGUMENT_COUNT 4" | append_conftest
"functions"
+- rm -f conftest$$.o
+- return
+- else
+- echo "#error vmap() conftest failed!" | append_conftest
"functions"
+- return
+- fi
++ compile_check_conftest "$CODE" "NV_FOLLOW_PFN_PRESENT"
"" "functions"
+ ;;
+
+ i2c_adapter)
+@@ -772,6 +805,20 @@
+ fi
+ ;;
+
++ request_threaded_irq)
++ #
++ # Determine if the request_threaded_irq() function is present.
++ #
++ # added: 2009-03-23 3aa551c9b4c40018f0e261a178e3d25478dc04a9
++ #
++ CODE="
++ #include <linux/interrupt.h>
++ int conftest_request_threaded_irq(void) {
++ return request_threaded_irq();
++ }"
++ compile_check_conftest "$CODE"
"NV_REQUEST_THREADED_IRQ_PRESENT" "" "functions"
++ ;;
++
+ acpi_device_ops)
+ #
+ # Determine if the 'acpi_device_ops' structure has
+@@ -918,21 +965,6 @@
+ fi
+ ;;
+
+- kmem_cache_create_usercopy)
+- #
+- # Determine if the kmem_cache_create_usercopy function exists.
+- #
+- # This function was added by:
+- # 2017-06-10 8eb8284b412906181357c2b0110d879d5af95e52
+- CODE="
+- #include <linux/slab.h>
+- void kmem_cache_create_usercopy(void) {
+- kmem_cache_create_usercopy();
+- }"
+-
+- compile_check_conftest "$CODE"
"NV_KMEM_CACHE_CREATE_USERCOPY_PRESENT" "" "functions"
+- ;;
+-
+ smp_call_function)
+ #
+ # Determine if the smp_call_function() function is
+@@ -1078,16 +1110,6 @@
+ compile_check_conftest "$CODE"
"NV_CPUHP_SETUP_STATE_PRESENT" "" "functions"
+ ;;
+
+- nvmap_support)
+- # check if nvmap is supported.
+- if [ -f nv-android.h ]; then
+- echo "#define HAVE_NV_ANDROID" | append_conftest
"generic"
+- return
+- else
+- echo "#undef HAVE_NV_ANDROID" | append_conftest
"generic"
+- fi
+- ;;
+-
+ acpi_evaluate_integer)
+ #
+ # Determine if the acpi_evaluate_integer() function is
+@@ -1211,9 +1233,6 @@
+ #
+ # Determine if the ioremap_nocache() function is present.
+ #
+- # Removed by commit 4bdc0d676a64 ("remove ioremap_nocache and
+- # devm_ioremap_nocache") in v5.6 (2020-01-06)
+- #
+ CODE="
+ #include <asm/io.h>
+ void conftest_ioremap_nocache(void) {
+@@ -1406,57 +1425,6 @@
+ compile_check_conftest "$CODE"
"NV_FILE_OPERATIONS_HAS_COMPAT_IOCTL" "" "types"
+ ;;
+
+- proc_ops)
+- CODE="
+- #include <linux/proc_fs.h>
+- int conftest_proc_ops(void) {
+- return offsetof(struct proc_ops, proc_open);
+- }"
+-
+- compile_check_conftest "$CODE" "NV_HAVE_PROC_OPS"
"" "types"
+- ;;
+-
+- sg_init_table)
+- #
+- # Determine if the sg_init_table() function is present.
+- #
+- echo "$CONFTEST_PREAMBLE
+- #include <linux/scatterlist.h>
+- void conftest_sg_init_table(struct scatterlist *sgl,
+- unsigned int nents) {
+- }" > conftest$$.c
+-
+- $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
+- rm -f conftest$$.c
+-
+- if [ ! -f conftest$$.o ]; then
+- echo "#undef NV_SG_INIT_TABLE_PRESENT" | append_conftest
"functions"
+- return
+-
+- fi
+- rm -f conftest$$.o
+-
+- echo "$CONFTEST_PREAMBLE
+- #include <linux/types.h>
+- #include <linux/scatterlist.h>
+- void conftest_sg_init_table(struct scatterlist *sgl,
+- unsigned int nents) {
+- sg_init_table();
+- }" > conftest$$.c
+-
+- $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
+- rm -f conftest$$.c
+-
+- if [ -f conftest$$.o ]; then
+- echo "#undef NV_SG_INIT_TABLE_PRESENT" | append_conftest
"functions"
+- rm -f conftest$$.o
+- return
+- else
+- echo "#define NV_SG_INIT_TABLE_PRESENT" | append_conftest
"functions"
+- return
+- fi
+- ;;
+-
+ sg_table)
+ #
+ # Determine if the struct sg_table type is present.
+@@ -1476,7 +1444,7 @@
+ #
+ echo "$CONFTEST_PREAMBLE
+ #include <linux/scatterlist.h>
+- int conftest_sg_alloc_table(void) {
++ void conftest_sg_alloc_table(void) {
+ }" > conftest$$.c
+
+ $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
+@@ -1492,7 +1460,7 @@
+
+ CODE="
+ #include <linux/scatterlist.h>
+- int conftest_sg_alloc_table(void) {
++ void conftest_sg_alloc_table(void) {
+ sg_alloc_table();
+ }"
+
+@@ -1565,6 +1533,197 @@
+ return
+ ;;
+
++ nvidia_vgpu_kvm_build)
++ #
++ # Add config parameter if running on KVM host.
++ #
++ if [ -n "$VGX_KVM_BUILD" ]; then
++ echo "#define NV_VGPU_KVM_BUILD" | append_conftest
"generic"
++ else
++ echo "#undef NV_VGPU_KVM_BUILD" | append_conftest
"generic"
++ fi
++ return
++ ;;
++
++ vfio_register_notifier)
++ #
++ # Check number of arguments required.
++ #
++ echo "$CONFTEST_PREAMBLE
++ #include <linux/vfio.h>
++ int conftest_vfio_register_notifier(void) {
++ return vfio_register_notifier((struct device *) NULL, (struct
notifier_block *) NULL);
++ }" > conftest$$.c
++
++ $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
++ rm -f conftest$$.c
++
++ if [ -f conftest$$.o ]; then
++ echo "#define NV_VFIO_NOTIFIER_ARGUMENT_COUNT 2" |
append_conftest "functions"
++ rm -f conftest$$.o
++ return
++ else
++ echo "#define NV_VFIO_NOTIFIER_ARGUMENT_COUNT 4" |
append_conftest "functions"
++ return
++ fi
++ ;;
++
++ vfio_info_add_capability_has_cap_type_id_arg)
++ #
++ # Check if vfio_info_add_capability() has cap_type_id field.
++ # cap_type_id field was removed in commit:
++ # 2017-12-12 dda01f787df9f9e46f1c0bf8aa11f246e300750d
++ #
++ CODE="
++ #include <linux/vfio.h>
++ int vfio_info_add_capability(struct vfio_info_cap *caps,
++ int cap_type_id,
++ void *cap_type) {
++ return 0;
++ }"
++
++ compile_check_conftest "$CODE"
"NV_VFIO_INFO_ADD_CAPABILITY_HAS_CAP_TYPE_ID_ARGS" ""
"types"
++ ;;
++
++ nvidia_grid_build)
++ if [ -n "$GRID_BUILD" ]; then
++ echo "#define NV_GRID_BUILD" | append_conftest
"generic"
++ else
++ echo "#undef NV_GRID_BUILD" | append_conftest
"generic"
++ fi
++ return
++ ;;
++
++ vm_fault_present)
++ #
++ # Determine if the 'vm_fault' structure is present. The earlier
++ # name for this struct was fault_data, and it was renamed to
++ # vm_fault by:
++ #
++ # 2007-07-19 d0217ac04ca6591841e5665f518e38064f4e65bd
++ #
++ CODE="
++ #include <linux/mm.h>
++ int conftest_vm_fault_present(void) {
++ return offsetof(struct vm_fault, flags);
++ }"
++
++ compile_check_conftest "$CODE" "NV_VM_FAULT_PRESENT"
"" "types"
++ ;;
++
++ vm_fault_has_address)
++ #
++ # Determine if the 'vm_fault' structure has an 'address', or
a
++ # 'virtual_address' field. The .virtual_address field was
++ # effectively renamed to .address, by these two commits:
++ #
++ # struct vm_fault: .address was added by:
++ # 2016-12-14 82b0f8c39a3869b6fd2a10e180a862248736ec6f
++ #
++ # struct vm_fault: .virtual_address was removed by:
++ # 2016-12-14 1a29d85eb0f19b7d8271923d8917d7b4f5540b3e
++ #
++ CODE="
++ #include <linux/mm.h>
++ int conftest_vm_fault_has_address(void) {
++ return offsetof(struct vm_fault, address);
++ }"
++
++ compile_check_conftest "$CODE" "NV_VM_FAULT_HAS_ADDRESS"
"" "types"
++ ;;
++
++ kmem_cache_has_kobj_remove_work)
++ #
++ # Determine if the 'kmem_cache' structure has
'kobj_remove_work'.
++ #
++ # 'kobj_remove_work' was added by commit 3b7b314053d02 ("slub:
make
++ # sysfs file removal asynchronous") in v4.12 (2017-06-23). This
++ # commit introduced a race between kmem_cache destroy and create
++ # which we need to workaround in our driver (see nvbug: 2543505).
++ # Also see comment for sysfs_slab_unlink conftest.
++ #
++ CODE="
++ #include <linux/mm.h>
++ #include <linux/slab.h>
++ #include <linux/slub_def.h>
++ int conftest_kmem_cache_has_kobj_remove_work(void) {
++ return offsetof(struct kmem_cache, kobj_remove_work);
++ }"
++
++ compile_check_conftest "$CODE"
"NV_KMEM_CACHE_HAS_KOBJ_REMOVE_WORK" "" "types"
++ ;;
++
++ mdev_uuid)
++ #
++ # Determine if mdev_uuid() function is present or not
++ #
++ CODE="
++ #include <linux/pci.h>
++ #include <linux/mdev.h>
++ void conftest_mdev_uuid() {
++ mdev_uuid();
++ }"
++
++ compile_check_conftest "$CODE" "NV_MDEV_UUID_PRESENT"
"" "functions"
++ ;;
++
++ mdev_dev)
++ #
++ # Determine if mdev_dev() function is present or not
++ #
++ CODE="
++ #include <linux/pci.h>
++ #include <linux/mdev.h>
++ void conftest_mdev_dev() {
++ mdev_dev();
++ }"
++
++ compile_check_conftest "$CODE" "NV_MDEV_DEV_PRESENT"
"" "functions"
++ ;;
++
++ mdev_parent)
++ #
++ # Determine if the struct mdev_parent type is present.
++ #
++ CODE="
++ #include <linux/pci.h>
++ #include <linux/mdev.h>
++ struct mdev_parent_ops conftest_mdev_parent;
++ "
++
++ compile_check_conftest "$CODE"
"NV_MDEV_PARENT_OPS_STRUCT_PRESENT" "" "types"
++ ;;
++
++ mdev_parent_dev)
++ #
++ # Determine if mdev_parent_dev() function is present or not
++ #
++ CODE="
++ #include <linux/pci.h>
++ #include <linux/mdev.h>
++ void conftest_mdev_parent_dev() {
++ mdev_parent_dev();
++ }"
++
++ compile_check_conftest "$CODE"
"NV_MDEV_PARENT_DEV_PRESENT" "" "functions"
++ ;;
++
++ mdev_from_dev)
++ #
++ # Determine if mdev_from_dev() function is present or not.
++ #
++ # Added: 2016-12-30 99e3123e3d72616a829dad6d25aa005ef1ef9b13
++ #
++ CODE="
++ #include <linux/pci.h>
++ #include <linux/mdev.h>
++ void conftest_mdev_from_dev() {
++ mdev_from_dev();
++ }"
++
++ compile_check_conftest "$CODE"
"NV_MDEV_FROM_DEV_PRESENT" "" "functions"
++ ;;
++
+ drm_available)
+ #
+ # Determine if the DRM subsystem is usable
+@@ -1578,26 +1737,47 @@
+ #include <drm/drm_drv.h>
+ #endif
+
+- #if defined(NV_DRM_DRM_PRIME_H_PRESENT)
+- #include <drm/drm_prime.h>
+- #endif
+-
+ #if !defined(CONFIG_DRM) && !defined(CONFIG_DRM_MODULE)
+ #error DRM not enabled
+ #endif
++
+ void conftest_drm_available(void) {
+ struct drm_driver drv;
+- drv.gem_prime_pin = 0;
+- drv.gem_prime_get_sg_table = 0;
+- drv.gem_prime_vmap = 0;
+- drv.gem_prime_vunmap = 0;
+- (void)drm_gem_prime_import;
+- (void)drm_gem_prime_export;
++
++ /* 2013-10-02 1bb72532ac260a2d3982b40bdd4c936d779d0d16 */
++ (void)drm_dev_alloc;
++
++ /* 2013-10-02 c22f0ace1926da399d9a16dfaf09174c1b03594c */
++ (void)drm_dev_register;
++
++ /* 2013-10-02 c3a49737ef7db0bdd4fcf6cf0b7140a883e32b2a */
++ (void)drm_dev_unregister;
+ }"
+
+ compile_check_conftest "$CODE" "NV_DRM_AVAILABLE"
"" "generic"
+ ;;
+
++ drm_dev_unref)
++ #
++ # Determine if drm_dev_unref() is present.
++ #
++ CODE="
++ #if defined(NV_DRM_DRMP_H_PRESENT)
++ #include <drm/drmP.h>
++ #endif
++ void conftest_drm_dev_unref(void) {
++ /*
++ * drm_dev_free() was added in:
++ * 2013-10-02 0dc8fe5985e01f238e7dc64ff1733cc0291811e8
++ * drm_dev_free() was renamed to drm_dev_unref() in:
++ * 2014-01-29 099d1c290e2ebc3b798961a6c177c3aef5f0b789
++ */
++ drm_dev_unref();
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_DEV_UNREF_PRESENT" "" "functions"
++ ;;
++
+ proc_create_data)
+ #
+ # Determine if the proc_create_data() function is present.
+@@ -1655,7 +1835,7 @@
+ vm_operations_struct)
+ #
+ # Determine if the 'vm_operations_struct' structure has
+- # a 'fault' field.
++ # 'fault' and 'access' fields.
+ #
+ CODE="
+ #include <linux/mm.h>
+@@ -1664,45 +1844,56 @@
+ }"
+
+ compile_check_conftest "$CODE"
"NV_VM_OPERATIONS_STRUCT_HAS_FAULT" "" "types"
+- ;;
+
+- vm_fault_present)
+- #
+- # Determine if the 'vm_fault' structure is present. The earlier
+- # name for this struct was fault_data, and it was renamed to
+- # vm_fault by:
+- #
+- # 2007-07-19 d0217ac04ca6591841e5665f518e38064f4e65bd
+- #
+ CODE="
+ #include <linux/mm.h>
+- int conftest_vm_fault_present(void) {
+- return offsetof(struct vm_fault, flags);
++ int conftest_vm_operations_struct(void) {
++ return offsetof(struct vm_operations_struct, access);
+ }"
+
+- compile_check_conftest "$CODE" "NV_VM_FAULT_PRESENT"
"" "types"
++ compile_check_conftest "$CODE"
"NV_VM_OPERATIONS_STRUCT_HAS_ACCESS" "" "types"
+ ;;
+
+- vm_fault_has_address)
+- #
+- # Determine if the 'vm_fault' structure has an 'address', or
a
+- # 'virtual_address' field. The .virtual_address field was
+- # effectively renamed to .address, by these two commits:
+- #
+- # struct vm_fault: .address was added by:
+- # 2016-12-14 82b0f8c39a3869b6fd2a10e180a862248736ec6f
+- #
+- # struct vm_fault: .virtual_address was removed by:
+- # 2016-12-14 1a29d85eb0f19b7d8271923d8917d7b4f5540b3e
+- #
++ fault_flags)
++ # Determine if the FAULT_FLAG_WRITE is defined
+ CODE="
+ #include <linux/mm.h>
+- int conftest_vm_fault_has_address(void) {
+- return offsetof(struct vm_fault, address);
++ void conftest_fault_flags(void) {
++ int flag = FAULT_FLAG_WRITE;
+ }"
+
+- compile_check_conftest "$CODE" "NV_VM_FAULT_HAS_ADDRESS"
"" "types"
++ compile_check_conftest "$CODE" "NV_FAULT_FLAG_PRESENT"
"" "types"
+ ;;
++
++ atomic_long_type)
++ # Determine if atomic_long_t and associated functions are defined
++ # Added in 2.6.16 2006-01-06 d3cb487149bd706aa6aeb02042332a450978dc1c
++ CODE="
++ #include <asm/atomic.h>
++ void conftest_atomic_long(void) {
++ atomic_long_t data;
++ atomic_long_read(&data);
++ atomic_long_set(&data, 0);
++ atomic_long_inc(&data);
++ }"
++
++ compile_check_conftest "$CODE" "NV_ATOMIC_LONG_PRESENT"
"" "types"
++ ;;
++
++ atomic64_type)
++ # Determine if atomic64_t and associated functions are defined
++ CODE="
++ #include <asm/atomic.h>
++ void conftest_atomic64(void) {
++ atomic64_t data;
++ atomic64_read(&data);
++ atomic64_set(&data, 0);
++ atomic64_inc(&data);
++ }"
++
++ compile_check_conftest "$CODE" "NV_ATOMIC64_PRESENT"
"" "types"
++ ;;
++
+ task_struct)
+ #
+ # Determine if the 'task_struct' structure has
+@@ -1717,6 +1908,20 @@
+ compile_check_conftest "$CODE" "NV_TASK_STRUCT_HAS_CRED"
"" "types"
+ ;;
+
++ backing_dev_info)
++ #
++ # Determine if the 'address_space' structure has
++ # a 'backing_dev_info' field.
++ #
++ CODE="
++ #include <linux/fs.h>
++ int conftest_backing_dev_info(void) {
++ return offsetof(struct address_space, backing_dev_info);
++ }"
++
++ compile_check_conftest "$CODE"
"NV_ADDRESS_SPACE_HAS_BACKING_DEV_INFO" "" "types"
++ ;;
++
+ address_space)
+ #
+ # Determine if the 'address_space' structure has
+@@ -1800,6 +2005,19 @@
+
+ compile_check_conftest "$CODE"
"NV_PM_VT_SWITCH_REQUIRED_PRESENT" "" "functions"
+ ;;
++
++ list_cut_position)
++ #
++ # Determine if the list_cut_position() function is present.
++ #
++ CODE="
++ #include <linux/list.h>
++ void conftest_list_cut_position(void) {
++ list_cut_position();
++ }"
++
++ compile_check_conftest "$CODE"
"NV_LIST_CUT_POSITION_PRESENT" "" "functions"
++ ;;
+
+ file_inode)
+ #
+@@ -1815,19 +2033,133 @@
+ compile_check_conftest "$CODE" "NV_FILE_HAS_INODE"
"" "types"
+ ;;
+
+- drm_pci_set_busid)
++ xen_ioemu_inject_msi)
+ #
+- # Determine if the drm_pci_set_busid function is present.
++ # Determine if the xen_ioemu_inject_msi() function is present.
+ #
+ CODE="
+- #if defined(NV_DRM_DRMP_H_PRESENT)
+- #include <drm/drmP.h>
++ #if defined(NV_XEN_IOEMU_H_PRESENT)
++ #include <linux/kernel.h>
++ #include <xen/interface/xen.h>
++ #include <xen/hvm.h>
++ #include <xen/ioemu.h>
+ #endif
+- void conftest_drm_pci_set_busid(void) {
+- drm_pci_set_busid();
++ void conftest_xen_ioemu_inject_msi(void) {
++ xen_ioemu_inject_msi();
++ }"
++
++ compile_check_conftest "$CODE" "NV_XEN_IOEMU_INJECT_MSI"
"" "functions"
++ ;;
++
++ phys_to_dma)
++ #
++ # Determine if the phys_to_dma function is present.
++ #
++ CODE="
++ #include <linux/dma-mapping.h>
++ void conftest_phys_to_dma(void) {
++ phys_to_dma();
++ }"
++
++ compile_check_conftest "$CODE" "NV_PHYS_TO_DMA_PRESENT"
"" "functions"
++ ;;
++
++ dma_ops)
++ #
++ # Determine if the 'dma_ops' structure is present.
++ #
++ CODE="
++ #include <linux/dma-mapping.h>
++ void conftest_dma_ops(void) {
++ (void)dma_ops;
+ }"
+
+- compile_check_conftest "$CODE"
"NV_DRM_PCI_SET_BUSID_PRESENT" "" "functions"
++ compile_check_conftest "$CODE" "NV_DMA_OPS_PRESENT"
"" "symbols"
++ ;;
++
++ swiotlb_dma_ops)
++ #
++ # Determine if the 'swiotlb_dma_ops' structure is present.
++ # It does not exist on all architectures.
++ #
++ CODE="
++ #include <linux/dma-mapping.h>
++ void conftest_dma_ops(void) {
++ (void)swiotlb_dma_ops;
++ }"
++
++ compile_check_conftest "$CODE"
"NV_SWIOTLB_DMA_OPS_PRESENT" "" "symbols"
++ ;;
++
++ dma_map_ops)
++ #
++ # Determine if the 'struct dma_map_ops' type is present.
++ #
++ # Commit 0a0f0d8be76d ("dma-mapping: split
<linux/dma-mapping.h>")
++ # in v5.10-rc1 (2020-09-22), moved 'struct dma_map_ops'
++ # type from <linux/dma-mapping.h> to <linux/dma-map-ops.h>.
++ #
++ CODE="
++ #if defined(NV_LINUX_DMA_MAP_OPS_H_PRESENT)
++ #include <linux/dma-map-ops.h>
++ #else
++ #include <linux/dma-mapping.h>
++ #endif
++ void conftest_dma_map_ops(void) {
++ struct dma_map_ops ops;
++ }"
++
++ compile_check_conftest "$CODE" "NV_DMA_MAP_OPS_PRESENT"
"" "types"
++ ;;
++
++ get_dma_ops)
++ #
++ # Determine if the get_dma_ops() function is present.
++ #
++ # Commit 0a0f0d8be76d ("dma-mapping: split
<linux/dma-mapping.h>")
++ # in v5.10-rc1 (2020-09-22), moved get_dma_ops() function
++ # prototype from <linux/dma-mapping.h> to
<linux/dma-map-ops.h>.
++ #
++ CODE="
++ #if defined(NV_LINUX_DMA_MAP_OPS_H_PRESENT)
++ #include <linux/dma-map-ops.h>
++ #else
++ #include <linux/dma-mapping.h>
++ #endif
++ void conftest_get_dma_ops(void) {
++ get_dma_ops();
++ }"
++
++ compile_check_conftest "$CODE" "NV_GET_DMA_OPS_PRESENT"
"" "functions"
++ ;;
++
++ noncoherent_swiotlb_dma_ops)
++ #
++ # Determine if the 'noncoherent_swiotlb_dma_ops' symbol is present.
++ #
++ CODE="
++ #include <linux/dma-mapping.h>
++ void conftest_noncoherent_swiotlb_dma_ops(void) {
++ (void)noncoherent_swiotlb_dma_ops;
++ }"
++
++ compile_check_conftest "$CODE"
"NV_NONCOHERENT_SWIOTLB_DMA_OPS_PRESENT" "" "symbols"
++ ;;
++
++ dma_map_resource)
++ #
++ # Determine if the dma_map_resource() function is present.
++ #
++ # dma_map_resource() was added by:
++ # 2016-08-10 6f3d87968f9c8b529bc81eff5a1f45e92553493d
++ #
++ CODE="
++ #include <linux/dma-mapping.h>
++ void conftest_dma_map_resource(void) {
++ dma_map_resource();
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DMA_MAP_RESOURCE_PRESENT" "" "functions"
+ ;;
+
+ write_cr4)
+@@ -1843,6 +2175,66 @@
+ compile_check_conftest "$CODE" "NV_WRITE_CR4_PRESENT"
"" "functions"
+ ;;
+
++ of_get_property)
++ #
++ # Determine if the of_get_property function is present.
++ #
++ CODE="
++ #if defined(NV_LINUX_OF_H_PRESENT)
++ #include <linux/of.h>
++ #endif
++ void conftest_of_get_property() {
++ of_get_property();
++ }"
++
++ compile_check_conftest "$CODE"
"NV_OF_GET_PROPERTY_PRESENT" "" "functions"
++ ;;
++
++ of_find_node_by_phandle)
++ #
++ # Determine if the of_find_node_by_phandle function is present.
++ #
++ CODE="
++ #if defined(NV_LINUX_OF_H_PRESENT)
++ #include <linux/of.h>
++ #endif
++ void conftest_of_find_node_by_phandle() {
++ of_find_node_by_phandle();
++ }"
++
++ compile_check_conftest "$CODE"
"NV_OF_FIND_NODE_BY_PHANDLE_PRESENT" "" "functions"
++ ;;
++
++ of_node_to_nid)
++ #
++ # Determine if of_node_to_nid is present
++ #
++ CODE="
++ #include <linux/version.h>
++ #include <linux/utsname.h>
++ #if defined(NV_LINUX_OF_H_PRESENT)
++ #include <linux/of.h>
++ #endif
++ void conftest_of_node_to_nid() {
++ of_node_to_nid();
++ }"
++
++ compile_check_conftest "$CODE"
"NV_OF_NODE_TO_NID_PRESENT" "" "functions"
++ ;;
++
++ pnv_pci_get_npu_dev)
++ #
++ # Determine if the pnv_pci_get_npu_dev function is present.
++ #
++ CODE="
++ #include <linux/pci.h>
++ void conftest_pnv_pci_get_npu_dev() {
++ pnv_pci_get_npu_dev();
++ }"
++
++ compile_check_conftest "$CODE"
"NV_PNV_PCI_GET_NPU_DEV_PRESENT" "" "functions"
++ ;;
++
+ for_each_online_node)
+ #
+ # Determine if the for_each_online_node() function is present.
+@@ -1869,6 +2261,705 @@
+ compile_check_conftest "$CODE" "NV_NODE_END_PFN_PRESENT"
"" "functions"
+ ;;
+
++ kernel_write)
++ #
++ # Determine if kernel_write function is present
++ #
++ CODE="
++ #include <linux/fs.h>
++ void conftest_kernel_write() {
++ kernel_write();
++ }"
++
++ compile_check_conftest "$CODE" "NV_KERNEL_WRITE_PRESENT"
"" "functions"
++ ;;
++
++ strnstr)
++ #
++ # Determine if strnstr function is present
++ #
++ CODE="
++ #include <linux/string.h>
++ void conftest_strnstr() {
++ strnstr();
++ }"
++
++ compile_check_conftest "$CODE" "NV_STRNSTR_PRESENT"
"" "functions"
++ ;;
++
++ iterate_dir)
++ #
++ # Determine if iterate_dir function is present
++ #
++ CODE="
++ #include <linux/fs.h>
++ void conftest_iterate_dir() {
++ iterate_dir();
++ }"
++
++ compile_check_conftest "$CODE" "NV_ITERATE_DIR_PRESENT"
"" "functions"
++ ;;
++ kstrtoull)
++ #
++ # Determine if kstrtoull function is present
++ #
++ CODE="
++ #include <linux/kernel.h>
++ void conftest_kstrtoull() {
++ kstrtoull();
++ }"
++
++ compile_check_conftest "$CODE" "NV_KSTRTOULL_PRESENT"
"" "functions"
++ ;;
++
++ drm_atomic_available)
++ #
++ # Determine if the DRM atomic modesetting subsystem is usable
++ #
++ # ("drm/atomic: Allow drivers to subclass drm_atomic_state, v3")
in
++ # v4.2 (2018-05-18).
++ #
++ # Make conftest more robust by adding test for
++ # drm_atomic_set_mode_prop_for_crtc(), this function added by
++ # commit 955f3c334f0f ("drm/atomic: Add MODE_ID property") in
v4.2
++ # (2015-05-25). If the DRM atomic modesetting subsystem is
++ # back ported to Linux kernel older than v4.2, then commit
++ # 955f3c334f0f must be back ported in order to get NVIDIA-DRM KMS
++ # support.
++ # Commit 72fdb40c1a4b ("drm: extract drm_atomic_uapi.c") in v4.20
++ # (2018-09-05), moved drm_atomic_set_mode_prop_for_crtc() function
++ # prototype from drm/drm_atomic.h to drm/drm_atomic_uapi.h.
++ #
++ echo "$CONFTEST_PREAMBLE
++ #if defined(NV_DRM_DRMP_H_PRESENT)
++ #include <drm/drmP.h>
++ #endif
++ #include <drm/drm_atomic.h>
++ #if !defined(CONFIG_DRM) && !defined(CONFIG_DRM_MODULE)
++ #error DRM not enabled
++ #endif
++ void conftest_drm_atomic_modeset_available(void) {
++ size_t a;
++
++ /* 2015-05-18 036ef5733ba433760a3512bb5f7a155946e2df05 */
++ a = offsetof(struct drm_mode_config_funcs, atomic_state_alloc);
++ }" > 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 "$CONFTEST_PREAMBLE
++ #if defined(NV_DRM_DRMP_H_PRESENT)
++ #include <drm/drmP.h>
++ #endif
++ #include <drm/drm_atomic.h>
++ #if defined(NV_DRM_DRM_ATOMIC_UAPI_H_PRESENT)
++ #include <drm/drm_atomic_uapi.h>
++ #endif
++ void conftest_drm_atomic_set_mode_prop_for_crtc(void) {
++ drm_atomic_set_mode_prop_for_crtc();
++ }" > 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 "#undef NV_DRM_ATOMIC_MODESET_AVAILABLE" |
append_conftest "generic"
++ else
++ echo "#define NV_DRM_ATOMIC_MODESET_AVAILABLE" |
append_conftest "generic"
++ fi
++ else
++ echo "#undef NV_DRM_ATOMIC_MODESET_AVAILABLE" |
append_conftest "generic"
++ fi
++ ;;
++
++ drm_bus_present)
++ #
++ # Determine if the 'struct drm_bus' type is present.
++ #
++ # added: 2010-12-15 8410ea3b95d105a5be5db501656f44bbb91197c1
++ # removed: 2014-08-29 c5786fe5f1c50941dbe27fc8b4aa1afee46ae893
++ #
++ CODE="
++ #if defined(NV_DRM_DRMP_H_PRESENT)
++ #include <drm/drmP.h>
++ #endif
++
++ void conftest_drm_bus_present(void) {
++ struct drm_bus bus;
++ }"
++
++ compile_check_conftest "$CODE" "NV_DRM_BUS_PRESENT"
"" "types"
++ ;;
++
++ drm_bus_has_bus_type)
++ #
++ # Determine if the 'drm_bus' structure has a 'bus_type'
field.
++ #
++ # added: 2010-12-15 8410ea3b95d105a5be5db501656f44bbb91197c1
++ # removed: 2013-11-03 42b21049fc26513ca8e732f47559b1525b04a992
++ #
++ CODE="
++ #if defined(NV_DRM_DRMP_H_PRESENT)
++ #include <drm/drmP.h>
++ #endif
++
++ int conftest_drm_bus_has_bus_type(void) {
++ return offsetof(struct drm_bus, bus_type);
++ }"
++
++ compile_check_conftest "$CODE" "NV_DRM_BUS_HAS_BUS_TYPE"
"" "types"
++ ;;
++
++ drm_bus_has_get_irq)
++ #
++ # Determine if the 'drm_bus' structure has a 'get_irq'
field.
++ #
++ # added: 2010-12-15 8410ea3b95d105a5be5db501656f44bbb91197c1
++ # removed: 2013-11-03 b2a21aa25a39837d06eb24a7f0fef1733f9843eb
++ #
++ CODE="
++ #if defined(NV_DRM_DRMP_H_PRESENT)
++ #include <drm/drmP.h>
++ #endif
++
++ int conftest_drm_bus_has_get_irq(void) {
++ return offsetof(struct drm_bus, get_irq);
++ }"
++
++ compile_check_conftest "$CODE" "NV_DRM_BUS_HAS_GET_IRQ"
"" "types"
++ ;;
++
++ drm_bus_has_get_name)
++ #
++ # Determine if the 'drm_bus' structure has a 'get_name'
field.
++ #
++ # added: 2010-12-15 8410ea3b95d105a5be5db501656f44bbb91197c1
++ # removed: 2013-11-03 9de1b51f1fae6476155350a0670dc637c762e718
++ #
++ CODE="
++ #if defined(NV_DRM_DRMP_H_PRESENT)
++ #include <drm/drmP.h>
++ #endif
++
++ int conftest_drm_bus_has_get_name(void) {
++ return offsetof(struct drm_bus, get_name);
++ }"
++
++ compile_check_conftest "$CODE" "NV_DRM_BUS_HAS_GET_NAME"
"" "types"
++ ;;
++
++ drm_driver_has_device_list)
++ #
++ # Determine if the 'drm_driver' structure has a
'device_list' field.
++ #
++ # Renamed from device_list to legacy_device_list by commit
++ # b3f2333de8e8 ("drm: restrict the device list for shadow
++ # attached drivers") in v3.14 (2013-12-11)
++ #
++ CODE="
++ #if defined(NV_DRM_DRMP_H_PRESENT)
++ #include <drm/drmP.h>
++ #endif
++
++ #if defined(NV_DRM_DRM_DRV_H_PRESENT)
++ #include <drm/drm_drv.h>
++ #endif
++
++ int conftest_drm_driver_has_device_list(void) {
++ return offsetof(struct drm_driver, device_list);
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_DRIVER_HAS_DEVICE_LIST" "" "types"
++ ;;
++
++
++ drm_driver_has_legacy_dev_list)
++ #
++ # Determine if the 'drm_driver' structure has a
'legacy_dev_list' field.
++ #
++ # drm_driver::device_list was added by:
++ # 2008-11-28 e7f7ab45ebcb54fd5f814ea15ea079e079662f67
++ # and then renamed to drm_driver::legacy_device_list by:
++ # 2013-12-11 b3f2333de8e81b089262b26d52272911523e605f
++ #
++ # The commit 57bb1ee60340 ("drm: Compile out legacy chunks from
++ # struct drm_device") compiles out the legacy chunks like
++ # drm_driver::legacy_dev_list.
++ #
++ CODE="
++ #if defined(NV_DRM_DRMP_H_PRESENT)
++ #include <drm/drmP.h>
++ #endif
++
++ #if defined(NV_DRM_DRM_DRV_H_PRESENT)
++ #include <drm/drm_drv.h>
++ #endif
++
++ int conftest_drm_driver_has_legacy_dev_list(void) {
++ return offsetof(struct drm_driver, legacy_dev_list);
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_DRIVER_HAS_LEGACY_DEV_LIST" "" "types"
++ ;;
++
++ jiffies_to_timespec)
++ #
++ # Determine if jiffies_to_timespec() is present
++ #
++ # removed by commit 751addac78b6
++ # ("y2038: remove obsolete jiffies conversion functions")
++ # in v5.6-rc1 (2019-12-13).
++ CODE="
++ #include <linux/jiffies.h>
++ void conftest_jiffies_to_timespec(void){
++ jiffies_to_timespec();
++ }"
++ compile_check_conftest "$CODE"
"NV_JIFFIES_TO_TIMESPEC_PRESENT" "" "functions"
++ ;;
++
++ drm_init_function_args)
++ #
++ # Determine if these functions:
++ # drm_universal_plane_init()
++ # drm_crtc_init_with_planes()
++ # drm_encoder_init()
++ # have a 'name' argument, which was added by these commits:
++ # drm_universal_plane_init: 2015-12-09
b0b3b7951114315d65398c27648705ca1c322faa
++ # drm_crtc_init_with_planes: 2015-12-09
f98828769c8838f526703ef180b3088a714af2f9
++ # drm_encoder_init: 2015-12-09
13a3d91f17a5f7ed2acd275d18b6acfdb131fb15
++ #
++ # Additionally determine whether drm_universal_plane_init() has a
++ # 'format_modifiers' argument, which was added by:
++ # 2017-07-23 e6fc3b68558e4c6d8d160b5daf2511b99afa8814
++ #
++ CODE="
++ #if defined(NV_DRM_DRMP_H_PRESENT)
++ #include <drm/drmP.h>
++ #endif
++
++ #if defined(NV_DRM_DRM_CRTC_H_PRESENT)
++ #include <drm/drm_crtc.h>
++ #endif
++
++ int conftest_drm_crtc_init_with_planes_has_name_arg(void) {
++ return
++ drm_crtc_init_with_planes(
++ NULL, /* struct drm_device *dev */
++ NULL, /* struct drm_crtc *crtc */
++ NULL, /* struct drm_plane *primary */
++ NULL, /* struct drm_plane *cursor */
++ NULL, /* const struct drm_crtc_funcs *funcs */
++ NULL); /* const char *name */
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_CRTC_INIT_WITH_PLANES_HAS_NAME_ARG" "" "types"
++
++ CODE="
++ #if defined(NV_DRM_DRMP_H_PRESENT)
++ #include <drm/drmP.h>
++ #endif
++
++ #if defined(NV_DRM_DRM_ENCODER_H_PRESENT)
++ #include <drm/drm_encoder.h>
++ #endif
++
++ int conftest_drm_encoder_init_has_name_arg(void) {
++ return
++ drm_encoder_init(
++ NULL, /* struct drm_device *dev */
++ NULL, /* struct drm_encoder *encoder */
++ NULL, /* const struct drm_encoder_funcs *funcs */
++ DRM_MODE_ENCODER_NONE, /* int encoder_type */
++ NULL); /* const char *name */
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_ENCODER_INIT_HAS_NAME_ARG" "" "types"
++
++ echo "$CONFTEST_PREAMBLE
++ #if defined(NV_DRM_DRMP_H_PRESENT)
++ #include <drm/drmP.h>
++ #endif
++
++ #if defined(NV_DRM_DRM_PLANE_H_PRESENT)
++ #include <drm/drm_plane.h>
++ #endif
++
++ int conftest_drm_universal_plane_init_has_format_modifiers_arg(void) {
++ return
++ drm_universal_plane_init(
++ NULL, /* struct drm_device *dev */
++ NULL, /* struct drm_plane *plane */
++ 0, /* unsigned long possible_crtcs */
++ NULL, /* const struct drm_plane_funcs *funcs */
++ NULL, /* const uint32_t *formats */
++ 0, /* unsigned int format_count */
++ NULL, /* const uint64_t *format_modifiers */
++ DRM_PLANE_TYPE_PRIMARY,
++ NULL); /* const char *name */
++ }" > conftest$$.c
++
++ $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
++
++ if [ -f conftest$$.o ]; then
++ rm -f conftest$$.o
++
++ echo "#define
NV_DRM_UNIVERSAL_PLANE_INIT_HAS_FORMAT_MODIFIERS_ARG" | append_conftest
"types"
++ echo "#define NV_DRM_UNIVERSAL_PLANE_INIT_HAS_NAME_ARG" |
append_conftest "types"
++ else
++ echo "#undef
NV_DRM_UNIVERSAL_PLANE_INIT_HAS_FORMAT_MODIFIERS_ARG" | append_conftest
"types"
++
++ echo "$CONFTEST_PREAMBLE
++ #if defined(NV_DRM_DRMP_H_PRESENT)
++ #include <drm/drmP.h>
++ #endif
++
++ #if defined(NV_DRM_DRM_PLANE_H_PRESENT)
++ #include <drm/drm_plane.h>
++ #endif
++
++ int conftest_drm_universal_plane_init_has_name_arg(void) {
++ return
++ drm_universal_plane_init(
++ NULL, /* struct drm_device *dev */
++ NULL, /* struct drm_plane *plane */
++ 0, /* unsigned long possible_crtcs */
++ NULL, /* const struct drm_plane_funcs *funcs */
++ NULL, /* const uint32_t *formats */
++ 0, /* unsigned int format_count */
++ DRM_PLANE_TYPE_PRIMARY,
++ NULL); /* const char *name */
++ }" > conftest$$.c
++
++ $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
++
++ if [ -f conftest$$.o ]; then
++ rm -f conftest$$.o
++
++ echo "#define NV_DRM_UNIVERSAL_PLANE_INIT_HAS_NAME_ARG" |
append_conftest "types"
++ else
++ echo "#undef NV_DRM_UNIVERSAL_PLANE_INIT_HAS_NAME_ARG" |
append_conftest "types"
++ fi
++ fi
++
++ ;;
++
++ drm_mode_connector_list_update_has_merge_type_bits_arg)
++ #
++ # Detect if drm_mode_connector_list_update() has a
++ # 'merge_type_bits' second argument. This argument was
++ # remove by:
++ # 2015-12-03 6af3e6561243f167dabc03f732d27ff5365cd4a4
++ #
++ CODE="
++ #include <drm/drmP.h>
++ void conftest_drm_mode_connector_list_update_has_merge_type_bits_arg(void)
{
++ drm_mode_connector_list_update(
++ NULL, /* struct drm_connector *connector */
++ true); /* bool merge_type_bits */
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_MODE_CONNECTOR_LIST_UPDATE_HAS_MERGE_TYPE_BITS_ARG" ""
"types"
++ ;;
++
++ vzalloc)
++ #
++ # Determine if the vzalloc function is present
++ # Added in 2.6.37 2010-10-26 e1ca7788dec6773b1a2bce51b7141948f2b8bccf
++ #
++ CODE="
++ #include <linux/vmalloc.h>
++ void conftest_vzalloc() {
++ vzalloc();
++ }"
++
++ compile_check_conftest "$CODE" "NV_VZALLOC_PRESENT"
"" "functions"
++ ;;
++
++ drm_driver_has_set_busid)
++ #
++ # Determine if the drm_driver structure has a 'set_busid' callback
++ # field.
++ #
++ # drm_driver::set_busid field were added by:
++ # 2014-08-29 915b4d11b8b9e7b84ba4a4645b6cc7fbc0c071cf
++ #
++ CODE="
++ #if defined(NV_DRM_DRMP_H_PRESENT)
++ #include <drm/drmP.h>
++ #endif
++
++ int conftest_drm_driver_has_set_busid(void) {
++ return offsetof(struct drm_driver, set_busid);
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_DRIVER_HAS_SET_BUSID" "" "types"
++ ;;
++
++ drm_driver_has_gem_prime_res_obj)
++ #
++ # Determine if the drm_driver structure has a 'gem_prime_res_obj'
++ # callback field.
++ #
++ # drm_driver::gem_prime_res_obj field was added by:
++ # 2014-07-01 3aac4502fd3f80dcf7e65dbf6edd8676893c1f46
++ #
++ # Removed by commit 51c98747113e (drm/prime: Ditch
++ # gem_prime_res_obj hook) in v5.4.
++ #
++ CODE="
++ #if defined(NV_DRM_DRMP_H_PRESENT)
++ #include <drm/drmP.h>
++ #endif
++
++ int conftest_drm_driver_has_gem_prime_res_obj(void) {
++ return offsetof(struct drm_driver, gem_prime_res_obj);
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_DRIVER_HAS_GEM_PRIME_RES_OBJ" "" "types"
++ ;;
++
++ drm_crtc_state_has_connectors_changed)
++ #
++ # Determine if the crtc_state has a 'connectors_changed' field.
++ #
++ # drm_crtc_state::connectors_changed was added by:
++ # 2015-07-21 fc596660dd4e83f7f84e3cd7b25dc5e8e83000ef
++ #
++ CODE="
++ #include <drm/drm_crtc.h>
++ void conftest_drm_crtc_state_has_connectors_changed(void) {
++ struct drm_crtc_state foo;
++ (void)foo.connectors_changed;
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_CRTC_STATE_HAS_CONNECTORS_CHANGED" "" "types"
++ ;;
++
++ drm_reinit_primary_mode_group)
++ #
++ # Determine if the function drm_reinit_primary_mode_group() is
++ # present.
++ #
++ # drm_reinit_primary_mode_group was added by:
++ # 2014-06-05 2390cd11bfbe8d2b1b28c4e0f01fe7e122f7196d
++ # removed by commit:
++ # 2015-07-09 3fdefa399e4644399ce3e74e65a75122d52dba6a
++ #
++ CODE="
++ #if defined(NV_DRM_DRM_CRTC_H_PRESENT)
++ #include <drm/drm_crtc.h>
++ #endif
++ void conftest_drm_reinit_primary_mode_group(void) {
++ drm_reinit_primary_mode_group();
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_REINIT_PRIMARY_MODE_GROUP_PRESENT" "" "functions"
++ ;;
++
++ wait_on_bit_lock_argument_count)
++ #
++ # Determine how many arguments wait_on_bit_lock takes.
++ #
++ # wait_on_bit_lock changed by
++ # 2014-07-07 743162013d40ca612b4cb53d3a200dff2d9ab26e
++ #
++ echo "$CONFTEST_PREAMBLE
++ #include <linux/wait.h>
++ void conftest_wait_on_bit_lock(void) {
++ wait_on_bit_lock(NULL, 0, 0);
++ }" > 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 "#define NV_WAIT_ON_BIT_LOCK_ARGUMENT_COUNT 3" |
append_conftest "functions"
++ return
++ fi
++
++ echo "$CONFTEST_PREAMBLE
++ #include <linux/wait.h>
++ void conftest_wait_on_bit_lock(void) {
++ wait_on_bit_lock(NULL, 0, NULL, 0);
++ }" > 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 "#define NV_WAIT_ON_BIT_LOCK_ARGUMENT_COUNT 4" |
append_conftest "functions"
++ return
++ fi
++ echo "#error wait_on_bit_lock() conftest failed!" |
append_conftest "functions"
++ ;;
++
++ bitmap_clear)
++ #
++ # Determine if the bitmap_clear function is present
++ # Added in 2.6.33 2009-12-15 c1a2a962a2ad103846e7950b4591471fabecece7
++ #
++ CODE="
++ #include <linux/bitmap.h>
++ void conftest_bitmap_clear() {
++ bitmap_clear();
++ }"
++
++ compile_check_conftest "$CODE" "NV_BITMAP_CLEAR_PRESENT"
"" "functions"
++ ;;
++
++ pci_stop_and_remove_bus_device)
++ #
++ # Determine if the pci_stop_and_remove_bus_device() function is present.
++ # Added in 3.4-rc1 2012-02-25 210647af897af8ef2d00828aa2a6b1b42206aae6
++ #
++ CODE="
++ #include <linux/types.h>
++ #include <linux/pci.h>
++ void conftest_pci_stop_and_remove_bus_device() {
++ pci_stop_and_remove_bus_device();
++ }"
++
++ compile_check_conftest "$CODE"
"NV_PCI_STOP_AND_REMOVE_BUS_DEVICE_PRESENT" "" "functions"
++ ;;
++
++ pci_remove_bus_device)
++ #
++ # Determine if the pci_remove_bus_device() function is present.
++ # Added before Linux-2.6.12-rc2 2005-04-16
++ #
++ CODE="
++ #include <linux/types.h>
++ #include <linux/pci.h>
++ void conftest_pci_remove_bus_device() {
++ pci_remove_bus_device();
++ }"
++
++ compile_check_conftest "$CODE"
"NV_PCI_REMOVE_BUS_DEVICE_PRESENT" "" "functions"
++ ;;
++
++ drm_atomic_set_mode_for_crtc)
++ #
++ # Determine if the function drm_atomic_set_mode_for_crtc() is
++ # present.
++ #
++ # drm_atomic_set_mode_for_crtc() was added by:
++ # 2015-05-26 819364da20fd914aba2fd03e95ee0467286752f5
++ #
++ CODE="
++ #if defined(NV_DRM_DRM_ATOMIC_H_PRESENT)
++ #include <drm/drm_atomic.h>
++ #endif
++ void conftest_drm_atomic_clean_old_fb(void) {
++ drm_atomic_set_mode_for_crtc();
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_ATOMIC_SET_MODE_FOR_CRTC" "" "functions"
++ ;;
++
++ drm_atomic_clean_old_fb)
++ #
++ # Determine if the function drm_atomic_clean_old_fb() is
++ # present.
++ #
++ # drm_atomic_clean_old_fb() was added by:
++ # 2015-11-11 0f45c26fc302c02b0576db37d4849baa53a2bb41
++ #
++ CODE="
++ #if defined(NV_DRM_DRM_ATOMIC_H_PRESENT)
++ #include <drm/drm_atomic.h>
++ #endif
++ void conftest_drm_atomic_clean_old_fb(void) {
++ drm_atomic_clean_old_fb();
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_ATOMIC_CLEAN_OLD_FB" "" "functions"
++ ;;
++
++ drm_helper_mode_fill_fb_struct |
drm_helper_mode_fill_fb_struct_has_const_mode_cmd_arg)
++ #
++ # Determine if the drm_helper_mode_fill_fb_struct function takes
++ # 'dev' argument.
++ #
++ # The drm_helper_mode_fill_fb_struct() has been updated to
++ # take 'dev' parameter by:
++ # 2016-12-14 a3f913ca98925d7e5bae725e9b2b38408215a695
++ #
++ echo "$CONFTEST_PREAMBLE
++ #include <drm/drm_crtc_helper.h>
++ void drm_helper_mode_fill_fb_struct(struct drm_device *dev,
++ struct drm_framebuffer *fb,
++ const struct drm_mode_fb_cmd2
*mode_cmd)
++ {
++ return;
++ }" > conftest$$.c;
++
++ $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
++ rm -f conftest$$.c
++
++ if [ -f conftest$$.o ]; then
++ echo "#define NV_DRM_HELPER_MODE_FILL_FB_STRUCT_HAS_DEV_ARG" |
append_conftest "function"
++ echo "#define
NV_DRM_HELPER_MODE_FILL_FB_STRUCT_HAS_CONST_MODE_CMD_ARG" | append_conftest
"function"
++ rm -f conftest$$.o
++ else
++ echo "#undef NV_DRM_HELPER_MODE_FILL_FB_STRUCT_HAS_DEV_ARG" |
append_conftest "function"
++
++ #
++ # Determine if the drm_mode_fb_cmd2 pointer argument is const in
++ # drm_mode_config_funcs::fb_create and
drm_helper_mode_fill_fb_struct().
++ #
++ # The drm_mode_fb_cmd2 pointer through this call chain was made const
by:
++ # 2015-11-11 1eb83451ba55d7a8c82b76b1591894ff2d4a95f2
++ #
++ echo "$CONFTEST_PREAMBLE
++ #include <drm/drm_crtc_helper.h>
++ void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
++ const struct drm_mode_fb_cmd2
*mode_cmd)
++ {
++ return;
++ }" > conftest$$.c;
++
++ $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
++ rm -f conftest$$.c
++
++ if [ -f conftest$$.o ]; then
++ echo "#define
NV_DRM_HELPER_MODE_FILL_FB_STRUCT_HAS_CONST_MODE_CMD_ARG" | append_conftest
"function"
++ rm -f conftest$$.o
++ else
++ echo "#undef
NV_DRM_HELPER_MODE_FILL_FB_STRUCT_HAS_CONST_MODE_CMD_ARG" | append_conftest
"function"
++ fi
++ fi
++ ;;
++
++ mm_context_t)
++ #
++ # Determine if the 'mm_context_t' data type is present
++ # and if it has an 'id' member.
++ #
++ echo "$CONFTEST_PREAMBLE
++ #include <linux/mm.h>
++ int conftest_mm_context_t(void) {
++ return offsetof(mm_context_t, id);
++ }" > conftest$$.c
++
++ $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
++ rm -f conftest$$.c
++
++ if [ -f conftest$$.o ]; then
++ echo "#define NV_MM_CONTEXT_T_HAS_ID" | append_conftest
"types"
++ rm -f conftest$$.o
++ return
++ else
++ echo "#undef NV_MM_CONTEXT_T_HAS_ID" | append_conftest
"types"
++ return
++ fi
++ ;;
+ get_user_pages)
+ #
+ # Conftest for get_user_pages()
+@@ -1886,7 +2977,7 @@
+ # 2016 Oct 12: 768ae309a96103ed02eb1e111e838c87854d8b51
+ #
+ # linux-4.4.168 cherry-picked commit 768ae309a961 without
+- # c12d2da56d0e which is covered in Conftest #3
++ # c12d2da56d0e which is covered in Conftest #3.
+ #
+ # Conftest #1: Check if get_user_pages accepts 6 arguments.
+ # Return if true.
+@@ -1966,7 +3057,6 @@
+ return
+ fi
+
+-
+ echo "#define NV_GET_USER_PAGES_HAS_WRITE_AND_FORCE_ARGS" |
append_conftest "functions"
+ echo "#define NV_GET_USER_PAGES_HAS_TASK_STRUCT" | append_conftest
"functions"
+
+@@ -1976,7 +3066,7 @@
+ get_user_pages_remote)
+ #
+ # Determine if the function get_user_pages_remote() is
+- # present and has write/force parameters.
++ # present and has write/force/locked/tsk parameters.
+ #
+ # get_user_pages_remote() was added by:
+ # 2016 Feb 12: 1e9877902dc7e11d2be038371c6fbf2dfcd469d7
+@@ -1989,13 +3079,17 @@
+ # get_user_pages_remote() added 'locked' parameter
+ # 2016 Dec 14:5b56d49fc31dbb0487e14ead790fc81ca9fb2c99
+ #
++ # get_user_pages_remote() removed 'tsk' parameter by
++ # commit 64019a2e467a ("mm/gup: remove task_struct pointer for
++ # all gup code") in v5.9-rc1 (2020-08-11).
++ #
+ # conftest #1: check if get_user_pages_remote() is available
+ # return if not available.
+ # Fall through to conftest #2 if it is present
+
+ echo "$CONFTEST_PREAMBLE
+ #include <linux/mm.h>
+- int conftest_get_user_pages_remote(void) {
++ void conftest_get_user_pages_remote(void) {
+ get_user_pages_remote();
+ }" > conftest$$.c
+
+@@ -2004,6 +3098,7 @@
+
+ if [ -f conftest$$.o ]; then
+ echo "#undef NV_GET_USER_PAGES_REMOTE_PRESENT" |
append_conftest "functions"
++ echo "#undef NV_GET_USER_PAGES_REMOTE_HAS_TSK_ARG" |
append_conftest "functions"
+ echo "#undef
NV_GET_USER_PAGES_REMOTE_HAS_WRITE_AND_FORCE_ARGS" | append_conftest
"functions"
+ echo "#undef NV_GET_USER_PAGES_REMOTE_HAS_LOCKED_ARG" |
append_conftest "functions"
+ rm -f conftest$$.o
+@@ -2031,14 +3126,20 @@
+ rm -f conftest$$.c
+
+ if [ -f conftest$$.o ]; then
++ echo "#define NV_GET_USER_PAGES_REMOTE_HAS_TSK_ARG" |
append_conftest "functions"
+ echo "#define
NV_GET_USER_PAGES_REMOTE_HAS_WRITE_AND_FORCE_ARGS" | append_conftest
"functions"
+ echo "#undef NV_GET_USER_PAGES_REMOTE_HAS_LOCKED_ARG" |
append_conftest "functions"
+ rm -f conftest$$.o
+ return
+ fi
+
++ echo "#undef NV_GET_USER_PAGES_REMOTE_HAS_WRITE_AND_FORCE_ARGS" |
append_conftest "functions"
++
++ #
+ # conftest #3: check if get_user_pages_remote() has locked argument
+-
++ # Return if these arguments are present. Fall through to conftest #4
++ # if these args are absent.
++ #
+ echo "$CONFTEST_PREAMBLE
+ #include <linux/mm.h>
+ long get_user_pages_remote(struct task_struct *tsk,
+@@ -2056,95 +3157,438 @@
+ rm -f conftest$$.c
+
+ if [ -f conftest$$.o ]; then
++ echo "#define NV_GET_USER_PAGES_REMOTE_HAS_TSK_ARG" |
append_conftest "functions"
++ echo "#define NV_GET_USER_PAGES_REMOTE_HAS_LOCKED_ARG" |
append_conftest "functions"
++ rm -f conftest$$.o
++ return
++ fi
++
++ #
++ # conftest #4: check if get_user_pages_remote() does not take
++ # tsk argument.
++ #
++ echo "$CONFTEST_PREAMBLE
++ #include <linux/mm.h>
++ long get_user_pages_remote(struct mm_struct *mm,
++ unsigned long start,
++ unsigned long nr_pages,
++ unsigned int gup_flags,
++ struct page **pages,
++ struct vm_area_struct **vmas,
++ int *locked) {
++ return 0;
++ }" > conftest$$.c
++
++ $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
++ rm -f conftest$$.c
++
++ if [ -f conftest$$.o ]; then
++ echo "#undef NV_GET_USER_PAGES_REMOTE_HAS_TSK_ARG" |
append_conftest "functions"
+ echo "#define NV_GET_USER_PAGES_REMOTE_HAS_LOCKED_ARG" |
append_conftest "functions"
+ rm -f conftest$$.o
+ else
++
++ echo "#define NV_GET_USER_PAGES_REMOTE_HAS_TSK_ARG" |
append_conftest "functions"
+ echo "#undef NV_GET_USER_PAGES_REMOTE_HAS_LOCKED_ARG" |
append_conftest "functions"
+ fi
+- echo "#undef NV_GET_USER_PAGES_REMOTE_HAS_WRITE_AND_FORCE_ARGS" |
append_conftest "functions"
++ ;;
++
++ usleep_range)
++ #
++ # Determine if the function usleep_range() is present.
++ #
++ # usleep_range() was added by:
++ # 2010 Aug 4 : 5e7f5a178bba45c5aca3448fddecabd4e28f1f6b
++ #
++ CODE="
++ #include <linux/delay.h>
++ void conftest_usleep_range(void) {
++ usleep_range();
++ }"
+
++ compile_check_conftest "$CODE" "NV_USLEEP_RANGE_PRESENT"
"" "functions"
+ ;;
+
+- drm_driver_unload_has_int_return_type)
++ radix_tree_empty)
+ #
+- # Determine if drm_driver::unload() returns integer value, which has
+- # been changed to void by commit -
++ # Determine if the function radix_tree_empty() is present.
+ #
+- # 2017-01-06 11b3c20bdd15d17382068be569740de1dccb173d
++ # radix_tree_empty() was added by:
++ # 2016 May 21 : e9256efcc8e390fa4fcf796a0c0b47d642d77d32
+ #
+ CODE="
++ #include <linux/radix-tree.h>
++ int conftest_radix_tree_empty(void) {
++ radix_tree_empty();
++ }"
++
++ compile_check_conftest "$CODE"
"NV_RADIX_TREE_EMPTY_PRESENT" "" "functions"
++ ;;
++
++ drm_gem_object_lookup)
++ #
++ # Determine the number of arguments of drm_gem_object_lookup().
++ #
++ # drm_gem_object_lookup() was originally added to the kernel by:
++ # 2008-07-30 : 673a394b1e3b69be886ff24abfd6df97c52e8d08
++ #
++ # First argument of type drm_device has been removed by:
++ # 2016-05-09 : a8ad0bd84f986072314595d05444719fdf29e412
++ #
++ echo "$CONFTEST_PREAMBLE
+ #if defined(NV_DRM_DRMP_H_PRESENT)
+ #include <drm/drmP.h>
+ #endif
++ #if defined(NV_DRM_DRM_GEM_H_PRESENT)
++ #include <drm/drm_gem.h>
++ #endif
++ void conftest_drm_gem_object_lookup(void) {
++ drm_gem_object_lookup(NULL, NULL, 0);
++ }" > conftest$$.c
+
+- #if defined(NV_DRM_DRM_DRV_H_PRESENT)
+- #include <drm/drm_drv.h>
++ $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
++ rm -f conftest$$.c
++
++ if [ -f conftest$$.o ]; then
++ echo "#define NV_DRM_GEM_OBJECT_LOOKUP_PRESENT" |
append_conftest "functions"
++ echo "#define NV_DRM_GEM_OBJECT_LOOKUP_ARGUMENT_COUNT 3" |
append_conftest "functions"
++ rm -f conftest$$.o
++ return
++ fi
++
++ echo "$CONFTEST_PREAMBLE
++ #if defined(NV_DRM_DRMP_H_PRESENT)
++ #include <drm/drmP.h>
+ #endif
++ #if defined(NV_DRM_DRM_GEM_H_PRESENT)
++ #include <drm/drm_gem.h>
++ #endif
++ void conftest_drm_gem_object_lookup(void) {
++ drm_gem_object_lookup(NULL, 0);
++ }" > conftest$$.c
+
+- int conftest_drm_driver_unload_has_int_return_type(struct drm_driver *drv)
{
+- return drv->unload(NULL /* dev */);
+- }
+- "
++ $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
++ rm -f conftest$$.c
+
+- compile_check_conftest "$CODE"
"NV_DRM_DRIVER_UNLOAD_HAS_INT_RETURN_TYPE" "" "types"
++ if [ -f conftest$$.o ]; then
++ echo "#define NV_DRM_GEM_OBJECT_LOOKUP_PRESENT" |
append_conftest "functions"
++ echo "#define NV_DRM_GEM_OBJECT_LOOKUP_ARGUMENT_COUNT 2" |
append_conftest "functions"
++ rm -f conftest$$.o
++ else
++ echo "#undef NV_DRM_GEM_OBJECT_LOOKUP_PRESENT" |
append_conftest "functions"
++ echo "#undef NV_DRM_GEM_OBJECT_LOOKUP_ARGUMENT_COUNT" |
append_conftest "functions"
++ fi
+ ;;
+
+- drm_get_pci_dev)
++ drm_master_drop_has_from_release_arg)
+ #
+- # Determine if drm_get_pci_dev() is present.
++ # Determine if drm_driver::master_drop() has 'from_release'
argument.
++ #
++ # Last argument 'bool from_release' has been removed by:
++ # 2016-06-21 : d6ed682eba54915ea56315bc2e5a33fca5922997
+ #
+ CODE="
+ #if defined(NV_DRM_DRMP_H_PRESENT)
+ #include <drm/drmP.h>
+ #endif
+
+- #if defined(NV_DRM_DRM_PCI_H_PRESENT)
+- #include <drm/drm_pci.h>
++ void conftest_drm_master_drop_has_from_release_arg(struct drm_driver *drv)
{
++ drv->master_drop(NULL, NULL, false);
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_MASTER_DROP_HAS_FROM_RELEASE_ARG" "" "types"
++ ;;
++
++ drm_mode_config_funcs_has_atomic_state_alloc)
++ #
++ # Determine if the 'drm_mode_config_funcs' structure has
++ # an 'atomic_state_alloc' field.
++ #
++ # added: 2015-05-18 036ef5733ba433760a3512bb5f7a155946e2df05
++ #
++ CODE="
++ #include <drm/drm_crtc.h>
++ int conftest_drm_mode_config_funcs_has_atomic_state_alloc(void) {
++ return offsetof(struct drm_mode_config_funcs, atomic_state_alloc);
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_MODE_CONFIG_FUNCS_HAS_ATOMIC_STATE_ALLOC" ""
"types"
++ ;;
++
++ drm_atomic_modeset_nonblocking_commit_available)
++ #
++ # Determine if nonblocking commit support avaiable in the DRM atomic
++ # modesetting subsystem.
++ #
++ # added: 2016-05-08 9f2a7950e77abf00a2a87f3b4cbefa36e9b6009b
++ #
++ CODE="
++ #include <drm/drm_crtc.h>
++ int conftest_drm_atomic_modeset_nonblocking_commit_available(void) {
++ return offsetof(struct drm_mode_config, helper_private);
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_ATOMIC_MODESET_NONBLOCKING_COMMIT_AVAILABLE" ""
"generic"
++ ;;
++
++ drm_atomic_state_ref_counting)
++ #
++ # Determine if functions drm_atomic_state_get/put() are
++ # present.
++ #
++ # Added by commit 0853695c3ba4 ("drm: Add reference counting to
++ # drm_atomic_state") in v4.10 (2016-10-14)
++ #
++ CODE="
++ #if defined(NV_DRM_DRM_ATOMIC_H_PRESENT)
++ #include <drm/drm_atomic.h>
+ #endif
++ void conftest_drm_atomic_state_get(void) {
++ drm_atomic_state_get();
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_ATOMIC_STATE_REF_COUNTING_PRESENT" "" "functions"
++ ;;
+
+- void conftest_drm_legacy_pci_init(void) {
+- drm_get_pci_dev();
++ vm_ops_fault_removed_vma_arg)
++ #
++ # Determine if vma.vm_ops.fault takes (vma, vmf), or just (vmf)
++ # args. Acronym key:
++ # vma: struct vm_area_struct
++ # vm_ops: struct vm_operations_struct
++ # vmf: struct vm_fault
++ #
++ # The redundant vma arg was removed from BOTH vma.vm_ops.fault and
++ # vma.vm_ops.page_mkwrite, with the following commit:
++ #
++ # 2017-02-24 11bac80004499ea59f361ef2a5516c84b6eab675
++ #
++ CODE="
++ #include <linux/mm.h>
++ void conftest_vm_ops_fault_removed_vma_arg(void) {
++ struct vm_operations_struct vm_ops;
++ struct vm_fault *vmf;
++ (void)vm_ops.fault(vmf);
++ }"
++
++ compile_check_conftest "$CODE"
"NV_VM_OPS_FAULT_REMOVED_VMA_ARG" "" "types"
++ ;;
++
++ pnv_npu2_init_context)
++ #
++ # Determine if the pnv_npu2_init_context() function is
++ # present.
++ #
++ CODE="
++ #if defined(NV_ASM_POWERNV_H_PRESENT)
++ #include <linux/pci.h>
++ #include <asm/powernv.h>
++ #endif
++ void conftest_pnv_npu2_init_context(void) {
++ pnv_npu2_init_context();
+ }"
+
+- compile_check_conftest "$CODE"
"NV_DRM_GET_PCI_DEV_PRESENT" "" "functions"
++ compile_check_conftest "$CODE"
"NV_PNV_NPU2_INIT_CONTEXT_PRESENT" "" "functions"
+ ;;
+
+- drm_pci_init)
++ drm_driver_unload_has_int_return_type)
++ #
++ # Determine if drm_driver::unload() returns integer value, which has
++ # been changed to void by commit -
+ #
+- # Determine if drm_pci_init() is present.
++ # 2017-01-06 11b3c20bdd15d17382068be569740de1dccb173d
+ #
+ CODE="
+ #if defined(NV_DRM_DRMP_H_PRESENT)
+ #include <drm/drmP.h>
+ #endif
+
+- void conftest_drm_legacy_pci_init(void) {
+- drm_pci_init();
++ int conftest_drm_driver_unload_has_int_return_type(struct drm_driver *drv)
{
++ return drv->unload(NULL /* dev */);
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_DRIVER_UNLOAD_HAS_INT_RETURN_TYPE" "" "types"
++ ;;
++
++ kref_has_refcount_of_type_refcount_t)
++ CODE="
++ #include <linux/kref.h>
++
++ refcount_t conftest_kref_has_refcount_of_type_refcount_t(struct kref *ref)
{
++ return ref->refcount;
++ }"
++
++ compile_check_conftest "$CODE"
"NV_KREF_HAS_REFCOUNT_OF_TYPE_REFCOUNT_T" "" "types"
++ ;;
++
++ is_export_symbol_present_*)
++ export_symbol_present_conftest $(echo $1 | cut -f5- -d_)
++ ;;
++
++ is_export_symbol_gpl_*)
++ export_symbol_gpl_conftest $(echo $1 | cut -f5- -d_)
++ ;;
++
++ drm_atomic_helper_disable_all)
++ #
++ # Determine if the function drm_atomic_helper_disable_all() is
++ # present.
++ #
++ # drm_atomic_helper_disable_all() has been added by:
++ # 2015-12-02 1494276000db789c6d2acd85747be4707051c801
++ #
++ CODE="
++ #if defined(NV_DRM_DRM_ATOMIC_HELPER_H_PRESENT)
++ #include <drm/drm_atomic_helper.h>
++ #endif
++ void conftest_drm_atomic_helper_disable_all(void) {
++ drm_atomic_helper_disable_all();
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_ATOMIC_HELPER_DISABLE_ALL_PRESENT" "" "functions"
++ ;;
++
++ drm_atomic_helper_set_config)
++ #
++ # Determine if drm_atomic_helper_set_config() has 'ctx' argument.
++ #
++ # drm_atomic_helper_set_config() was added by:
++ # 2014-06-27 042652ed95996a9ef6dcddddc53b5d8bc7fa887e
++ # and it has been updated to take ctx parameter by:
++ # 2017-03-22 a4eff9aa6db8eb3d1864118f3558214b26f630b4
++ #
++ echo "$CONFTEST_PREAMBLE
++ #if defined(NV_DRM_DRM_ATOMIC_HELPER_H_PRESENT)
++ #include <drm/drm_atomic_helper.h>
++ #endif
++ void conftest_drm_atomic_helper_set_config(void) {
++ drm_atomic_helper_set_config();
++ }" > conftest$$.c
++
++ $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
++ rm -f conftest$$.c
++
++ if [ -f conftest$$.o ]; then
++ echo "#undef NV_DRM_ATOMIC_HELPER_SET_CONFIG_PRESENT" |
append_conftest "functions"
++ else
++ echo "#define NV_DRM_ATOMIC_HELPER_SET_CONFIG_PRESENT" |
append_conftest "functions"
++
++ echo "$CONFTEST_PREAMBLE
++ #include <drm/drm_atomic_helper.h>
++ int drm_atomic_helper_set_config(struct drm_mode_set *set,
++ struct drm_modeset_acquire_ctx *ctx) {
++ return 0;
++ }" > conftest$$.c
++
++ $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
++ rm -f conftest$$.c
++
++ if [ -f conftest$$.o ]; then
++ echo "#define NV_DRM_ATOMIC_HELPER_SET_CONFIG_HAS_CTX_ARG"
| append_conftest "types"
++ rm -f conftest$$.o
++ else
++ echo "#undef NV_DRM_ATOMIC_HELPER_SET_CONFIG_HAS_CTX_ARG"
| append_conftest "types"
++ fi
++ fi
++ ;;
++
++ drm_atomic_helper_crtc_destroy_state_has_crtc_arg)
++ #
++ # Determine if __drm_atomic_helper_crtc_destroy_state() has 'crtc'
++ # argument.
++ #
++ # __drm_atomic_helper_crtc_destroy_state() is updated to drop
++ # crtc argument by:
++ # 2016-05-09 ec2dc6a0fe38de8d73a7b7638a16e7d33a19a5eb
++ #
++ CODE="
++ #if defined(NV_DRM_DRM_ATOMIC_HELPER_H_PRESENT)
++ #include <drm/drm_atomic_helper.h>
++ #endif
++ void conftest_drm_atomic_helper_crtc_destroy_state_has_crtc_arg(void) {
++ __drm_atomic_helper_crtc_destroy_state(NULL, NULL);
+ }"
+
+- compile_check_conftest "$CODE" "NV_DRM_PCI_INIT_PRESENT"
"" "functions"
++ compile_check_conftest "$CODE"
"NV_DRM_ATOMIC_HELPER_CRTC_DESTROY_STATE_HAS_CRTC_ARG" ""
"types"
+ ;;
+
+- drm_legacy_pci_init)
++ drm_atomic_helper_connector_dpms)
+ #
+- # Determine if drm_legacy_pci_init() is present. drm_pci_init() was
+- # deprecated and renamed to drm_legacy_pci_init by:
++ # Determine if the function drm_atomic_helper_connector_dpms() is present.
+ #
+- # 2017-05-24 10631d724deff712343d96dd3017cd323349f761
++ # drm_atomic_helper_connector_dpms() was removed by:
++ # 2017-07-25 7d902c05b480cc44033dcb56e12e51b082656b42
+ #
+ CODE="
+- #if defined(NV_DRM_DRMP_H_PRESENT)
+- #include <drm/drmP.h>
++ #if defined(NV_DRM_DRM_ATOMIC_HELPER_H_PRESENT)
++ #include <drm/drm_atomic_helper.h>
+ #endif
++ void conftest_drm_atomic_helper_connector_dpms(void) {
++ drm_atomic_helper_connector_dpms();
++ }"
+
+- #if defined(NV_DRM_DRM_PCI_H_PRESENT)
+- #include <drm/drm_pci.h>
++ compile_check_conftest "$CODE"
"NV_DRM_ATOMIC_HELPER_CONNECTOR_DPMS_PRESENT" ""
"functions"
++ ;;
++
++ backlight_device_register)
++ #
++ # Determine if the backlight_device_register() function is present
++ # and how many arguments it takes.
++ #
++ # Don't try to support the 4-argument form of
backlight_device_register().
++ #
++ echo "$CONFTEST_PREAMBLE
++ #include <linux/backlight.h>
++ #if !defined(CONFIG_BACKLIGHT_CLASS_DEVICE)
++ #error Backlight class device not enabled
+ #endif
+- void conftest_drm_legacy_pci_init(void) {
+- drm_legacy_pci_init();
++ void conftest_backlight_device_register(void) {
++ backlight_device_register(NULL, NULL, NULL, NULL, NULL);
++ }" > 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 "#define NV_BACKLIGHT_DEVICE_REGISTER_PRESENT" |
append_conftest "functions"
++ return
++ else
++ echo "#undef NV_BACKLIGHT_DEVICE_REGISTER_PRESENT" |
append_conftest "functions"
++ return
++ fi
++ ;;
++
++ backlight_properties_type)
++ #
++ # Determine if the backlight_properties structure has a 'type'
field
++ # and whether BACKLIGHT_RAW is defined.
++ #
++ CODE="
++ #include <linux/backlight.h>
++ void conftest_backlight_props_type(void) {
++ struct backlight_properties tmp;
++ tmp.type = BACKLIGHT_RAW;
+ }"
+
+- compile_check_conftest "$CODE"
"NV_DRM_LEGACY_PCI_INIT_PRESENT" "" "functions"
++ compile_check_conftest "$CODE"
"NV_BACKLIGHT_PROPERTIES_TYPE_PRESENT" "" "types"
++ ;;
++
++ register_acpi_notifier)
++ #
++ # Determine if the register_acpi_notifier() and unregister_acpi_notifier()
++ # functions are present.
++ #
++ # register_acpi_notifier() and unregister_acpi_notifier() are
++ # added by:
++ # 2008-01-25 9ee85241fdaab358dff1d8647f20a478cfa512a1
++ #
++ CODE="
++ #include <acpi/acpi_bus.h>
++ int conftest_register_acpi_notifier(void) {
++ return register_acpi_notifier();
++ }"
++ compile_check_conftest "$CODE"
"NV_REGISTER_ACPI_NOTIFER_PRESENT" "" "functions"
+ ;;
+
+ timer_setup)
+@@ -2162,7 +3606,172 @@
+ compile_check_conftest "$CODE" "NV_TIMER_SETUP_PRESENT"
"" "functions"
+ ;;
+
+- do_gettimeofday)
++ radix_tree_replace_slot)
++ #
++ # Determine if the radix_tree_replace_slot() function is
++ # present and how many arguments it takes.
++ #
++ # radix_tree_replace_slot added
++ # 2006-12-06 7cf9c2c76c1a17b32f2da85b50cd4fe468ed44b5
++ # root parameter added to radix_tree_replace_slot in 4.10 (but the symbol
was not exported)
++ # 2016-12-12 6d75f366b9242f9b17ed7d0b0604d7460f818f21
++ # radix_tree_replace_slot symbol export was introduced in 4.11
++ # 2017-10-11 10257d719686706aa669b348309cfd9fd9783ad9
++ #
++ CODE="
++ #include <linux/bug.h>
++ #include <linux/version.h>
++ void conftest_radix_tree_replace_slot(void) {
++ BUILD_BUG_ON(LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) ||
LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0));
++ }"
++ compile_check_conftest "$CODE"
"NV_RADIX_TREE_REPLACE_SLOT_PRESENT" "" "functions"
++
++ echo "$CONFTEST_PREAMBLE
++ #include <linux/radix-tree.h>
++ void conftest_radix_tree_replace_slot(void) {
++ radix_tree_replace_slot(NULL, NULL);
++ }" > 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 "#define NV_RADIX_TREE_REPLACE_SLOT_ARGUMENT_COUNT 2" |
append_conftest "functions"
++ return
++ fi
++
++ echo "$CONFTEST_PREAMBLE
++ #include <linux/radix-tree.h>
++ void conftest_radix_tree_replace_slot(void) {
++ radix_tree_replace_slot(NULL, NULL, NULL);
++ }" > 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 "#define NV_RADIX_TREE_REPLACE_SLOT_ARGUMENT_COUNT 3" |
append_conftest "functions"
++ return
++ else
++ echo "#error radix_tree_replace_slot() conftest failed!" |
append_conftest "functions"
++ fi
++ ;;
++
++ drm_old_atomic_state_iterators_present)
++ #
++ # Determine if the old atomic state iterators
++ # for_each_crtc_in_state(), for_each_connector_in_state() and
++ # for_each_plane_in_state() are present.
++ #
++ # These old atomic state iterators were added by:
++ # 2015-04-10 df63b9994eaf942afcdb946d27a28661d7dfbf2a
++ # and they are removed by:
++ # 2017-07-19 77ac3b00b13185741effd0d5e2f1f05e4bfef7dc
++ #
++ CODE="
++ #include <drm/drmP.h>
++ #include <drm/drm_atomic.h>
++ void conftest_drm_old_atomic_state_iterators_present(void) {
++ struct drm_crtc_state *crtc_state;
++ struct drm_atomic_state *state;
++ struct drm_crtc *crtc;
++ int i;
++
++ for_each_crtc_in_state(state, crtc, crtc_state, i) {
++ }
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_OLD_ATOMIC_STATE_ITERATORS_PRESENT" | append_conftest "types"
++ ;;
++
++ drm_mode_object_find_has_file_priv_arg)
++ #
++ # Determine if drm_mode_object_find() has 'file_priv' arguments.
++ #
++ # The function drm_mode_object_find() was added by:
++ # 2008-11-07 f453ba0460742ad027ae0c4c7d61e62817b3e7ef
++ # and it is updated to take 'file_priv' argument by:
++ # 2017-03-14 418da17214aca5ef5f0b6f7588905ee7df92f98f
++ #
++ CODE="
++ #include <drm/drm_mode_object.h>
++ void conftest_drm_mode_object_find_has_file_priv_arg(
++ struct drm_device *dev,
++ struct drm_file *file_priv,
++ uint32_t id,
++ uint32_t type) {
++ (void)drm_mode_object_find(dev, file_priv, id, type);
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_MODE_OBJECT_FIND_HAS_FILE_PRIV_ARG" | append_conftest "types"
++ ;;
++ kmem_cache_create_usercopy)
++ #
++ # Determine if the kmem_cache_create_usercopy function exists.
++ #
++ # This function was added by:
++ # 2017-06-10 8eb8284b412906181357c2b0110d879d5af95e52
++ CODE="
++ #include <linux/slab.h>
++ void kmem_cache_create_usercopy(void) {
++ kmem_cache_create_usercopy();
++ }"
++
++ compile_check_conftest "$CODE"
"NV_KMEM_CACHE_CREATE_USERCOPY_PRESENT" "" "functions"
++ ;;
++
++ drm_connector_funcs_have_mode_in_name)
++ #
++ # Determine if _mode_ is present in connector function names.
++ #
++ # _mode_ has been dropped from connector function names by commits:
++ # 2018-07-09 c555f02371c338b06752577aebf738dbdb6907bd
++ # 2018-07-09 cde4c44d8769c1be16074c097592c46c7d64092b
++ # 2018-07-09 97e14fbeb53fe060c5f6a7a07e37fd24c087ed0c
++ #
++ CODE="
++ #include <drm/drm_connector.h>
++ void conftest_drm_connector_funcs_have_mode_in_name(void) {
++ drm_mode_connector_attach_encoder();
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_CONNECTOR_FUNCS_HAVE_MODE_IN_NAME" "" "functions"
++ ;;
++
++ vm_fault_t)
++ #
++ # Determine if vm_fault_t is present
++ #
++ # Added by commit 1c8f422059ae5da07db7406ab916203f9417e396 ("mm:
++ # change return type to vm_fault_t") in v4.17 (2018-04-05)
++ #
++ CODE="
++ #include <linux/mm.h>
++ vm_fault_t conftest_vm_fault_t;
++ "
++ compile_check_conftest "$CODE"
"NV_VM_FAULT_T_IS_PRESENT" "" "types"
++ ;;
++
++ vmf_insert_pfn)
++ #
++ # Determine if the function vmf_insert_pfn() is
++ # present.
++ #
++ # Added by commit 1c8f422059ae5da07db7406ab916203f9417e396 ("mm:
++ # change return type to vm_fault_t") in v4.17 (2018-04-05)
++ #
++ CODE="
++ #include <linux/mm.h>
++ void conftest_vmf_insert_pfn(void) {
++ vmf_insert_pfn();
++ }"
++
++ compile_check_conftest "$CODE"
"NV_VMF_INSERT_PFN_PRESENT" "" "functions"
++ ;;
++
++ do_gettimeofday)
+ #
+ # Determine if the function do_gettimeofday() is
+ # present.
+@@ -2190,9 +3799,32 @@
+ compile_check_conftest "$CODE"
"NV_DO_GETTIMEOFDAY_PRESENT" "" "functions"
+ ;;
+
+- drm_gem_object_put_unlocked)
++ drm_framebuffer_get)
+ #
+- # Determine if the function drm_gem_object_put_unlocked() is present.
++ # Determine if the function drm_framebuffer_get() is present.
++ #
++ # Added by commit a4a69da06bc11a937a6e417938b1bb698ee1fa46 (drm:
++ # Introduce drm_framebuffer_{get,put}()) on 2017-02-28.
++ #
++ CODE="
++ #if defined(NV_DRM_DRMP_H_PRESENT)
++ #include <drm/drmP.h>
++ #endif
++
++ #if defined(NV_DRM_DRM_FRAMEBUFFER_H_PRESENT)
++ #include <drm/drm_framebuffer.h>
++ #endif
++
++ void conftest_drm_framebuffer_get(void) {
++ drm_framebuffer_get();
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_FRAMEBUFFER_GET_PRESENT" "" "functions"
++ ;;
++
++ drm_gem_object_get)
++ #
++ # Determine if the function drm_gem_object_get() is present.
+ #
+ # Added by commit e6b62714e87c8811d5564b6a0738dcde63a51774 (drm:
+ # Introduce drm_gem_object_{get,put}()) on 2017-02-28.
+@@ -2205,20 +3837,19 @@
+ #if defined(NV_DRM_DRM_GEM_H_PRESENT)
+ #include <drm/drm_gem.h>
+ #endif
+- void conftest_drm_gem_object_put_unlocked(void) {
+- drm_gem_object_put_unlocked();
++ void conftest_drm_gem_object_get(void) {
++ drm_gem_object_get();
+ }"
+
+- compile_check_conftest "$CODE"
"NV_DRM_GEM_OBJECT_PUT_UNLOCKED_PRESENT" "" "functions"
++ compile_check_conftest "$CODE"
"NV_DRM_GEM_OBJECT_GET_PRESENT" "" "functions"
+ ;;
+
+- drm_driver_legacy_feature_bit_present)
++ drm_dev_put)
+ #
+- # Determine if the DRIVER_LEGACY feature bit is present, either as a
+- # preprocessor macro or in an enum.
++ # Determine if the function drm_dev_put() is present.
+ #
+- # The DRIVER_* feature bits were changed from CPP macros to an enum
+- # with commit 0e2a933b02c972919f7478364177eb76cd4ae00d (2019-01-29).
++ # Added by commit 9a96f55034e41b4e002b767e9218d55f03bdff7d (drm:
++ # introduce drm_dev_{get/put} functions) on 2017-09-26.
+ #
+ CODE="
+ #if defined(NV_DRM_DRMP_H_PRESENT)
+@@ -2228,14 +3859,108 @@
+ #if defined(NV_DRM_DRM_DRV_H_PRESENT)
+ #include <drm/drm_drv.h>
+ #endif
++ void conftest_drm_dev_put(void) {
++ drm_dev_put();
++ }"
++
++ compile_check_conftest "$CODE" "NV_DRM_DEV_PUT_PRESENT"
"" "functions"
++ ;;
++
++ drm_connector_list_iter)
++ #
++ # Determine if the drm_connector_list_iter struct is present.
++ #
++ # Added by commit 613051dac40da1751ab269572766d3348d45a197 ("drm:
++ # locking&new iterators for connector_list") in v4.11
(2016-12-14).
++ #
++ CODE="
++ #include <drm/drm_connector.h>
++ int conftest_drm_connector_list_iter(void) {
++ struct drm_connector_list_iter conn_iter;
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_CONNECTOR_LIST_ITER_PRESENT" "" "types"
++
++ #
++ # Determine if the function drm_connector_list_iter_get() is
++ # renamed to drm_connector_list_iter_begin().
++ #
++ # Renamed by b982dab1e66d2b998e80a97acb6eaf56518988d3 (drm: Rename
++ # connector list iterator API) in v4.12 (2017-02-28).
++ #
++ CODE="
++ #if defined(NV_DRM_DRM_CONNECTOR_H_PRESENT)
++ #include <drm/drm_connector.h>
++ #endif
++ void conftest_drm_connector_list_iter_begin(void) {
++ drm_connector_list_iter_begin();
++ }"
+
+- void conftest_drm_driver_legacy_feature_bit_present(struct drm_driver *drv)
{
+- drv->driver_features = DRIVER_LEGACY;
++ compile_check_conftest "$CODE"
"NV_DRM_CONNECTOR_LIST_ITER_BEGIN_PRESENT" "" "functions"
++ ;;
++
++ drm_atomic_helper_swap_state_has_stall_arg)
++ #
++ # Determine if drm_atomic_helper_swap_state() has 'stall' argument.
++ #
++ # drm_atomic_helper_swap_state() function prototype updated to take
++ # 'state' and 'stall' arguments by commit
++ # 5e84c2690b805caeff3b4c6c9564c7b8de54742d (drm/atomic-helper:
++ # Massage swap_state signature somewhat)
++ # in v4.8 (2016-06-10).
++ #
++ CODE="
++ #include <drm/drm_atomic_helper.h>
++ void conftest_drm_atomic_helper_swap_state_has_stall_arg(
++ struct drm_atomic_state *state,
++ bool stall) {
++ (void)drm_atomic_helper_swap_state(state, stall);
+ }"
+
+- compile_check_conftest "$CODE"
"NV_DRM_DRIVER_LEGACY_FEATURE_BIT_PRESENT" "" "types"
++ compile_check_conftest "$CODE"
"NV_DRM_ATOMIC_HELPER_SWAP_STATE_HAS_STALL_ARG" | append_conftest
"types"
++
++ #
++ # Determine if drm_atomic_helper_swap_state() returns int.
++ #
++ # drm_atomic_helper_swap_state() function prototype
++ # updated to return int by commit
++ # c066d2310ae9bbc695c06e9237f6ea741ec35e43 (drm/atomic: Change
++ # drm_atomic_helper_swap_state to return an error.) in v4.14
++ # (2017-07-11).
++ #
++ CODE="
++ #include <drm/drm_atomic_helper.h>
++ int conftest_drm_atomic_helper_swap_state_return_int(
++ struct drm_atomic_state *state,
++ bool stall) {
++ return drm_atomic_helper_swap_state(state, stall);
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_ATOMIC_HELPER_SWAP_STATE_RETURN_INT" | append_conftest
"types"
+ ;;
+
++ dma_direct_map_resource)
++ #
++ # Determine whether dma_is_direct() exists.
++ #
++ # dma_is_direct() was added by commit 356da6d0cde3 ("dma-mapping:
++ # bypass indirect calls for dma-direct") in (2018-12-06).
++ #
++ # If dma_is_direct() does exist, then we assume that
++ # dma_direct_map_resource() exists. Both functions were added
++ # as part of the same patchset.
++ #
++ # The presence of dma_is_direct() and dma_direct_map_resource()
++ # means that dma_direct can perform DMA mappings itself.
++ #
++ CODE="
++ #include <linux/dma-mapping.h>
++ void conftest_dma_is_direct(void) {
++ dma_is_direct();
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DMA_IS_DIRECT_PRESENT" "" "functions"
++ ;;
+
+ drm_driver_prime_flag_present)
+ #
+@@ -2262,6 +3987,7 @@
+ #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;
+ }"
+@@ -2269,12 +3995,453 @@
+ compile_check_conftest "$CODE"
"NV_DRM_DRIVER_PRIME_FLAG_PRESENT" "" "types"
+ ;;
+
++ drm_gem_prime_export_has_dev_arg)
++ #
++ # Determine if drm_driver::gem_prime_export() has 'dev' argument.
++ #
++ # The 'dev' argument has been dropped from
++ # drm_driver::gem_prime_export() by commit e4fa8457b219 (drm/prime:
++ # Align gem_prime_export with obj_funcs.export) in v5.4-rc1
++ # (2019-06-14).
++ #
++ CODE="
++ #include <drm/drmP.h>
++ #if defined(NV_DRM_DRM_DRV_H_PRESENT)
++ #include <drm/drm_drv.h>
++ #endif
++ struct dma_buf *conftest_drm_gem_prime_export_has_dev_arg(
++ struct drm_driver *drv,
++ struct drm_device *dev, struct drm_gem_object *obj, int flags) {
++ return drv->gem_prime_export(dev, obj, flags);
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_GEM_PRIME_EXPORT_HAS_DEV_ARG" "" "types"
++ ;;
++
++ drm_connector_for_each_possible_encoder)
++ #
++ # Determine the number of arguments of the
++ # drm_connector_for_each_possible_encoder() macro.
++ #
++ # drm_connector_for_each_possible_encoder() is added by commit
++ # 83aefbb887b5 (drm: Add drm_connector_for_each_possible_encoder())
++ # in v4.19. The definition and prorotype is changed to take only
++ # two arguments connector and encoder, by commit 62afb4ad425a
++ # (drm/connector: Allow max possible encoders to attach to a
++ # connector) in v5.5rc1.
++ #
++ echo "$CONFTEST_PREAMBLE
++ #if defined(NV_DRM_DRMP_H_PRESENT)
++ #include <drm/drmP.h>
++ #endif
++
++ #if defined(NV_DRM_CONNECTOR_H_PRESENT)
++ #include <drm/drm_connector.h>
++ #endif
++
++ void conftest_drm_connector_for_each_possible_encoder(
++ struct drm_connector *connector,
++ struct drm_encoder *encoder,
++ int i) {
++
++ drm_connector_for_each_possible_encoder(connector, encoder, i) {
++ }
++ }" > conftest$$.c
++
++ $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
++ rm -f conftest$$.c
++
++ if [ -f conftest$$.o ]; then
++ echo "#define
NV_DRM_CONNECTOR_FOR_EACH_POSSIBLE_ENCODER_ARGUMENT_COUNT 3" | append_conftest
"functions"
++ rm -f conftest$$.o
++ return
++ else
++ echo "#define
NV_DRM_CONNECTOR_FOR_EACH_POSSIBLE_ENCODER_ARGUMENT_COUNT 2" | append_conftest
"functions"
++ fi
++ ;;
++
++ drm_gem_object_has_resv)
++ #
++ # Determine if the 'drm_gem_object' structure has a 'resv'
field.
++ #
++ # A 'resv' filed in the 'drm_gem_object' structure, is added
by
++ # commit 1ba627148ef5 (drm: Add reservation_object to
++ # drm_gem_object) in v5.2.
++ #
++ CODE="$CONFTEST_PREAMBLE
++ #if defined(NV_DRM_DRM_GEM_H_PRESENT)
++ #include <drm/drm_gem.h>
++ #endif
++
++ int conftest_drm_gem_object_has_resv(void) {
++ return offsetof(struct drm_gem_object, resv);
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_GEM_OBJECT_HAS_RESV" "" "types"
++ ;;
++
++ proc_ops)
++ #
++ # Determine if the 'struct proc_ops' type is present.
++ #
++ # Added by commit d56c0d45f0e2 ("proc: decouple proc from VFS with
++ # "struct proc_ops"") in 5.6-rc1
++ #
++ CODE="
++ #include <linux/proc_fs.h>
++
++ struct proc_ops p_ops;
++ "
++
++ compile_check_conftest "$CODE" "NV_PROC_OPS_PRESENT"
"" "types"
++ ;;
++
++ timeval)
++ #
++ # Determine if the 'struct timeval' type is present.
++ #
++ # Removed by commit c766d1472c70 ("y2038: hide
++ # timeval/timespec/itimerval/itimerspec types") in 5.6-rc3
++ # (2020-02-20).
++ #
++ CODE="
++ #include <linux/time.h>
++
++ struct timeval tm;
++ "
++
++ compile_check_conftest "$CODE" "NV_TIMEVAL_PRESENT"
"" "types"
++ ;;
++
++ ktime_get_raw_ts64)
++ #
++ # Determine if ktime_get_raw_ts64() is present
++ #
++ # Added by commit fb7fcc96a86cf ("timekeeping: Standardize on
++ # ktime_get_*() naming") in 4.18 (2018-04-27)
++ #
++ CODE="
++ #include <linux/ktime.h>
++ void conftest_ktime_get_raw_ts64(void){
++ ktime_get_raw_ts64();
++ }"
++ compile_check_conftest "$CODE"
"NV_KTIME_GET_RAW_TS64_PRESENT" "" "functions"
++ ;;
++
++ ktime_get_real_ts64)
++ #
++ # Determine if ktime_get_real_ts64() is present
++ #
++ # Added by commit d6d29896c665d ("timekeeping: Provide timespec64
++ # based interfaces") in 3.17 (2014-07-16)
++ #
++ CODE="
++ #include <linux/ktime.h>
++ void conftest_ktime_get_real_ts64(void){
++ ktime_get_real_ts64();
++ }"
++ compile_check_conftest "$CODE"
"NV_KTIME_GET_REAL_TS64_PRESENT" "" "functions"
++ ;;
++
++ mm_has_mmap_lock)
++ #
++ # Determine if the 'mm_struct' structure has a 'mmap_lock'
field.
++ #
++ # Kernel commit da1c55f1b272 ("mmap locking API: rename mmap_sem
++ # to mmap_lock") replaced the field 'mmap_sem' by
'mmap_lock'
++ # in v5.8-rc1 (2020-06-08).
++ CODE="
++ #include <linux/mm_types.h>
++
++ int conftest_mm_has_mmap_lock(void) {
++ return offsetof(struct mm_struct, mmap_lock);
++ }"
++
++ compile_check_conftest "$CODE" "NV_MM_HAS_MMAP_LOCK"
"" "types"
++
++ ;;
++
++ pci_dev_has_skip_bus_pm)
++ #
++ # Determine if skip_bus_pm flag is present in struct pci_dev.
++ # Presence of this flag is used to determine whether a call to
++ # pci_{save/restore}_state()can be skipped and kernel PCI
++ # subsystem framework will take care of saving/restoring device
++ # state.
++ #
++ # Added by commit d491f2b75237 ("PCI: PM: Avoid possible
++ # suspend-to-idle issue") in 5.2-rc3 (2019-06-13)
++ #
++ CODE="
++ #include <linux/pci.h>
++ void conftest_pci_dev_has_skip_bus_pm(void) {
++ struct pci_dev dev;
++ (void)dev.skip_bus_pm;
++ }"
++
++ compile_check_conftest "$CODE"
"NV_PCI_DEV_HAS_SKIP_BUS_PM" "" "types"
++ ;;
++
++ vmalloc_has_pgprot_t_arg)
++ #
++ # Determine if __vmalloc has the 'pgprot' argument.
++ #
++ # The third argument to __vmalloc, page protection
++ # 'pgprot_t prot', was removed by commit 88dca4ca5a93
++ # (mm: remove the pgprot argument to __vmalloc)
++ # in v5.8-rc1 (2020-06-01).
++ CODE="
++ #include <linux/vmalloc.h>
++
++ void conftest_vmalloc_has_pgprot_t_arg(void) {
++ pgprot_t prot;
++ (void)__vmalloc(0, 0, prot);
++ }"
++
++ compile_check_conftest "$CODE"
"NV_VMALLOC_HAS_PGPROT_T_ARG" "" "types"
++
++ ;;
++
++ drm_gem_object_put_unlocked)
++ #
++ # Determine if the function drm_gem_object_put_unlocked() is present.
++ #
++ # In v5.9-rc1, commit 2f4dd13d4bb8 ("drm/gem: add
++ # drm_gem_object_put helper") removes drm_gem_object_put_unlocked()
++ # function and replace its definition by transient macro. Commit
++ # ab15d56e27be ("drm: remove transient
++ # drm_gem_object_put_unlocked()") finally removes
++ # drm_gem_object_put_unlocked() macro.
++ #
++ CODE="
++ #if defined(NV_DRM_DRMP_H_PRESENT)
++ #include <drm/drmP.h>
++ #endif
++
++ #if defined(NV_DRM_DRM_GEM_H_PRESENT)
++ #include <drm/drm_gem.h>
++ #endif
++ void conftest_drm_gem_object_put_unlocked(void) {
++ drm_gem_object_put_unlocked();
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_GEM_OBJECT_PUT_UNLOCK_PRESENT" "" "functions"
++ ;;
++
++ drm_display_mode_has_vrefresh)
++ #
++ # Determine if the 'drm_display_mode' structure has a
'vrefresh'
++ # field.
++ #
++ # Removed by commit 0425662fdf05 ("drm: Nuke mode->vrefresh")
in
++ # v5.9-rc1.
++ #
++ CODE="
++ #include <drm/drm_modes.h>
++
++ int conftest_drm_display_mode_has_vrefresh(void) {
++ return offsetof(struct drm_display_mode, vrefresh);
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_DISPLAY_MODE_HAS_VREFRESH" "types"
++
++ ;;
++
++ drm_driver_master_set_has_int_return_type)
++ #
++ # Determine if drm_driver::master_set() returns integer value
++ #
++ # Changed to void by commit 907f53200f98 ("drm: vmwgfx: remove
++ # drm_driver::master_set() return type") in v5.9-rc1.
++ #
++ CODE="
++ #if defined(NV_DRM_DRMP_H_PRESENT)
++ #include <drm/drmP.h>
++ #endif
++
++ #if defined(NV_DRM_DRM_DRV_H_PRESENT)
++ #include <drm/drm_drv.h>
++ #endif
++
++ int conftest_drm_driver_master_set_has_int_return_type(struct drm_driver
*drv,
++ struct drm_device *dev, struct drm_file *file_priv, bool from_open) {
++
++ return drv->master_set(dev, file_priv, from_open);
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_DRIVER_SET_MASTER_HAS_INT_RETURN_TYPE" "" "types"
++ ;;
++
++ drm_driver_has_gem_free_object)
++ #
++ # Determine if the 'drm_driver' structure has a
'gem_free_object'
++ # function pointer.
++ #
++ # drm_driver::gem_free_object is removed by commit 1a9458aeb8eb
++ # ("drm: remove drm_driver::gem_free_object") in v5.9-rc1.
++ #
++ CODE="
++ #if defined(NV_DRM_DRMP_H_PRESENT)
++ #include <drm/drmP.h>
++ #endif
++
++ #if defined(NV_DRM_DRM_DRV_H_PRESENT)
++ #include <drm/drm_drv.h>
++ #endif
++
++ int conftest_drm_driver_has_gem_free_object(void) {
++ return offsetof(struct drm_driver, gem_free_object);
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_DRIVER_HAS_GEM_FREE_OBJECT" "" "types"
++ ;;
++
++ vga_tryget)
++ #
++ # Determine if vga_tryget() is present
++ #
++ # vga_tryget() was removed by commit f369bc3f9096 ("vgaarb: mark
++ # vga_tryget static") in v5.9-rc1 (2020-08-01).
++ #
++ CODE="
++ #include <linux/vgaarb.h>
++ void conftest_vga_tryget(void) {
++ vga_tryget();
++ }"
++
++ compile_check_conftest "$CODE" "NV_VGA_TRYGET_PRESENT"
"" "functions"
++ ;;
++
++ pci_channel_state)
++ #
++ # Determine if pci_channel_state enum type is present.
++ #
++ # pci_channel_state was removed by commit 16d79cd4e23b ("PCI: Use
++ # 'pci_channel_state_t' instead of 'enum
pci_channel_state'") in
++ # v5.9-rc1 (2020-07-02).
++ #
++ CODE="
++ #include <linux/pci.h>
++
++ enum pci_channel_state state;
++ "
++
++ compile_check_conftest "$CODE"
"NV_PCI_CHANNEL_STATE_PRESENT" "" "types"
++ ;;
++
++ drm_prime_pages_to_sg_has_drm_device_arg)
++ #
++ # Determine if drm_prime_pages_to_sg() has 'dev' argument.
++ #
++ # drm_prime_pages_to_sg() is updated to take 'dev' argument by
commit
++ # 707d561f77b5 ("drm: allow limiting the scatter list size.").
++ #
++ CODE="
++ #if defined(NV_DRM_DRMP_H_PRESENT)
++ #include <drm/drmP.h>
++ #endif
++ #if defined(NV_DRM_DRM_PRIME_H_PRESENT)
++ #include <drm/drm_prime.h>
++ #endif
++
++ struct sg_table *drm_prime_pages_to_sg(struct drm_device *dev,
++ struct page **pages,
++ unsigned int nr_pages) {
++ return 0;
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_PRIME_PAGES_TO_SG_HAS_DRM_DEVICE_ARG" "" "types"
++ ;;
++
++ drm_driver_has_gem_prime_callbacks)
++ #
++ # Determine if drm_driver structure has the GEM and PRIME callback
++ # function pointers.
++ #
++ # The GEM and PRIME callback are removed from drm_driver
++ # structure, by commit d693def4fd1c ("drm: Remove obsolete GEM and
++ # PRIME callbacks from struct drm_driver").
++ #
++ CODE="
++ #if defined(NV_DRM_DRMP_H_PRESENT)
++ #include <drm/drmP.h>
++ #endif
++
++ #if defined(NV_DRM_DRM_DRV_H_PRESENT)
++ #include <drm/drm_drv.h>
++ #endif
++
++ void conftest_drm_driver_has_gem_and_prime_callbacks(void) {
++ struct drm_driver drv;
++
++ drv.gem_prime_pin = 0;
++ drv.gem_prime_get_sg_table = 0;
++ drv.gem_prime_vmap = 0;
++ drv.gem_prime_vunmap = 0;
++ drv.gem_vm_ops = 0;
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_DRIVER_HAS_GEM_PRIME_CALLBACKS" "" "types"
++ ;;
++
++ drm_crtc_atomic_check_has_atomic_state_arg)
++ #
++ # Determine if drm_crtc_helper_funcs::atomic_check takes 'state'
++ # argument of 'struct drm_atomic_state' type.
++ #
++ # The commit 29b77ad7b9ca ("drm/atomic: Pass the full state to CRTC
++ # atomic_check") passed the full atomic state to
++ # drm_crtc_helper_funcs::atomic_check()
++ #
++ # Turning incompatible-pointer-types check into error is necessary
++ # to make test fail if drm_crtc_helper_funcs::atomic_check is taking
++ # 'crtc_state' instead of 'state', otherwise test simply
pass
++ # because compilation succeeds throwing incompatible-pointer-types
++ # warning. This test is expected to fail on Linux kernels <= v5.10,
++ # the commit ea8daa7b9784 ("kbuild: Add option to turn incompatible
++ # pointer check into error") has turned incompatible-pointer-types
++ # check into error from v4.6.
++ #
++ echo "$CONFTEST_PREAMBLE
++ #include <drm/drm_modeset_helper_vtables.h>
++ int conftest_drm_crtc_atomic_check_has_atomic_state_arg(
++ struct drm_crtc *crtc, struct drm_atomic_state *state) {
++ const struct drm_crtc_helper_funcs *funcs = crtc->helper_private;
++ return funcs->atomic_check(crtc, state);
++ }" > conftest$$.c
++
++ $CC $CFLAGS -Werror=incompatible-pointer-types -c conftest$$.c >
/dev/null 2>&1
++ rm -f conftest$$.c
++
++ if [ -f conftest$$.o ]; then
++ rm -f conftest$$.o
++ echo "#define NV_DRM_CRTC_ATOMIC_CHECK_HAS_ATOMIC_STATE_ARG" |
append_conftest "types"
++ else
++ echo "#undef NV_DRM_CRTC_ATOMIC_CHECK_HAS_ATOMIC_STATE_ARG" |
append_conftest "types"
++ fi
++ ;;
++
++ drm_gem_object_vmap_has_map_arg)
++ #
++ # Determine if drm_gem_object_funcs::vmap takes 'map'
++ # argument of 'struct dma_buf_map' type.
++ #
++ # The commit 49a3f51dfeee ("drm/gem: Use struct dma_buf_map in GEM
++ # vmap ops and convert GEM backends") update
++ # drm_gem_object_funcs::vmap to take 'map' argument.
++ #
++ CODE="
++ #include <drm/drm_gem.h>
++ int conftest_drm_gem_object_vmap_has_map_arg(
++ struct drm_gem_object *obj, struct dma_buf_map *map) {
++ return obj->funcs->vmap(obj, map);
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_GEM_OBJECT_VMAP_HAS_MAP_ARG" "" "types"
++ ;;
+ esac
+ }
+
+-create_skeleton_headers
+-build_cflags
+-
+ case "$6" in
+ cc_sanity_check)
+ #
+@@ -2320,137 +4487,85 @@
+
+ cc_version_check)
+ #
+- # Verify that the same compiler is used for the kernel and kernel
+- # module.
++ # Verify that the same compiler major and minor version is
++ # used for the kernel and kernel module.
++ #
++ # Some gcc version strings that have proven problematic for parsing
++ # in the past:
++ #
++ # gcc.real (GCC) 3.3 (Debian)
++ # gcc-Version 3.3 (Debian)
++ # gcc (GCC) 3.1.1 20020606 (Debian prerelease)
++ # version gcc 3.2.3
+ #
+ VERBOSE=$7
+-
+- if [ ! -f gcc-version-check.c ]; then
+- #
+- # gcc-version-check.c is not in the current working directory.
+- # This can happen when building the kernel module from an
+- # NVIDIA-internal intermediate directory prior to creating an
+- # NVIDIA driver package. Since the version check below is less
+- # useful than it used to be, just silently skip the test if
+- # gcc-version-check.c is missing.
+- #
+- IGNORE_CC_MISMATCH=1
+- fi
+-
+- if [ -n "$IGNORE_CC_MISMATCH" -o -n "$SYSSRC" -o -n
"$SYSINCLUDE" ]; then
+- #
+- # The user chose to disable the CC version test (which may or
+- # may not be wise) or is building the module for a kernel not
+- # currently running, which renders the test meaningless.
+- #
+- exit 0
+- fi
+-
+- rm -f gcc-version-check
+- $HOSTCC gcc-version-check.c -o gcc-version-check > /dev/null 2>&1
+- if [ ! -f gcc-version-check ]; then
+- if [ "$CC" != "cc" ]; then
+- MSG="Could not compile 'gcc-version-check.c'. Please be
"
+- MSG="$MSG sure you have your Linux distribution's libc "
+- MSG="$MSG development package installed and that '$CC'
"
+- MSG="$MSG is a valid C compiler name."
+- else
+- MSG="Could not compile 'gcc-version-check.c'. Please be
"
+- MSG="$MSG sure you have your Linux distribution's gcc "
+- MSG="$MSG and libc development packages installed."
+- fi
+- RET=1
+- else
+- PROC_VERSION="/proc/version"
+- if [ -f $PROC_VERSION ]; then
+- MSG=`./gcc-version-check "$(cat $PROC_VERSION)"`
+- RET=$?
+- else
+- MSG="$PROC_VERSION does not exist."
+- RET=1
+- fi
+- rm -f gcc-version-check
++
++ kernel_compile_h=$OUTPUT/include/generated/compile.h
++
++ if [ ! -f ${kernel_compile_h} ]; then
++ # The kernel's compile.h file is not present, so there
++ # isn't a convenient way to identify the compiler version
++ # used to build the kernel.
++ IGNORE_CC_MISMATCH=1
+ fi
+
+- if [ "$RET" != "0" ]; then
++ if [ -n "$IGNORE_CC_MISMATCH" ]; then
++ exit 0
++ fi
++
++ kernel_cc_string=`cat ${kernel_compile_h} | \
++ grep LINUX_COMPILER | cut -f 2 -d '"'`
++
++ kernel_cc_version=`echo ${kernel_cc_string} | grep -o '[0-9]\+\.[0-9]\+'
| head -n 1`
++ kernel_cc_major=`echo ${kernel_cc_version} | cut -d '.' -f 1`
++ kernel_cc_minor=`echo ${kernel_cc_version} | cut -d '.' -f 2`
++
++ echo "
++ #if (__GNUC__ != ${kernel_cc_major}) || (__GNUC_MINOR__ != ${kernel_cc_minor})
++ #error \"cc version mismatch\"
++ #endif
++ " > conftest$$.c
++
++ $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
++ rm -f conftest$$.c
++
++ if [ -f conftest$$.o ]; then
++ rm -f conftest$$.o
++ exit 0;
++ else
+ #
+ # The gcc version check failed
+ #
+-
++
+ if [ "$VERBOSE" = "full_output" ]; then
+ echo "";
+- echo "gcc-version-check failed:";
++ echo "Compiler version check failed:";
++ echo "";
++ echo "The major and minor number of the compiler used to";
++ echo "compile the kernel:";
++ echo "";
++ echo "${kernel_cc_string}";
+ echo "";
+- echo "$MSG" | fmt -w 52
++ echo "does not match the compiler used here:";
+ echo "";
+- echo "If you know what you are doing and want to override";
+- echo "the gcc version check, you can do so by setting the";
+- echo "IGNORE_CC_MISMATCH environment variable to
\"1\".";
++ $CC --version
+ echo "";
+- echo "In any other case, set the CC environment variable";
+- echo "to the name of the compiler that was used to compile";
+- echo "the kernel.";
++ echo "It is recommended to set the CC environment variable";
++ echo "to the compiler that was used to compile the kernel.";
+ echo ""
++ echo "The compiler version check can be disabled by setting";
++ echo "the IGNORE_CC_MISMATCH environment variable to
\"1\".";
++ echo "However, mixing compiler versions between the kernel";
++ echo "and kernel modules can result in subtle bugs that are";
++ echo "difficult to diagnose.";
++ echo "";
+ echo "*** Failed CC version check. Bailing out! ***";
+ echo "";
+- else
+- echo "$MSG";
++ elif [ "$VERBOSE" = "just_msg" ]; then
++ echo "The kernel was built with ${kernel_cc_string}, but the"
\
++ "current compiler version is `$CC --version | head -n
1`.";
+ fi
+ exit 1;
+- else
+- exit 0
+- fi
+- ;;
+-
+- suser_sanity_check)
+- #
+- # Determine the caller's user id to determine if we have sufficient
+- # privileges for the requested operation.
+- #
+- if [ $(id -ur) != 0 ]; then
+- echo "";
+- echo "Please run \"make install\" as root.";
+- echo "";
+- echo "*** Failed super-user sanity check. Bailing out! ***";
+- exit 1
+- else
+- exit 0
+- fi
+- ;;
+-
+- rmmod_sanity_check)
+- #
+- # Make sure that any currently loaded NVIDIA kernel module can be
+- # unloaded.
+- #
+- MODULE="nvidia"
+-
+- if [ -n "$SYSSRC" -o -n "$SYSINCLUDE" ]; then
+- #
+- # Don't attempt to remove the kernel module if we're not
+- # building against the running kernel.
+- #
+- exit 0
+- fi
+-
+- if lsmod | grep -wq $MODULE; then
+- rmmod $MODULE > /dev/null 2>&1
+- fi
+-
+- if lsmod | grep -wq $MODULE; then
+- #
+- # The NVIDIA kernel module is still loaded, most likely because
+- # it is busy.
+- #
+- echo "";
+- echo "Unable to remove existing NVIDIA kernel module.";
+- echo "Please be sure you have exited X before attempting";
+- echo "to install the NVIDIA kernel module.";
+- echo "";
+- echo "*** Failed rmmod sanity check. Bailing out! ***";
+- exit 1
+- else
+- exit 0
+ fi
+ ;;
+
+@@ -2530,52 +4645,6 @@
+ fi
+ ;;
+
+- rivafb_sanity_check)
+- #
+- # Check if the kernel was compiled with rivafb support. If so, then
+- # exit, since the driver no longer works with rivafb.
+- #
+-
+- if test_configuration_option CONFIG_FB_RIVA; then
+- echo "Your kernel was configured to include rivafb support!";
+- echo "";
+- echo "The rivafb driver conflicts with the NVIDIA driver,
please";
+- echo "reconfigure your kernel and *disable* rivafb support,
then";
+- echo "try installing the NVIDIA kernel module again.";
+- echo "";
+- if [ "$VERBOSE" = "full_output" ]; then
+- echo "*** Failed rivafb sanity check. Bailing out! ***";
+- echo "";
+- fi
+- exit 1
+- else
+- exit 0
+- fi
+- ;;
+-
+- nvidiafb_sanity_check)
+- #
+- # Check if the kernel was compiled with nvidiafb support. If so, then
+- # exit, since the driver doesn't work with nvidiafb.
+- #
+-
+- if test_configuration_option CONFIG_FB_NVIDIA; then
+- echo "Your kernel was configured to include nvidiafb support!";
+- echo "";
+- echo "The nvidiafb driver conflicts with the NVIDIA driver,
please";
+- echo "reconfigure your kernel and *disable* nvidiafb support,
then";
+- echo "try installing the NVIDIA kernel module again.";
+- echo "";
+- if [ "$VERBOSE" = "full_output" ]; then
+- echo "*** Failed nvidiafb sanity check. Bailing out! ***";
+- echo "";
+- fi
+- exit 1
+- else
+- exit 0
+- fi
+- ;;
+-
+ xen_sanity_check)
+ #
+ # Check if the target kernel is a Xen kernel. If so, exit, since
+@@ -2587,6 +4656,8 @@
+ exit 0
+ fi
+
++ test_xen
++
+ if [ "$XEN_PRESENT" != "0" ]; then
+ echo "The kernel you are installing for is a Xen kernel!";
+ echo "";
+@@ -2652,7 +4723,7 @@
+
+ for PATCH in patch-*.h; do
+ if [ -f $PATCH ]; then
+- echo "#include \"$PATCH\"" | append_conftest
"patches"
++ echo "#include \"$PATCH\""
+ PATCHES="$PATCHES "`echo $PATCH | sed -s
's/patch-\(.*\)\.h/\1/'`
+ fi
+ done
+@@ -2660,14 +4731,11 @@
+ echo "static struct {
+ const char *short_description;
+ const char *description;
+- } __nv_patches[] = {" | append_conftest "patches"
++ } __nv_patches[] = {"
+ for i in $PATCHES; do
+- echo "{ \"$i\", NV_PATCH_${i}_DESCRIPTION }," | \
+- append_conftest "patches"
++ echo "{ \"$i\", NV_PATCH_${i}_DESCRIPTION },"
+ done
+- echo "{ NULL, NULL } };" | append_conftest "patches"
+-
+- update_conftest "patches"
++ echo "{ NULL, NULL } };"
+
+ exit 0
+ ;;
+@@ -2677,20 +4745,13 @@
+ # Run a series of compile tests to determine the set of interfaces
+ # and features available in the target kernel.
+ #
+- shift 5
++ shift 6
+
+- test_headers
++ CFLAGS=$1
++ shift
+
+ for i in $*; do compile_test $i; done
+
+- if [ -n "$SHOW_COMPILE_TEST_RESULTS" -a -f conftest.h ]; then
+- cat conftest.h conftest/*.h
+- fi
+-
+- for header in $COMPILE_TEST_HEADERS; do
+- update_conftest "$header"
+- done
+-
+ exit 0
+ ;;
+
+@@ -2716,7 +4777,33 @@
+ exit 1
+ fi
+ ;;
+-
++ vgpu_kvm_sanity_check)
++ #
++ # Determine whether we are running a vGPU on KVM host.
++ #
++ VERBOSE=$7
++ iommu=CONFIG_VFIO_IOMMU_TYPE1
++ mdev=CONFIG_VFIO_MDEV_DEVICE
++ kvm=CONFIG_KVM_VFIO
++
++ if [ -n "$VGX_KVM_BUILD" ]; then
++ if (test_configuration_option ${iommu} || test_configuration_option
${iommu}_MODULE) &&
++ (test_configuration_option ${mdev} || test_configuration_option
${mdev}_MODULE) &&
++ (test_configuration_option ${kvm} || test_configuration_option
${kvm}_MODULE); then
++ exit 0
++ else
++ echo "The kernel is not running a vGPU on KVM host.";
++ echo "";
++ if [ "$VERBOSE" = "full_output" ]; then
++ echo "*** Failed vGPU on KVM sanity check. Bailing out!
***";
++ echo "";
++ fi
++ fi
++ exit 1
++ else
++ exit 0
++ fi
++ ;;
+ test_configuration_option)
+ #
+ # Check to see if the given config option is set.
+@@ -2760,4 +4847,25 @@
+ exit 1
+ ;;
+
++
++ test_kernel_headers)
++ #
++ # Check for the availability of certain kernel headers
++ #
++
++ test_headers
++ exit $?
++ ;;
++
++
++ build_cflags)
++ #
++ # Generate CFLAGS for use in the compile tests
++ #
++
++ build_cflags
++ echo $CFLAGS
++ exit 0
++ ;;
++
+ esac
+diff -Naur a/kernel/nv-gpu-info.h b/kernel/nv-gpu-info.h
+--- a/kernel/nv-gpu-info.h 1970-01-01 01:00:00.000000000 +0100
++++ b/kernel/nv-gpu-info.h 2021-06-09 21:37:47.510578416 +0200
+@@ -0,0 +1,31 @@
++/* _NVRM_COPYRIGHT_BEGIN_
++ *
++ * Copyright 2015 by NVIDIA Corporation. All rights reserved. All
++ * information contained herein is proprietary and confidential to NVIDIA
++ * Corporation. Any use, reproduction, or disclosure without the written
++ * permission of NVIDIA Corporation is prohibited.
++ *
++ * _NVRM_COPYRIGHT_END_
++ */
++
++#ifndef _NV_GPU_INFO_H_
++#define _NV_GPU_INFO_H_
++
++typedef struct {
++ NvU32 gpu_id;
++
++ struct {
++ NvU32 domain;
++ NvU8 bus, slot, function;
++ } pci_info;
++
++ /*
++ * opaque OS-specific pointer; on Linux, this is a pointer to the
++ * 'struct pci_dev' for the GPU.
++ */
++ void *os_dev_ptr;
++} nv_gpu_info_t;
++
++#define NV_MAX_GPUS 32
++
++#endif /* _NV_GPU_INFO_H_ */
+diff -Naur a/kernel/nvidia-dma-fence-helper.h b/kernel/nvidia-dma-fence-helper.h
+--- a/kernel/nvidia-dma-fence-helper.h 1970-01-01 01:00:00.000000000 +0100
++++ b/kernel/nvidia-dma-fence-helper.h 2021-06-09 21:37:47.510578416 +0200
+@@ -0,0 +1,121 @@
++/*
++ * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++#ifndef __NVIDIA_DMA_FENCE_HELPER_H__
++#define __NVIDIA_DMA_FENCE_HELPER_H__
++
++#include "nvidia-drm-conftest.h"
++
++#if defined(NV_DRM_FENCE_AVAILABLE)
++
++/*
++ * Fence headers are moved to file dma-fence.h and struct fence has
++ * been renamed to dma_fence by commit -
++ *
++ * 2016-10-25 : f54d1867005c3323f5d8ad83eed823e84226c429
++ */
++
++#if defined(NV_LINUX_FENCE_H_PRESENT)
++#include <linux/fence.h>
++#else
++#include <linux/dma-fence.h>
++#endif
++
++#if defined(NV_LINUX_FENCE_H_PRESENT)
++typedef struct fence nv_dma_fence_t;
++typedef struct fence_ops nv_dma_fence_ops_t;
++#else
++typedef struct dma_fence nv_dma_fence_t;
++typedef struct dma_fence_ops nv_dma_fence_ops_t;
++#endif
++
++#if defined(NV_LINUX_FENCE_H_PRESENT)
++#define NV_DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT FENCE_FLAG_ENABLE_SIGNAL_BIT
++#else
++#define NV_DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT
++#endif
++
++static inline bool nv_dma_fence_is_signaled(nv_dma_fence_t *fence) {
++#if defined(NV_LINUX_FENCE_H_PRESENT)
++ return fence_is_signaled(fence);
++#else
++ return dma_fence_is_signaled(fence);
++#endif
++}
++
++static inline nv_dma_fence_t *nv_dma_fence_get(nv_dma_fence_t *fence)
++{
++#if defined(NV_LINUX_FENCE_H_PRESENT)
++ return fence_get(fence);
++#else
++ return dma_fence_get(fence);
++#endif
++}
++
++static inline void nv_dma_fence_put(nv_dma_fence_t *fence) {
++#if defined(NV_LINUX_FENCE_H_PRESENT)
++ fence_put(fence);
++#else
++ dma_fence_put(fence);
++#endif
++}
++
++static inline signed long
++nv_dma_fence_default_wait(nv_dma_fence_t *fence,
++ bool intr, signed long timeout) {
++#if defined(NV_LINUX_FENCE_H_PRESENT)
++ return fence_default_wait(fence, intr, timeout);
++#else
++ return dma_fence_default_wait(fence, intr, timeout);
++#endif
++}
++
++static inline int nv_dma_fence_signal(nv_dma_fence_t *fence) {
++#if defined(NV_LINUX_FENCE_H_PRESENT)
++ return fence_signal(fence);
++#else
++ return dma_fence_signal(fence);
++#endif
++}
++
++static inline u64 nv_dma_fence_context_alloc(unsigned num) {
++#if defined(NV_LINUX_FENCE_H_PRESENT)
++ return fence_context_alloc(num);
++#else
++ return dma_fence_context_alloc(num);
++#endif
++}
++
++static inline void
++nv_dma_fence_init(nv_dma_fence_t *fence,
++ const nv_dma_fence_ops_t *ops,
++ spinlock_t *lock, u64 context, unsigned seqno) {
++#if defined(NV_LINUX_FENCE_H_PRESENT)
++ fence_init(fence, ops, lock, context, seqno);
++#else
++ dma_fence_init(fence, ops, lock, context, seqno);
++#endif
++}
++
++#endif /* defined(NV_DRM_FENCE_AVAILABLE) */
++
++#endif /* __NVIDIA_DMA_FENCE_HELPER_H__ */
+diff -Naur a/kernel/nvidia-dma-resv-helper.h b/kernel/nvidia-dma-resv-helper.h
+--- a/kernel/nvidia-dma-resv-helper.h 1970-01-01 01:00:00.000000000 +0100
++++ b/kernel/nvidia-dma-resv-helper.h 2021-06-09 21:37:47.510578416 +0200
+@@ -0,0 +1,80 @@
++/*
++ * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++#ifndef __NVIDIA_DMA_RESV_HELPER_H__
++#define __NVIDIA_DMA_RESV_HELPER_H__
++
++#include "nvidia-drm-conftest.h"
++
++#if defined(NV_DRM_FENCE_AVAILABLE)
++
++/*
++ * linux/reservation.h is renamed to linux/dma-resv.h, by commit
++ * 52791eeec1d9 (dma-buf: rename reservation_object to dma_resv)
++ * in v5.4.
++ */
++
++#if defined(NV_LINUX_DMA_RESV_H_PRESENT)
++#include <linux/dma-resv.h>
++#else
++#include <linux/reservation.h>
++#endif
++
++#include <nvidia-dma-fence-helper.h>
++
++#if defined(NV_LINUX_DMA_RESV_H_PRESENT)
++typedef struct dma_resv nv_dma_resv_t;
++#else
++typedef struct reservation_object nv_dma_resv_t;
++#endif
++
++static inline void nv_dma_resv_init(nv_dma_resv_t *obj)
++{
++#if defined(NV_LINUX_DMA_RESV_H_PRESENT)
++ dma_resv_init(obj);
++#else
++ reservation_object_init(obj);
++#endif
++}
++
++static inline void nv_dma_resv_fini(nv_dma_resv_t *obj)
++{
++#if defined(NV_LINUX_DMA_RESV_H_PRESENT)
++ dma_resv_fini(obj);
++#else
++ reservation_object_init(obj);
++#endif
++}
++
++static inline void nv_dma_resv_add_excl_fence(nv_dma_resv_t *obj,
++ nv_dma_fence_t *fence)
++{
++#if defined(NV_LINUX_DMA_RESV_H_PRESENT)
++ dma_resv_add_excl_fence(obj, fence);
++#else
++ reservation_object_add_excl_fence(obj, fence);
++#endif
++}
++
++#endif /* defined(NV_DRM_FENCE_AVAILABLE) */
++
++#endif /* __NVIDIA_DMA_RESV_HELPER_H__ */
+diff -Naur a/kernel/nvidia-drm-conftest.h b/kernel/nvidia-drm-conftest.h
+--- a/kernel/nvidia-drm-conftest.h 1970-01-01 01:00:00.000000000 +0100
++++ b/kernel/nvidia-drm-conftest.h 2021-06-09 21:37:47.510578416 +0200
+@@ -0,0 +1,64 @@
++/*
++ * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++#ifndef __NVIDIA_DRM_CONFTEST_H__
++#define __NVIDIA_DRM_CONFTEST_H__
++
++#include "conftest.h"
++
++/*
++ * NOTE: This file is expected to get included at the top before including any
++ * of linux/drm headers.
++ *
++ * The goal is to redefine refcount_dec_and_test and refcount_inc before
++ * including drm header files, so that the drm macro/inline calls to
++ * refcount_dec_and_test* and refcount_inc get redirected to
++ * alternate implementation in this file.
++ */
++
++#if NV_IS_EXPORT_SYMBOL_GPL_refcount_inc
++
++#include <linux/refcount.h>
++
++#define refcount_inc(__ptr) \
++ do { \
++ atomic_inc(&(__ptr)->refs); \
++ } while(0)
++
++#endif
++
++#if NV_IS_EXPORT_SYMBOL_GPL_refcount_dec_and_test
++
++#include <linux/refcount.h>
++
++#define refcount_dec_and_test(__ptr) atomic_dec_and_test(&(__ptr)->refs)
++
++#endif
++
++#if defined(NV_DRM_DRIVER_HAS_GEM_PRIME_RES_OBJ) || \
++ defined(NV_DRM_GEM_OBJECT_HAS_RESV)
++#define NV_DRM_FENCE_AVAILABLE
++#else
++#undef NV_DRM_FENCE_AVAILABLE
++#endif
++
++#endif /* defined(__NVIDIA_DRM_CONFTEST_H__) */
+diff -Naur a/kernel/nvidia-drm-gem.c b/kernel/nvidia-drm-gem.c
+--- a/kernel/nvidia-drm-gem.c 1970-01-01 01:00:00.000000000 +0100
++++ b/kernel/nvidia-drm-gem.c 2021-06-09 21:37:47.511578395 +0200
+@@ -0,0 +1,193 @@
++/*
++ * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++#include "nvidia-drm-conftest.h"
++
++#if defined(NV_DRM_AVAILABLE)
++
++#include "nvidia-drm-priv.h"
++#include "nvidia-drm-ioctl.h"
++#include "nvidia-drm-prime-fence.h"
++#include "nvidia-drm-gem.h"
++#include "nvidia-dma-resv-helper.h"
++#include "nvidia-drm-gem-nvkms-memory.h"
++
++#if defined(NV_DRM_DRM_PRIME_H_PRESENT)
++#include <drm/drm_prime.h>
++#endif
++
++#include "linux/dma-buf.h"
++
++void nv_drm_gem_free(struct drm_gem_object *gem)
++{
++ struct nv_drm_gem_object *nv_gem = to_nv_gem_object(gem);
++
++ /* Cleanup core gem object */
++ drm_gem_object_release(&nv_gem->base);
++
++#if defined(NV_DRM_FENCE_AVAILABLE) && !defined(NV_DRM_GEM_OBJECT_HAS_RESV)
++ nv_dma_resv_fini(&nv_gem->resv);
++#endif
++
++ nv_gem->ops->free(nv_gem);
++}
++
++#if !defined(NV_DRM_DRIVER_HAS_GEM_PRIME_CALLBACKS) && \
++ defined(NV_DRM_GEM_OBJECT_VMAP_HAS_MAP_ARG)
++static int nv_drm_gem_vmap(struct drm_gem_object *gem,
++ struct dma_buf_map *map)
++{
++ map->vaddr = nv_drm_gem_prime_vmap(gem);
++ if (map->vaddr == NULL) {
++ return -ENOMEM;
++ }
++ map->is_iomem = true;
++ return 0;
++}
++
++static void nv_drm_gem_vunmap(struct drm_gem_object *gem,
++ struct dma_buf_map *map)
++{
++ nv_drm_gem_prime_vunmap(gem, map->vaddr);
++ map->vaddr = NULL;
++}
++#endif
++
++#if !defined(NV_DRM_DRIVER_HAS_GEM_FREE_OBJECT) || \
++ !defined(NV_DRM_DRIVER_HAS_GEM_PRIME_CALLBACKS)
++static struct drm_gem_object_funcs nv_drm_gem_funcs = {
++ .free = nv_drm_gem_free,
++ .get_sg_table = nv_drm_gem_prime_get_sg_table,
++
++#if !defined(NV_DRM_DRIVER_HAS_GEM_PRIME_CALLBACKS)
++ .export = nv_drm_gem_prime_export,
++#if defined(NV_DRM_GEM_OBJECT_VMAP_HAS_MAP_ARG)
++ .vmap = nv_drm_gem_vmap,
++ .vunmap = nv_drm_gem_vunmap,
++#else
++ .vmap = nv_drm_gem_prime_vmap,
++ .vunmap = nv_drm_gem_prime_vunmap,
++#endif
++
++#if defined(NV_DRM_ATOMIC_MODESET_AVAILABLE)
++ .vm_ops = &nv_drm_gem_vma_ops,
++#endif
++
++#endif
++};
++#endif
++
++void nv_drm_gem_object_init(struct nv_drm_device *nv_dev,
++ struct nv_drm_gem_object *nv_gem,
++ const struct nv_drm_gem_object_funcs * const ops,
++ size_t size,
++ bool prime)
++{
++ struct drm_device *dev = nv_dev->dev;
++
++ nv_gem->nv_dev = nv_dev;
++ nv_gem->prime = prime;
++ nv_gem->ops = ops;
++
++ /* Initialize the gem object */
++
++#if defined(NV_DRM_FENCE_AVAILABLE)
++ nv_dma_resv_init(&nv_gem->resv);
++
++#if defined(NV_DRM_GEM_OBJECT_HAS_RESV)
++ nv_gem->base.resv = &nv_gem->resv;
++#endif
++
++#endif
++
++#if !defined(NV_DRM_DRIVER_HAS_GEM_FREE_OBJECT)
++ nv_gem->base.funcs = &nv_drm_gem_funcs;
++#endif
++
++ drm_gem_private_object_init(dev, &nv_gem->base, size);
++}
++
++struct dma_buf *nv_drm_gem_prime_export(
++#if defined(NV_DRM_GEM_PRIME_EXPORT_HAS_DEV_ARG)
++ struct drm_device *dev,
++#endif
++ struct drm_gem_object *gem, int flags)
++{
++ struct nv_drm_device *nv_dev = to_nv_device(gem->dev);
++
++ struct nv_drm_gem_object *nv_gem = to_nv_gem_object(gem);
++
++ if (!nv_gem->prime) {
++ NV_DRM_DEV_LOG_ERR(
++ nv_dev,
++ "Gem object 0x%p is not suitable to export", gem);
++ return ERR_PTR(-EINVAL);
++ }
++
++ return drm_gem_prime_export(
++#if defined(NV_DRM_GEM_PRIME_EXPORT_HAS_DEV_ARG)
++ dev,
++#endif
++ gem, flags);
++}
++
++struct sg_table *nv_drm_gem_prime_get_sg_table(struct drm_gem_object *gem)
++{
++ struct nv_drm_gem_object *nv_gem = to_nv_gem_object(gem);
++
++ if (nv_gem->ops->prime_get_sg_table != NULL) {
++ return nv_gem->ops->prime_get_sg_table(nv_gem);
++ }
++
++ return ERR_PTR(-ENOTSUPP);
++}
++
++void *nv_drm_gem_prime_vmap(struct drm_gem_object *gem)
++{
++ struct nv_drm_gem_object *nv_gem = to_nv_gem_object(gem);
++
++ if (nv_gem->ops->prime_vmap != NULL) {
++ return nv_gem->ops->prime_vmap(nv_gem);
++ }
++
++ return ERR_PTR(-ENOTSUPP);
++}
++
++void nv_drm_gem_prime_vunmap(struct drm_gem_object *gem, void *address)
++{
++ struct nv_drm_gem_object *nv_gem = to_nv_gem_object(gem);
++
++ if (nv_gem->ops->prime_vunmap != NULL) {
++ nv_gem->ops->prime_vunmap(nv_gem, address);
++ }
++}
++
++#if defined(NV_DRM_DRIVER_HAS_GEM_PRIME_RES_OBJ)
++nv_dma_resv_t* nv_drm_gem_prime_res_obj(struct drm_gem_object *obj)
++{
++ struct nv_drm_gem_object *nv_gem = to_nv_gem_object(obj);
++
++ return &nv_gem->resv;
++}
++#endif
++
++#endif /* NV_DRM_AVAILABLE */
+diff -Naur a/kernel/nvidia-drm-gem.h b/kernel/nvidia-drm-gem.h
+--- a/kernel/nvidia-drm-gem.h 1970-01-01 01:00:00.000000000 +0100
++++ b/kernel/nvidia-drm-gem.h 2021-06-09 21:37:47.511578395 +0200
+@@ -0,0 +1,198 @@
++/*
++ * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++#ifndef __NVIDIA_DRM_GEM_H__
++#define __NVIDIA_DRM_GEM_H__
++
++#include "nvidia-drm-conftest.h"
++
++#if defined(NV_DRM_AVAILABLE)
++
++#include "nvidia-drm-priv.h"
++
++#if defined(NV_DRM_DRMP_H_PRESENT)
++#include <drm/drmP.h>
++#endif
++
++#if defined(NV_DRM_DRM_GEM_H_PRESENT)
++#include <drm/drm_gem.h>
++#endif
++
++#include "nvkms-kapi.h"
++
++#if defined(NV_DRM_FENCE_AVAILABLE)
++#include "nvidia-dma-fence-helper.h"
++#include "nvidia-dma-resv-helper.h"
++#endif
++
++struct nv_drm_gem_object;
++
++struct nv_drm_gem_object_funcs {
++ void (*free)(struct nv_drm_gem_object *nv_gem);
++ struct sg_table *(*prime_get_sg_table)(struct nv_drm_gem_object *nv_gem);
++ void *(*prime_vmap)(struct nv_drm_gem_object *nv_gem);
++ void (*prime_vunmap)(struct nv_drm_gem_object *nv_gem, void *address);
++};
++
++struct nv_drm_gem_object {
++ struct drm_gem_object base;
++
++ struct nv_drm_device *nv_dev;
++ const struct nv_drm_gem_object_funcs *ops;
++
++#if defined(NV_DRM_FENCE_AVAILABLE)
++ nv_dma_resv_t resv;
++#endif
++
++ bool prime:1;
++};
++
++static inline struct nv_drm_gem_object *to_nv_gem_object(
++ struct drm_gem_object *gem)
++{
++ if (gem != NULL) {
++ return container_of(gem, struct nv_drm_gem_object, base);
++ }
++
++ return NULL;
++}
++
++/*
++ * drm_gem_object_{get/put}() added by commit
++ * e6b62714e87c8811d5564b6a0738dcde63a51774 (2017-02-28) and
++ * drm_gem_object_{reference/unreference}() removed by commit
++ * 3e70fd160cf0b1945225eaa08dd2cb8544f21cb8 (2018-11-15).
++ */
++
++static inline void
++nv_drm_gem_object_unreference_unlocked(struct nv_drm_gem_object *nv_gem)
++{
++#if defined(NV_DRM_GEM_OBJECT_GET_PRESENT)
++
++#if defined(NV_DRM_GEM_OBJECT_PUT_UNLOCK_PRESENT)
++ drm_gem_object_put_unlocked(&nv_gem->base);
++#else
++ drm_gem_object_put(&nv_gem->base);
++#endif
++
++#else
++ drm_gem_object_unreference_unlocked(&nv_gem->base);
++#endif
++}
++
++static inline void
++nv_drm_gem_object_unreference(struct nv_drm_gem_object *nv_gem)
++{
++#if defined(NV_DRM_GEM_OBJECT_GET_PRESENT)
++ drm_gem_object_put(&nv_gem->base);
++#else
++ drm_gem_object_unreference(&nv_gem->base);
++#endif
++}
++
++static inline int nv_drm_gem_handle_create_drop_reference(
++ struct drm_file *file_priv,
++ struct nv_drm_gem_object *nv_gem,
++ uint32_t *handle)
++{
++ int ret = drm_gem_handle_create(file_priv, &nv_gem->base, handle);
++
++ /* drop reference from allocate - handle holds it now */
++
++ nv_drm_gem_object_unreference_unlocked(nv_gem);
++
++ return ret;
++}
++
++static inline int nv_drm_gem_create_mmap_offset(
++ struct nv_drm_gem_object *nv_gem,
++ uint64_t *offset)
++{
++ int ret;
++
++ if ((ret = drm_gem_create_mmap_offset(&nv_gem->base)) < 0) {
++ NV_DRM_DEV_LOG_ERR(
++ nv_gem->nv_dev,
++ "drm_gem_create_mmap_offset failed with error code %d",
++ ret);
++ goto done;
++ }
++
++ *offset = drm_vma_node_offset_addr(&nv_gem->base.vma_node);
++
++done:
++
++ return ret;
++}
++
++void nv_drm_gem_free(struct drm_gem_object *gem);
++
++struct dma_buf *nv_drm_gem_prime_export(
++#if defined(NV_DRM_GEM_PRIME_EXPORT_HAS_DEV_ARG)
++ struct drm_device *dev,
++#endif
++ struct drm_gem_object *gem, int flags);
++
++static inline struct nv_drm_gem_object *nv_drm_gem_object_lookup(
++ struct drm_device *dev,
++ struct drm_file *filp,
++ u32 handle)
++{
++ #if defined(NV_DRM_GEM_OBJECT_LOOKUP_PRESENT)
++ #if (NV_DRM_GEM_OBJECT_LOOKUP_ARGUMENT_COUNT == 3)
++ return to_nv_gem_object(drm_gem_object_lookup(dev, filp, handle));
++ #elif (NV_DRM_GEM_OBJECT_LOOKUP_ARGUMENT_COUNT == 2)
++ return to_nv_gem_object(drm_gem_object_lookup(filp, handle));
++ #else
++ #error "Unknow arguments count of drm_gem_object_lookup()"
++ #endif
++ #else
++ #error "drm_gem_object_lookup() is not defined"
++ #endif
++}
++
++static inline int nv_drm_gem_handle_create(struct drm_file *filp,
++ struct nv_drm_gem_object *nv_gem,
++ uint32_t *handle)
++{
++ return drm_gem_handle_create(filp, &nv_gem->base, handle);
++}
++
++void nv_drm_gem_object_init(struct nv_drm_device *nv_dev,
++ struct nv_drm_gem_object *nv_gem,
++ const struct nv_drm_gem_object_funcs * const ops,
++ size_t size,
++ bool prime);
++
++struct sg_table *nv_drm_gem_prime_get_sg_table(struct drm_gem_object *gem);
++
++void *nv_drm_gem_prime_vmap(struct drm_gem_object *gem);
++
++void nv_drm_gem_prime_vunmap(struct drm_gem_object *gem, void *address);
++
++#if defined(NV_DRM_DRIVER_HAS_GEM_PRIME_RES_OBJ)
++nv_dma_resv_t* nv_drm_gem_prime_res_obj(struct drm_gem_object *obj);
++#endif
++
++#endif /* NV_DRM_AVAILABLE */
++
++#endif /* __NVIDIA_DRM_GEM_H__ */
+diff -Naur a/kernel/nvidia-drm-gem-user-memory.c b/kernel/nvidia-drm-gem-user-memory.c
+--- a/kernel/nvidia-drm-gem-user-memory.c 1970-01-01 01:00:00.000000000 +0100
++++ b/kernel/nvidia-drm-gem-user-memory.c 2021-06-09 21:37:47.510578416 +0200
+@@ -0,0 +1,139 @@
++/*
++ * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++#include "nvidia-drm-conftest.h"
++
++#if defined(NV_DRM_AVAILABLE)
++
++#if defined(NV_DRM_DRM_PRIME_H_PRESENT)
++#include <drm/drm_prime.h>
++#endif
++
++#include "nvidia-drm-gem-user-memory.h"
++#include "nvidia-drm-helper.h"
++#include "nvidia-drm-ioctl.h"
++
++static inline
++void __nv_drm_gem_user_memory_free(struct nv_drm_gem_object *nv_gem)
++{
++ struct nv_drm_gem_user_memory *nv_user_memory = to_nv_user_memory(nv_gem);
++
++ nv_drm_unlock_user_pages(nv_user_memory->pages_count,
++ nv_user_memory->pages);
++
++ nv_drm_free(nv_user_memory);
++}
++
++static struct sg_table *__nv_drm_gem_user_memory_prime_get_sg_table(
++ struct nv_drm_gem_object *nv_gem)
++{
++ struct nv_drm_gem_user_memory *nv_user_memory = to_nv_user_memory(nv_gem);
++ struct drm_gem_object *gem = &nv_gem->base;
++
++ return nv_drm_prime_pages_to_sg(gem->dev,
++ nv_user_memory->pages,
++ nv_user_memory->pages_count);
++}
++
++static void *__nv_drm_gem_user_memory_prime_vmap(
++ struct nv_drm_gem_object *nv_gem)
++{
++ struct nv_drm_gem_user_memory *nv_user_memory = to_nv_user_memory(nv_gem);
++
++ return nv_drm_vmap(nv_user_memory->pages,
++ nv_user_memory->pages_count);
++}
++
++static void __nv_drm_gem_user_memory_prime_vunmap(
++ struct nv_drm_gem_object *gem,
++ void *address)
++{
++ nv_drm_vunmap(address);
++}
++
++static struct nv_drm_gem_object_funcs __nv_gem_user_memory_ops = {
++ .free = __nv_drm_gem_user_memory_free,
++ .prime_get_sg_table = __nv_drm_gem_user_memory_prime_get_sg_table,
++ .prime_vmap = __nv_drm_gem_user_memory_prime_vmap,
++ .prime_vunmap = __nv_drm_gem_user_memory_prime_vunmap,
++};
++
++int nv_drm_gem_import_userspace_memory_ioctl(struct drm_device *dev,
++ void *data, struct drm_file *filep)
++{
++ struct nv_drm_device *nv_dev = to_nv_device(dev);
++
++ struct drm_nvidia_gem_import_userspace_memory_params *params = data;
++ struct nv_drm_gem_user_memory *nv_user_memory;
++
++ struct page **pages = NULL;
++ unsigned long pages_count = 0;
++
++ int ret = 0;
++
++ if ((params->size % PAGE_SIZE) != 0) {
++ NV_DRM_DEV_LOG_ERR(
++ nv_dev,
++ "Userspace memory 0x%llx size should be in a multiple of page "
++ "size to create a gem object",
++ params->address);
++ return -EINVAL;
++ }
++
++ pages_count = params->size / PAGE_SIZE;
++
++ ret = nv_drm_lock_user_pages(params->address, pages_count, &pages);
++
++ if (ret != 0) {
++ NV_DRM_DEV_LOG_ERR(
++ nv_dev,
++ "Failed to lock user pages for address 0x%llx: %d",
++ params->address, ret);
++ return ret;
++ }
++
++ if ((nv_user_memory =
++ nv_drm_calloc(1, sizeof(*nv_user_memory))) == NULL) {
++ ret = -ENOMEM;
++ goto failed;
++ }
++
++ nv_user_memory->pages = pages;
++ nv_user_memory->pages_count = pages_count;
++
++ nv_drm_gem_object_init(nv_dev,
++ &nv_user_memory->base,
++ &__nv_gem_user_memory_ops,
++ params->size,
++ true);
++
++ return nv_drm_gem_handle_create_drop_reference(filep,
++ &nv_user_memory->base,
++ ¶ms->handle);
++
++failed:
++ nv_drm_unlock_user_pages(pages_count, pages);
++
++ return ret;
++}
++
++#endif
+diff -Naur a/kernel/nvidia-drm-gem-user-memory.h b/kernel/nvidia-drm-gem-user-memory.h
+--- a/kernel/nvidia-drm-gem-user-memory.h 1970-01-01 01:00:00.000000000 +0100
++++ b/kernel/nvidia-drm-gem-user-memory.h 2021-06-09 21:37:47.510578416 +0200
+@@ -0,0 +1,53 @@
++/*
++ * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++#ifndef __NVIDIA_DRM_GEM_USER_MEMORY_H__
++#define __NVIDIA_DRM_GEM_USER_MEMORY_H__
++
++#include "nvidia-drm-conftest.h"
++
++#if defined(NV_DRM_AVAILABLE)
++
++#include "nvidia-drm-gem.h"
++
++struct nv_drm_gem_user_memory {
++ struct nv_drm_gem_object base;
++ struct page **pages;
++ unsigned long pages_count;
++};
++
++static inline struct nv_drm_gem_user_memory *to_nv_user_memory(
++ struct nv_drm_gem_object *nv_gem)
++{
++ if (nv_gem != NULL) {
++ return container_of(nv_gem, struct nv_drm_gem_user_memory, base);
++ }
++
++ return NULL;
++}
++
++int nv_drm_gem_import_userspace_memory_ioctl(struct drm_device *dev,
++ void *data, struct drm_file *filep);
++
++#endif
++
++#endif /* __NVIDIA_DRM_GEM_USER_MEMORY_H__ */
+diff -Naur a/kernel/nvidia-drm-helper.c b/kernel/nvidia-drm-helper.c
+--- a/kernel/nvidia-drm-helper.c 1970-01-01 01:00:00.000000000 +0100
++++ b/kernel/nvidia-drm-helper.c 2021-06-09 21:37:47.511578395 +0200
+@@ -0,0 +1,189 @@
++/*
++ * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++/*
++ * This file contains snapshots of DRM helper functions from the
++ * Linux kernel which are used by nvidia-drm.ko if the target kernel
++ * predates the helper function. Having these functions consistently
++ * present simplifies nvidia-drm.ko source.
++ */
++
++#include "nvidia-drm-helper.h"
++
++#if defined(NV_DRM_ATOMIC_MODESET_AVAILABLE)
++
++#if defined(NV_DRM_DRMP_H_PRESENT)
++#include <drm/drmP.h>
++#endif
++
++#if defined(NV_DRM_DRM_ATOMIC_UAPI_H_PRESENT)
++#include <drm/drm_atomic_uapi.h>
++#endif
++
++static void __nv_drm_framebuffer_put(struct drm_framebuffer *fb)
++{
++#if defined(NV_DRM_FRAMEBUFFER_GET_PRESENT)
++ drm_framebuffer_put(fb);
++#else
++ drm_framebuffer_unreference(fb);
++#endif
++
++}
++
++/*
++ * drm_atomic_helper_disable_all() has been added by commit
++ * 1494276000db789c6d2acd85747be4707051c801, which is Signed-off-by:
++ * Thierry Reding <treding(a)nvidia.com>
++ * Daniel Vetter <daniel.vetter(a)ffwll.ch>
++ *
++ * drm_atomic_helper_disable_all() is copied from
++ * linux/drivers/gpu/drm/drm_atomic_helper.c and modified to use
++ * nv_drm_for_each_crtc instead of drm_for_each_crtc to loop over all crtcs,
++ * use nv_drm_for_each_*_in_state instead of for_each_connector_in_state to loop
++ * over all modeset object states, and use drm_atomic_state_free() if
++ * drm_atomic_state_put() is not available.
++ *
++ * drm_atomic_helper_disable_all() is copied from
++ * linux/drivers/gpu/drm/drm_atomic_helper.c @
++ * 49d70aeaeca8f62b72b7712ecd1e29619a445866, which has the following
++ * copyright and license information:
++ *
++ * Copyright (C) 2014 Red Hat
++ * Copyright (C) 2014 Intel Corp.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ * OTHER DEALINGS IN THE SOFTWARE.
++ *
++ * Authors:
++ * Rob Clark <robdclark(a)gmail.com>
++ * Daniel Vetter <daniel.vetter(a)ffwll.ch>
++ */
++int nv_drm_atomic_helper_disable_all(struct drm_device *dev,
++ struct drm_modeset_acquire_ctx *ctx)
++{
++ struct drm_atomic_state *state;
++ struct drm_connector_state *conn_state;
++ struct drm_connector *conn;
++ struct drm_plane_state *plane_state;
++ struct drm_plane *plane;
++ struct drm_crtc_state *crtc_state;
++ struct drm_crtc *crtc;
++ unsigned plane_mask = 0;
++ int ret, i;
++
++ state = drm_atomic_state_alloc(dev);
++ if (!state)
++ return -ENOMEM;
++
++ state->acquire_ctx = ctx;
++
++ nv_drm_for_each_crtc(crtc, dev) {
++ crtc_state = drm_atomic_get_crtc_state(state, crtc);
++ if (IS_ERR(crtc_state)) {
++ ret = PTR_ERR(crtc_state);
++ goto free;
++ }
++
++ crtc_state->active = false;
++
++ ret = drm_atomic_set_mode_prop_for_crtc(crtc_state, NULL);
++ if (ret < 0)
++ goto free;
++
++ ret = drm_atomic_add_affected_planes(state, crtc);
++ if (ret < 0)
++ goto free;
++
++ ret = drm_atomic_add_affected_connectors(state, crtc);
++ if (ret < 0)
++ goto free;
++ }
++
++ nv_drm_for_each_connector_in_state(state, conn, conn_state, i) {
++ ret = drm_atomic_set_crtc_for_connector(conn_state, NULL);
++ if (ret < 0)
++ goto free;
++ }
++
++ nv_drm_for_each_plane_in_state(state, plane, plane_state, i) {
++ ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
++ if (ret < 0)
++ goto free;
++
++ drm_atomic_set_fb_for_plane(plane_state, NULL);
++ plane_mask |= BIT(drm_plane_index(plane));
++ plane->old_fb = plane->fb;
++ }
++
++ ret = drm_atomic_commit(state);
++free:
++ if (plane_mask) {
++ drm_for_each_plane_mask(plane, dev, plane_mask) {
++ if (ret == 0) {
++ plane->fb = NULL;
++ plane->crtc = NULL;
++
++ WARN_ON(plane->state->fb);
++ WARN_ON(plane->state->crtc);
++
++ if (plane->old_fb)
++ __nv_drm_framebuffer_put(plane->old_fb);
++ }
++ plane->old_fb = NULL;
++ }
++ }
++
++#if defined(NV_DRM_ATOMIC_STATE_REF_COUNTING_PRESENT)
++ drm_atomic_state_put(state);
++#else
++ if (ret != 0) {
++ drm_atomic_state_free(state);
++ } else {
++ /*
++ * In case of success, drm_atomic_commit() takes care to cleanup and
++ * free @state.
++ *
++ * Comment placed above drm_atomic_commit() says: The caller must not
++ * free or in any other way access @state. If the function fails then
++ * the caller must clean up @state itself.
++ */
++ }
++#endif
++ return ret;
++}
++
++#endif /* NV_DRM_ATOMIC_MODESET_AVAILABLE */
+diff -Naur a/kernel/nvidia-drm-helper.h b/kernel/nvidia-drm-helper.h
+--- a/kernel/nvidia-drm-helper.h 1970-01-01 01:00:00.000000000 +0100
++++ b/kernel/nvidia-drm-helper.h 2021-06-09 21:37:47.511578395 +0200
+@@ -0,0 +1,441 @@
++/*
++ * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++#ifndef __NVIDIA_DRM_HELPER_H__
++#define __NVIDIA_DRM_HELPER_H__
++
++#include "nvidia-drm-conftest.h"
++
++#if defined(NV_DRM_AVAILABLE)
++
++#if defined(NV_DRM_DRMP_H_PRESENT)
++#include <drm/drmP.h>
++#endif
++
++#if defined(NV_DRM_DRM_DRV_H_PRESENT)
++#include <drm/drm_drv.h>
++#endif
++
++/*
++ * drm_dev_put() is added by commit 9a96f55034e41b4e002b767e9218d55f03bdff7d
++ * (2017-09-26) and drm_dev_unref() is removed by
++ * ba1d345401476a5f7fbad622607c5a1f95e59b31 (2018-11-15).
++ *
++ * drm_dev_unref() has been added and drm_dev_free() removed by commit -
++ *
++ * 2014-01-29: 099d1c290e2ebc3b798961a6c177c3aef5f0b789
++ */
++static inline void nv_drm_dev_free(struct drm_device *dev)
++{
++#if defined(NV_DRM_DEV_PUT_PRESENT)
++ drm_dev_put(dev);
++#elif defined(NV_DRM_DEV_UNREF_PRESENT)
++ drm_dev_unref(dev);
++#else
++ drm_dev_free(dev);
++#endif
++}
++
++#if defined(NV_DRM_DRM_PRIME_H_PRESENT)
++#include <drm/drm_prime.h>
++#endif
++
++static inline struct sg_table*
++nv_drm_prime_pages_to_sg(struct drm_device *dev,
++ struct page **pages, unsigned int nr_pages)
++{
++#if defined(NV_DRM_PRIME_PAGES_TO_SG_HAS_DRM_DEVICE_ARG)
++ return drm_prime_pages_to_sg(dev, pages, nr_pages);
++#else
++ return drm_prime_pages_to_sg(pages, nr_pages);
++#endif
++}
++
++#if defined(NV_DRM_ATOMIC_MODESET_AVAILABLE)
++
++/*
++ * drm_for_each_connector(), drm_for_each_crtc(), drm_for_each_fb(),
++ * drm_for_each_encoder and drm_for_each_plane() were added by kernel
++ * commit 6295d607ad34ee4e43aab3f20714c2ef7a6adea1 which was
++ * Signed-off-by:
++ * Daniel Vetter <daniel.vetter(a)intel.com>
++ * drm_for_each_connector(), drm_for_each_crtc(), drm_for_each_fb(),
++ * drm_for_each_encoder and drm_for_each_plane() are copied from
++ * include/drm/drm_crtc @
++ * 6295d607ad34ee4e43aab3f20714c2ef7a6adea1
++ * which has the following copyright and license information:
++ *
++ * Copyright © 2006 Keith Packard
++ * Copyright © 2007-2008 Dave Airlie
++ * Copyright © 2007-2008 Intel Corporation
++ * Jesse Barnes <jesse.barnes(a)intel.com>
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ * OTHER DEALINGS IN THE SOFTWARE.
++ */
++#include <drm/drm_crtc.h>
++
++#if defined(drm_for_each_plane)
++#define nv_drm_for_each_plane(plane, dev) \
++ drm_for_each_plane(plane, dev)
++#else
++#define nv_drm_for_each_plane(plane, dev) \
++ list_for_each_entry(plane, &(dev)->mode_config.plane_list, head)
++#endif
++
++#if defined(drm_for_each_crtc)
++#define nv_drm_for_each_crtc(crtc, dev) \
++ drm_for_each_crtc(crtc, dev)
++#else
++#define nv_drm_for_each_crtc(crtc, dev) \
++ list_for_each_entry(crtc, &(dev)->mode_config.crtc_list, head)
++#endif
++
++#if defined(NV_DRM_CONNECTOR_LIST_ITER_PRESENT)
++#define nv_drm_for_each_connector(connector, conn_iter, dev) \
++ drm_for_each_connector_iter(connector, conn_iter)
++#elif defined(drm_for_each_connector)
++#define nv_drm_for_each_connector(connector, conn_iter, dev) \
++ drm_for_each_connector(connector, dev)
++#else
++#define nv_drm_for_each_connector(connector, conn_iter, dev) \
++ WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); \
++ list_for_each_entry(connector, &(dev)->mode_config.connector_list, head)
++#endif
++
++#if defined(drm_for_each_encoder)
++#define nv_drm_for_each_encoder(encoder, dev) \
++ drm_for_each_encoder(encoder, dev)
++#else
++#define nv_drm_for_each_encoder(encoder, dev) \
++ list_for_each_entry(encoder, &(dev)->mode_config.encoder_list, head)
++#endif
++
++#if defined(drm_for_each_fb)
++#define nv_drm_for_each_fb(fb, dev) \
++ drm_for_each_fb(fb, dev)
++#else
++#define nv_drm_for_each_fb(fb, dev) \
++ list_for_each_entry(fb, &(dev)->mode_config.fb_list, head)
++#endif
++
++#include <drm/drm_atomic.h>
++#include <drm/drm_atomic_helper.h>
++
++int nv_drm_atomic_helper_disable_all(struct drm_device *dev,
++ struct drm_modeset_acquire_ctx *ctx);
++
++/*
++ * for_each_connector_in_state(), for_each_crtc_in_state() and
++ * for_each_plane_in_state() were added by kernel commit
++ * df63b9994eaf942afcdb946d27a28661d7dfbf2a which was Signed-off-by:
++ * Ander Conselvan de Oliveira <ander.conselvan.de.oliveira(a)intel.com>
++ * Daniel Vetter <daniel.vetter(a)ffwll.ch>
++ *
++ * for_each_connector_in_state(), for_each_crtc_in_state() and
++ * for_each_plane_in_state() were copied from
++ * include/drm/drm_atomic.h @
++ * 21a01abbe32a3cbeb903378a24e504bfd9fe0648
++ * which has the following copyright and license information:
++ *
++ * Copyright (C) 2014 Red Hat
++ * Copyright (C) 2014 Intel Corp.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ * OTHER DEALINGS IN THE SOFTWARE.
++ *
++ * Authors:
++ * Rob Clark <robdclark(a)gmail.com>
++ * Daniel Vetter <daniel.vetter(a)ffwll.ch>
++ */
++
++/**
++ * nv_drm_for_each_connector_in_state - iterate over all connectors in an
++ * atomic update
++ * @__state: &struct drm_atomic_state pointer
++ * @connector: &struct drm_connector iteration cursor
++ * @connector_state: &struct drm_connector_state iteration cursor
++ * @__i: int iteration cursor, for macro-internal use
++ *
++ * This iterates over all connectors in an atomic update. Note that before the
++ * software state is committed (by calling drm_atomic_helper_swap_state(), this
++ * points to the new state, while afterwards it points to the old state. Due to
++ * this tricky confusion this macro is deprecated.
++ */
++#if !defined(for_each_connector_in_state)
++#define nv_drm_for_each_connector_in_state(__state, \
++ connector, connector_state, __i) \
++ for ((__i) = 0; \
++ (__i) < (__state)->num_connector &&
\
++ ((connector) = (__state)->connectors[__i].ptr, \
++ (connector_state) = (__state)->connectors[__i].state, 1); \
++ (__i)++) \
++ for_each_if (connector)
++#else
++#define nv_drm_for_each_connector_in_state(__state, \
++ connector, connector_state, __i) \
++ for_each_connector_in_state(__state, connector, connector_state, __i)
++#endif
++
++
++/**
++ * nv_drm_for_each_crtc_in_state - iterate over all CRTCs in an atomic update
++ * @__state: &struct drm_atomic_state pointer
++ * @crtc: &struct drm_crtc iteration cursor
++ * @crtc_state: &struct drm_crtc_state iteration cursor
++ * @__i: int iteration cursor, for macro-internal use
++ *
++ * This iterates over all CRTCs in an atomic update. Note that before the
++ * software state is committed (by calling drm_atomic_helper_swap_state(), this
++ * points to the new state, while afterwards it points to the old state. Due to
++ * this tricky confusion this macro is deprecated.
++ */
++#if !defined(for_each_crtc_in_state)
++#define nv_drm_for_each_crtc_in_state(__state, crtc, crtc_state, __i) \
++ for ((__i) = 0; \
++ (__i) < (__state)->dev->mode_config.num_crtc &&
\
++ ((crtc) = (__state)->crtcs[__i].ptr, \
++ (crtc_state) = (__state)->crtcs[__i].state, 1); \
++ (__i)++) \
++ for_each_if (crtc_state)
++#else
++#define nv_drm_for_each_crtc_in_state(__state, crtc, crtc_state, __i) \
++ for_each_crtc_in_state(__state, crtc, crtc_state, __i)
++#endif
++
++/**
++ * nv_drm_for_each_plane_in_state - iterate over all planes in an atomic update
++ * @__state: &struct drm_atomic_state pointer
++ * @plane: &struct drm_plane iteration cursor
++ * @plane_state: &struct drm_plane_state iteration cursor
++ * @__i: int iteration cursor, for macro-internal use
++ *
++ * This iterates over all planes in an atomic update. Note that before the
++ * software state is committed (by calling drm_atomic_helper_swap_state(), this
++ * points to the new state, while afterwards it points to the old state. Due to
++ * this tricky confusion this macro is deprecated.
++ */
++#if !defined(for_each_plane_in_state)
++#define nv_drm_for_each_plane_in_state(__state, plane, plane_state, __i) \
++ for ((__i) = 0; \
++ (__i) < (__state)->dev->mode_config.num_total_plane &&
\
++ ((plane) = (__state)->planes[__i].ptr, \
++ (plane_state) = (__state)->planes[__i].state, 1); \
++ (__i)++) \
++ for_each_if (plane_state)
++#else
++#define nv_drm_for_each_plane_in_state(__state, plane, plane_state, __i) \
++ for_each_plane_in_state(__state, plane, plane_state, __i)
++#endif
++
++static inline struct drm_crtc *nv_drm_crtc_find(struct drm_device *dev,
++ uint32_t id)
++{
++#if defined(NV_DRM_MODE_OBJECT_FIND_HAS_FILE_PRIV_ARG)
++ return drm_crtc_find(dev, NULL /* file_priv */, id);
++#else
++ return drm_crtc_find(dev, id);
++#endif
++}
++
++static inline struct drm_encoder *nv_drm_encoder_find(struct drm_device *dev,
++ uint32_t id)
++{
++#if defined(NV_DRM_MODE_OBJECT_FIND_HAS_FILE_PRIV_ARG)
++ return drm_encoder_find(dev, NULL /* file_priv */, id);
++#else
++ return drm_encoder_find(dev, id);
++#endif
++}
++
++/*
++ * drm_connector_for_each_possible_encoder() is added by commit
++ * 83aefbb887b59df0b3520965c3701e01deacfc52 which was Signed-off-by:
++ * Ville Syrjälä <ville.syrjala(a)linux.intel.com>
++ *
++ * drm_connector_for_each_possible_encoder() is copied from
++ * include/drm/drm_connector.h and modified to use nv_drm_encoder_find()
++ * instead of drm_encoder_find().
++ *
++ * drm_connector_for_each_possible_encoder() is copied from
++ * include/drm/drm_connector.h @
++ * 83aefbb887b59df0b3520965c3701e01deacfc52
++ * which has the following copyright and license information:
++ *
++ * Copyright (c) 2016 Intel Corporation
++ *
++ * Permission to use, copy, modify, distribute, and sell this software and its
++ * documentation for any purpose is hereby granted without fee, provided that
++ * the above copyright notice appear in all copies and that both that copyright
++ * notice and this permission notice appear in supporting documentation, and
++ * that the name of the copyright holders not be used in advertising or
++ * publicity pertaining to distribution of the software without specific,
++ * written prior permission. The copyright holders make no representations
++ * about the suitability of this software for any purpose. It is provided "as
++ * is" without express or implied warranty.
++ *
++ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
++ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
++ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
++ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
++ * OF THIS SOFTWARE.
++ */
++
++#if defined(NV_DRM_DRM_CONNECTOR_H_PRESENT)
++#include <drm/drm_connector.h>
++#endif
++
++/**
++ * nv_drm_connector_for_each_possible_encoder - iterate connector's possible
++ * encoders
++ * @connector: &struct drm_connector pointer
++ * @encoder: &struct drm_encoder pointer used as cursor
++ * @__i: int iteration cursor, for macro-internal use
++ */
++#if !defined(drm_connector_for_each_possible_encoder)
++
++#if !defined(for_each_if)
++#define for_each_if(condition) if (!(condition)) {} else
++#endif
++
++#define __nv_drm_connector_for_each_possible_encoder(connector, encoder, __i) \
++ for ((__i) = 0; (__i) < ARRAY_SIZE((connector)->encoder_ids) &&
\
++ (connector)->encoder_ids[(__i)] != 0; (__i)++) \
++ for_each_if((encoder) = \
++ nv_drm_encoder_find((connector)->dev, \
++ (connector)->encoder_ids[(__i)]))
++
++#define nv_drm_connector_for_each_possible_encoder(connector, encoder) \
++ { \
++ unsigned int __i; \
++ __nv_drm_connector_for_each_possible_encoder(connector, encoder, __i)
++
++#define nv_drm_connector_for_each_possible_encoder_end \
++ }
++
++#else
++
++#if NV_DRM_CONNECTOR_FOR_EACH_POSSIBLE_ENCODER_ARGUMENT_COUNT == 3
++
++#define nv_drm_connector_for_each_possible_encoder(connector, encoder) \
++ { \
++ unsigned int __i; \
++ drm_connector_for_each_possible_encoder(connector, encoder, __i)
++
++#define nv_drm_connector_for_each_possible_encoder_end \
++ }
++
++#else
++
++#define nv_drm_connector_for_each_possible_encoder(connector, encoder) \
++ drm_connector_for_each_possible_encoder(connector, encoder)
++
++#define nv_drm_connector_for_each_possible_encoder_end
++
++#endif
++
++#endif
++
++static inline int
++nv_drm_connector_attach_encoder(struct drm_connector *connector,
++ struct drm_encoder *encoder)
++{
++#if defined(NV_DRM_CONNECTOR_FUNCS_HAVE_MODE_IN_NAME)
++ return drm_mode_connector_attach_encoder(connector, encoder);
++#else
++ return drm_connector_attach_encoder(connector, encoder);
++#endif
++}
++
++static inline int
++nv_drm_connector_update_edid_property(struct drm_connector *connector,
++ const struct edid *edid)
++{
++#if defined(NV_DRM_CONNECTOR_FUNCS_HAVE_MODE_IN_NAME)
++ return drm_mode_connector_update_edid_property(connector, edid);
++#else
++ return drm_connector_update_edid_property(connector, edid);
++#endif
++}
++
++#if defined(NV_DRM_CONNECTOR_LIST_ITER_PRESENT)
++#include <drm/drm_connector.h>
++
++static inline
++void nv_drm_connector_list_iter_begin(struct drm_device *dev,
++ struct drm_connector_list_iter *iter)
++{
++#if defined(NV_DRM_CONNECTOR_LIST_ITER_BEGIN_PRESENT)
++ drm_connector_list_iter_begin(dev, iter);
++#else
++ drm_connector_list_iter_get(dev, iter);
++#endif
++}
++
++static inline
++void nv_drm_connector_list_iter_end(struct drm_connector_list_iter *iter)
++{
++#if defined(NV_DRM_CONNECTOR_LIST_ITER_BEGIN_PRESENT)
++ drm_connector_list_iter_end(iter);
++#else
++ drm_connector_list_iter_put(iter);
++#endif
++}
++#endif
++
++#endif /* defined(NV_DRM_ATOMIC_MODESET_AVAILABLE) */
++
++#endif /* defined(NV_DRM_AVAILABLE) */
++
++#endif /* __NVIDIA_DRM_HELPER_H__ */
+diff -Naur a/kernel/nvidia-drm-ioctl.h b/kernel/nvidia-drm-ioctl.h
+--- a/kernel/nvidia-drm-ioctl.h 1970-01-01 01:00:00.000000000 +0100
++++ b/kernel/nvidia-drm-ioctl.h 2021-06-09 21:37:47.511578395 +0200
+@@ -0,0 +1,135 @@
++/*
++ * Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ * OTHER DEALINGS IN THE SOFTWARE.
++ */
++
++#ifndef _UAPI_NVIDIA_DRM_IOCTL_H_
++#define _UAPI_NVIDIA_DRM_IOCTL_H_
++
++#include <drm/drm.h>
++
++/*
++ * We should do our best to keep these values constant. Any change to these will
++ * be backwards incompatible with client applications that might be using them
++ */
++#define DRM_NVIDIA_GET_CRTC_CRC32 0x00
++#define DRM_NVIDIA_GEM_IMPORT_NVKMS_MEMORY 0x01
++#define DRM_NVIDIA_GEM_IMPORT_USERSPACE_MEMORY 0x02
++#define DRM_NVIDIA_GET_DEV_INFO 0x03
++#define DRM_NVIDIA_FENCE_SUPPORTED 0x04
++#define DRM_NVIDIA_FENCE_CONTEXT_CREATE 0x05
++#define DRM_NVIDIA_GEM_FENCE_ATTACH 0x06
++#define DRM_NVIDIA_GET_CLIENT_CAPABILITY 0x08
++
++#define DRM_IOCTL_NVIDIA_GEM_IMPORT_NVKMS_MEMORY \
++ DRM_IOWR((DRM_COMMAND_BASE + DRM_NVIDIA_GEM_IMPORT_NVKMS_MEMORY), \
++ struct drm_nvidia_gem_import_nvkms_memory_params)
++
++#define DRM_IOCTL_NVIDIA_GEM_IMPORT_USERSPACE_MEMORY \
++ DRM_IOWR((DRM_COMMAND_BASE + DRM_NVIDIA_GEM_IMPORT_USERSPACE_MEMORY), \
++ struct drm_nvidia_gem_import_userspace_memory_params)
++
++#define DRM_IOCTL_NVIDIA_GET_DEV_INFO \
++ DRM_IOWR((DRM_COMMAND_BASE + DRM_NVIDIA_GET_DEV_INFO), \
++ struct drm_nvidia_get_dev_info_params)
++
++/*
++ * XXX Solaris compiler has issues with DRM_IO. None of this is supported on
++ * Solaris anyway, so just skip it.
++ *
++ * 'warning: suggest parentheses around arithmetic in operand of |'
++ */
++#if defined(NV_LINUX)
++#define DRM_IOCTL_NVIDIA_FENCE_SUPPORTED \
++ DRM_IO(DRM_COMMAND_BASE + DRM_NVIDIA_FENCE_SUPPORTED)
++#else
++#define DRM_IOCTL_NVIDIA_FENCE_SUPPORTED 0
++#endif
++
++#define DRM_IOCTL_NVIDIA_FENCE_CONTEXT_CREATE \
++ DRM_IOWR((DRM_COMMAND_BASE + DRM_NVIDIA_FENCE_CONTEXT_CREATE), \
++ struct drm_nvidia_fence_context_create_params)
++
++#define DRM_IOCTL_NVIDIA_GEM_FENCE_ATTACH \
++ DRM_IOW((DRM_COMMAND_BASE + DRM_NVIDIA_GEM_FENCE_ATTACH), \
++ struct drm_nvidia_gem_fence_attach_params)
++
++#define DRM_IOCTL_NVIDIA_GET_CLIENT_CAPABILITY \
++ DRM_IOWR((DRM_COMMAND_BASE + DRM_NVIDIA_GET_CLIENT_CAPABILITY), \
++ struct drm_nvidia_get_client_capability_params)
++
++#define DRM_IOCTL_NVIDIA_GET_CRTC_CRC32 \
++ DRM_IOWR((DRM_COMMAND_BASE + DRM_NVIDIA_GET_CRTC_CRC32), \
++ struct drm_nvidia_get_crtc_crc32_params)
++
++struct drm_nvidia_gem_import_nvkms_memory_params {
++ uint64_t mem_size; /* IN */
++
++ uint64_t nvkms_params_ptr; /* IN */
++ uint64_t nvkms_params_size; /* IN */
++
++ uint32_t handle; /* OUT */
++
++ uint32_t __pad;
++};
++
++struct drm_nvidia_gem_import_userspace_memory_params {
++ uint64_t size; /* IN Size of memory in bytes */
++ uint64_t address; /* IN Virtual address of userspace memory */
++ uint32_t handle; /* OUT Handle to gem object */
++};
++
++struct drm_nvidia_get_dev_info_params {
++ uint32_t gpu_id; /* OUT */
++ uint32_t primary_index; /* OUT; the "card%d" value */
++};
++
++struct drm_nvidia_fence_context_create_params {
++ uint32_t handle; /* OUT GEM handle to fence context */
++
++ uint32_t index; /* IN Index of semaphore to use for fencing */
++ uint64_t size; /* IN Size of semaphore surface in bytes */
++
++ /* Params for importing userspace semaphore surface */
++ uint64_t import_mem_nvkms_params_ptr; /* IN */
++ uint64_t import_mem_nvkms_params_size; /* IN */
++
++ /* Params for creating software signaling event */
++ uint64_t event_nvkms_params_ptr; /* IN */
++ uint64_t event_nvkms_params_size; /* IN */
++};
++
++struct drm_nvidia_gem_fence_attach_params {
++ uint32_t handle; /* IN GEM handle to attach fence to */
++ uint32_t fence_context_handle; /* IN GEM handle to fence context on which fence is
run on */
++ uint32_t sem_thresh; /* IN Semaphore value to reach before signal */
++};
++
++struct drm_nvidia_get_client_capability_params {
++ uint64_t capability; /* IN Client capability enum */
++ uint64_t value; /* OUT Client capability value */
++};
++
++struct drm_nvidia_get_crtc_crc32_params {
++ uint32_t crtc_id; /* IN CRTC identifier */
++ uint32_t crc32; /* OUT CRC32 value */
++};
++
++#endif /* _UAPI_NVIDIA_DRM_IOCTL_H_ */
+diff -Naur a/kernel/nvidia-drm-linux.c b/kernel/nvidia-drm-linux.c
+--- a/kernel/nvidia-drm-linux.c 1970-01-01 01:00:00.000000000 +0100
++++ b/kernel/nvidia-drm-linux.c 2021-06-09 21:37:47.511578395 +0200
+@@ -0,0 +1,185 @@
++/*
++ * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/err.h>
++
++#include "nvidia-drm-os-interface.h"
++#include "nvidia-drm.h"
++
++#include "conftest.h"
++
++#if defined(NV_DRM_AVAILABLE)
++
++#include <linux/vmalloc.h>
++
++#if defined(NV_DRM_DRMP_H_PRESENT)
++#include <drm/drmP.h>
++#endif
++
++#include "nv-mm.h"
++
++MODULE_PARM_DESC(
++ modeset,
++ "Enable atomic kernel modesetting (1 = enable, 0 = disable (default))");
++bool nv_drm_modeset_module_param = false;
++module_param_named(modeset, nv_drm_modeset_module_param, bool, 0400);
++
++void *nv_drm_calloc(size_t nmemb, size_t size)
++{
++ return kzalloc(nmemb * size, GFP_KERNEL);
++}
++
++void nv_drm_free(void *ptr)
++{
++ if (IS_ERR(ptr)) {
++ return;
++ }
++
++ kfree(ptr);
++}
++
++char *nv_drm_asprintf(const char *fmt, ...)
++{
++ va_list ap;
++ char *p;
++
++ va_start(ap, fmt);
++ p = kvasprintf(GFP_KERNEL, fmt, ap);
++ va_end(ap);
++
++ return p;
++}
++
++#if defined(NVCPU_X86) || defined(NVCPU_X86_64)
++ #define WRITE_COMBINE_FLUSH() asm
volatile("sfence":::"memory")
++#elif defined(NVCPU_FAMILY_ARM)
++ #if defined(NVCPU_ARM)
++ #define WRITE_COMBINE_FLUSH() { dsb(); outer_sync(); }
++ #elif defined(NVCPU_AARCH64)
++ #define WRITE_COMBINE_FLUSH() mb()
++ #endif
++#elif defined(NVCPU_PPC64LE)
++ #define WRITE_COMBINE_FLUSH() asm volatile("sync":::"memory")
++#endif
++
++void nv_drm_write_combine_flush(void)
++{
++ WRITE_COMBINE_FLUSH();
++}
++
++int nv_drm_lock_user_pages(unsigned long address,
++ unsigned long pages_count, struct page ***pages)
++{
++ struct mm_struct *mm = current->mm;
++ struct page **user_pages;
++ const int write = 1;
++ const int force = 0;
++ int pages_pinned;
++
++ user_pages = nv_drm_calloc(pages_count, sizeof(*user_pages));
++
++ if (user_pages == NULL) {
++ return -ENOMEM;
++ }
++
++ nv_mmap_read_lock(mm);
++
++ pages_pinned = NV_GET_USER_PAGES(address, pages_count, write, force,
++ user_pages, NULL);
++ nv_mmap_read_unlock(mm);
++
++ if (pages_pinned < 0 || (unsigned)pages_pinned < pages_count) {
++ goto failed;
++ }
++
++ *pages = user_pages;
++
++ return 0;
++
++failed:
++
++ if (pages_pinned > 0) {
++ int i;
++
++ for (i = 0; i < pages_pinned; i++) {
++ put_page(user_pages[i]);
++ }
++ }
++
++ nv_drm_free(user_pages);
++
++ return (pages_pinned < 0) ? pages_pinned : -EINVAL;
++}
++
++void nv_drm_unlock_user_pages(unsigned long pages_count, struct page **pages)
++{
++ unsigned long i;
++
++ for (i = 0; i < pages_count; i++) {
++ set_page_dirty_lock(pages[i]);
++
++ put_page(pages[i]);
++ }
++
++ nv_drm_free(pages);
++}
++
++void *nv_drm_vmap(struct page **pages, unsigned long pages_count)
++{
++ return vmap(pages, pages_count, VM_USERMAP, PAGE_KERNEL);
++}
++
++void nv_drm_vunmap(void *address)
++{
++ vunmap(address);
++}
++
++#endif /* NV_DRM_AVAILABLE */
++
++/*************************************************************************
++ * Linux loading support code.
++ *************************************************************************/
++
++static int __init nv_linux_drm_init(void)
++{
++ return nv_drm_init();
++}
++
++static void __exit nv_linux_drm_exit(void)
++{
++ nv_drm_exit();
++}
++
++module_init(nv_linux_drm_init);
++module_exit(nv_linux_drm_exit);
++
++#if defined(MODULE_LICENSE)
++ MODULE_LICENSE("MIT");
++#endif
++#if defined(MODULE_INFO)
++ MODULE_INFO(supported, "external");
++#endif
++#if defined(MODULE_VERSION)
++ MODULE_VERSION(NV_VERSION_STRING);
++#endif
+diff -Naur a/kernel/nvidia-drm-os-interface.h b/kernel/nvidia-drm-os-interface.h
+--- a/kernel/nvidia-drm-os-interface.h 1970-01-01 01:00:00.000000000 +0100
++++ b/kernel/nvidia-drm-os-interface.h 2021-06-09 21:37:47.512578373 +0200
+@@ -0,0 +1,56 @@
++/*
++ * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++#ifndef __NVIDIA_DRM_OS_INTERFACE_H__
++#define __NVIDIA_DRM_OS_INTERFACE_H__
++
++#include "nvidia-drm-conftest.h" /* NV_DRM_AVAILABLE */
++
++#include "nvtypes.h"
++
++#if defined(NV_DRM_AVAILABLE)
++
++struct page;
++
++/* Set to true when the atomic modeset feature is enabled. */
++extern bool nv_drm_modeset_module_param;
++
++void *nv_drm_calloc(size_t nmemb, size_t size);
++
++void nv_drm_free(void *ptr);
++
++char *nv_drm_asprintf(const char *fmt, ...);
++
++void nv_drm_write_combine_flush(void);
++
++int nv_drm_lock_user_pages(unsigned long address,
++ unsigned long pages_count, struct page ***pages);
++
++void nv_drm_unlock_user_pages(unsigned long pages_count, struct page **pages);
++
++void *nv_drm_vmap(struct page **pages, unsigned long pages_count);
++
++void nv_drm_vunmap(void *address);
++
++#endif
++
++#endif /* __NVIDIA_DRM_OS_INTERFACE_H__ */
+diff -Naur a/kernel/nvidia-drm-priv.h b/kernel/nvidia-drm-priv.h
+--- a/kernel/nvidia-drm-priv.h 1970-01-01 01:00:00.000000000 +0100
++++ b/kernel/nvidia-drm-priv.h 2021-06-09 21:37:47.512578373 +0200
+@@ -0,0 +1,119 @@
++/*
++ * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++#ifndef __NVIDIA_DRM_PRIV_H__
++#define __NVIDIA_DRM_PRIV_H__
++
++#include "nvidia-drm-conftest.h" /* NV_DRM_AVAILABLE */
++
++#if defined(NV_DRM_AVAILABLE)
++
++#if defined(NV_DRM_DRMP_H_PRESENT)
++#include <drm/drmP.h>
++#endif
++
++#if defined(NV_DRM_DRM_DEVICE_H_PRESENT)
++#include <drm/drm_device.h>
++#endif
++
++#if defined(NV_DRM_DRM_GEM_H_PRESENT)
++#include <drm/drm_gem.h>
++#endif
++
++#include "nvidia-drm-os-interface.h"
++
++#include "nvkms-kapi.h"
++
++#define NV_DRM_LOG_ERR(__fmt, ...) \
++ DRM_ERROR("[nvidia-drm] " __fmt "\n", ##__VA_ARGS__)
++
++#define NV_DRM_LOG_INFO(__fmt, ...) \
++ DRM_INFO("[nvidia-drm] " __fmt "\n", ##__VA_ARGS__)
++
++#define NV_DRM_DEV_LOG_INFO(__dev, __fmt, ...) \
++ NV_DRM_LOG_INFO("[GPU ID 0x%08x] " __fmt, __dev->gpu_info.gpu_id,
##__VA_ARGS__)
++
++#define NV_DRM_DEV_LOG_ERR(__dev, __fmt, ...) \
++ NV_DRM_LOG_ERR("[GPU ID 0x%08x] " __fmt, __dev->gpu_info.gpu_id,
##__VA_ARGS__)
++
++#define NV_DRM_WARN(__condition) WARN_ON((__condition))
++
++struct nv_drm_device {
++ nv_gpu_info_t gpu_info;
++
++ struct drm_device *dev;
++
++ struct NvKmsKapiDevice *pDevice;
++
++#if defined(NV_DRM_ATOMIC_MODESET_AVAILABLE)
++ /*
++ * Lock to protect drm-subsystem and fields of this structure
++ * from concurrent access.
++ *
++ * Do not hold this lock if some lock from core drm-subsystem
++ * is already held, locking order should be like this -
++ *
++ * mutex_lock(nv_drm_device::lock);
++ * ....
++ * mutex_lock(drm_device::mode_config::lock);
++ * ....
++ * .......
++ * mutex_unlock(drm_device::mode_config::lock);
++ * ........
++ * ..
++ * mutex_lock(drm_device::struct_mutex);
++ * ....
++ * ........
++ * mutex_unlock(drm_device::struct_mutex);
++ * ..
++ * mutex_unlock(nv_drm_device::lock);
++ */
++ struct mutex lock;
++
++ NvU32 pitchAlignment;
++
++ atomic_t enable_event_handling;
++
++ /**
++ * @flip_event_wq:
++ *
++ * The wait queue on which nv_drm_atomic_commit_internal() sleeps until
++ * next flip event occurs.
++ */
++ wait_queue_head_t flip_event_wq;
++
++#endif
++
++ struct nv_drm_device *next;
++};
++
++static inline struct nv_drm_device *to_nv_device(
++ struct drm_device *dev)
++{
++ return dev->dev_private;
++}
++
++extern const struct NvKmsKapiFunctionsTable* const nvKms;
++
++#endif /* defined(NV_DRM_AVAILABLE) */
++
++#endif /* __NVIDIA_DRM_PRIV_H__ */
+diff -Naur a/kernel/nvkms-api-types.h b/kernel/nvkms-api-types.h
+--- a/kernel/nvkms-api-types.h 1970-01-01 01:00:00.000000000 +0100
++++ b/kernel/nvkms-api-types.h 2021-06-09 21:37:47.512578373 +0200
+@@ -0,0 +1,306 @@
++/*
++ * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved.
++ *
++ * NVIDIA CORPORATION and its licensors retain all intellectual property
++ * and proprietary rights in and to this software, related documentation
++ * and any modifications thereto. Any use, reproduction, disclosure or
++ * distribution of this software and related documentation without an express
++ * license agreement from NVIDIA CORPORATION is strictly prohibited.
++ */
++
++#if !defined(NVKMS_API_TYPES_H)
++#define NVKMS_API_TYPES_H
++
++#include "nvtypes.h"
++
++#define NVKMS_MAX_SUBDEVICES 8
++
++#define NVKMS_LEFT 0
++#define NVKMS_RIGHT 1
++#define NVKMS_MAX_EYES 2
++
++#define NVKMS_MAIN_PLANE 0
++#define NVKMS_OVERLAY_PLANE 1
++#define NVKMS_MAX_PLANES_PER_HEAD 2
++#define NVKMS_ALL_PLANES_MASK (BIT(NVKMS_MAIN_PLANE) | \
++ BIT(NVKMS_OVERLAY_PLANE))
++
++#define NVKMS_DP_ADDRESS_STRING_LENGTH 64
++
++typedef NvU32 NvKmsDeviceHandle;
++typedef NvU32 NvKmsDispHandle;
++typedef NvU32 NvKmsConnectorHandle;
++typedef NvU32 NvKmsSurfaceHandle;
++typedef NvU32 NvKmsFrameLockHandle;
++typedef NvU32 NvKmsDeferredRequestFifoHandle;
++typedef NvU32 NvKmsSwapGroupHandle;
++
++struct NvKmsSize {
++ NvU16 width;
++ NvU16 height;
++};
++
++struct NvKmsPoint {
++ NvU16 x;
++ NvU16 y;
++};
++
++struct NvKmsSignedPoint {
++ NvS16 x;
++ NvS16 y;
++};
++
++struct NvKmsRect {
++ NvU16 x;
++ NvU16 y;
++ NvU16 width;
++ NvU16 height;
++};
++
++/*
++ * A 3x3 row-major matrix.
++ *
++ * The elements are 32-bit single-precision IEEE floating point values. The
++ * floating point bit pattern should be stored in NvU32s to be passed into the
++ * kernel.
++ */
++struct NvKmsMatrix {
++ NvU32 m[3][3];
++};
++
++typedef enum {
++ NVKMS_CONNECTOR_TYPE_DP = 0,
++ NVKMS_CONNECTOR_TYPE_VGA = 1,
++ NVKMS_CONNECTOR_TYPE_DVI_I = 2,
++ NVKMS_CONNECTOR_TYPE_DVI_D = 3,
++ NVKMS_CONNECTOR_TYPE_ADC = 4,
++ NVKMS_CONNECTOR_TYPE_LVDS = 5,
++ NVKMS_CONNECTOR_TYPE_HDMI = 6,
++ NVKMS_CONNECTOR_TYPE_UNKNOWN = 7,
++ NVKMS_CONNECTOR_TYPE_MAX = NVKMS_CONNECTOR_TYPE_UNKNOWN,
++} NvKmsConnectorType;
++
++static inline
++const char *NvKmsConnectorTypeString(const NvKmsConnectorType connectorType)
++{
++ switch (connectorType) {
++ case NVKMS_CONNECTOR_TYPE_DP: return "DP";
++ case NVKMS_CONNECTOR_TYPE_VGA: return "VGA";
++ case NVKMS_CONNECTOR_TYPE_DVI_I: return "DVI-I";
++ case NVKMS_CONNECTOR_TYPE_DVI_D: return "DVI-D";
++ case NVKMS_CONNECTOR_TYPE_ADC: return "ADC";
++ case NVKMS_CONNECTOR_TYPE_LVDS: return "LVDS";
++ case NVKMS_CONNECTOR_TYPE_HDMI: return "HDMI";
++ default: break;
++ }
++ return "Unknown";
++}
++
++typedef enum {
++ NVKMS_CONNECTOR_SIGNAL_FORMAT_VGA = 0,
++ NVKMS_CONNECTOR_SIGNAL_FORMAT_LVDS = 1,
++ NVKMS_CONNECTOR_SIGNAL_FORMAT_TMDS = 2,
++ NVKMS_CONNECTOR_SIGNAL_FORMAT_DP = 3,
++ NVKMS_CONNECTOR_SIGNAL_FORMAT_UNKNOWN = 4,
++ NVKMS_CONNECTOR_SIGNAL_FORMAT_MAX =
++ NVKMS_CONNECTOR_SIGNAL_FORMAT_UNKNOWN,
++} NvKmsConnectorSignalFormat;
++
++enum NvKmsSurfaceMemoryFormat {
++ NvKmsSurfaceMemoryFormatI8 = 0,
++ NvKmsSurfaceMemoryFormatA1R5G5B5 = 1,
++ NvKmsSurfaceMemoryFormatX1R5G5B5 = 2,
++ NvKmsSurfaceMemoryFormatR5G6B5 = 3,
++ NvKmsSurfaceMemoryFormatA8R8G8B8 = 4,
++ NvKmsSurfaceMemoryFormatX8R8G8B8 = 5,
++ NvKmsSurfaceMemoryFormatA2B10G10R10 = 6,
++ NvKmsSurfaceMemoryFormatX2B10G10R10 = 7,
++ NvKmsSurfaceMemoryFormatA8B8G8R8 = 8,
++ NvKmsSurfaceMemoryFormatX8B8G8R8 = 9,
++};
++
++static inline NvU8 nvKmsSurfaceMemoryFormatToBytesPerPixel(
++ enum NvKmsSurfaceMemoryFormat format)
++{
++ switch (format)
++ {
++ case NvKmsSurfaceMemoryFormatI8:
++ return 1;
++ case NvKmsSurfaceMemoryFormatA1R5G5B5:
++ case NvKmsSurfaceMemoryFormatX1R5G5B5:
++ case NvKmsSurfaceMemoryFormatR5G6B5:
++ return 2;
++ case NvKmsSurfaceMemoryFormatA8R8G8B8:
++ case NvKmsSurfaceMemoryFormatX8R8G8B8:
++ case NvKmsSurfaceMemoryFormatA8B8G8R8:
++ case NvKmsSurfaceMemoryFormatX8B8G8R8:
++ case NvKmsSurfaceMemoryFormatA2B10G10R10:
++ case NvKmsSurfaceMemoryFormatX2B10G10R10:
++ return 4;
++ }
++
++ return 0;
++}
++
++static inline NvU8 nvKmsSurfaceMemoryFormatToBitsPerPixel(
++ enum NvKmsSurfaceMemoryFormat format)
++{
++ return nvKmsSurfaceMemoryFormatToBytesPerPixel(format) * 8;
++}
++
++static inline NvU8 nvKmsSurfaceMemoryFormatToDepth
++(
++ enum NvKmsSurfaceMemoryFormat format
++)
++{
++ switch (format)
++ {
++ case NvKmsSurfaceMemoryFormatI8:
++ return 8;
++ case NvKmsSurfaceMemoryFormatX1R5G5B5:
++ return 15;
++ case NvKmsSurfaceMemoryFormatA1R5G5B5:
++ case NvKmsSurfaceMemoryFormatR5G6B5:
++ return 16;
++ case NvKmsSurfaceMemoryFormatX8R8G8B8:
++ case NvKmsSurfaceMemoryFormatX8B8G8R8:
++ return 24;
++ case NvKmsSurfaceMemoryFormatX2B10G10R10:
++ return 30;
++ case NvKmsSurfaceMemoryFormatA8R8G8B8:
++ case NvKmsSurfaceMemoryFormatA8B8G8R8:
++ case NvKmsSurfaceMemoryFormatA2B10G10R10:
++ return 32;
++ }
++
++ return 0;
++}
++
++static inline const char *NvKmsSurfaceMemoryFormatToString
++(
++ const enum NvKmsSurfaceMemoryFormat format
++)
++{
++ switch (format) {
++ default:
++ /* Default return "Unknown" */
++ break;
++
++ case NvKmsSurfaceMemoryFormatI8:
++ return "I8";
++ case NvKmsSurfaceMemoryFormatA1R5G5B5:
++ return "A1R5G5B5";
++ case NvKmsSurfaceMemoryFormatX1R5G5B5:
++ return "X1R5G5B5";
++ case NvKmsSurfaceMemoryFormatR5G6B5:
++ return "R5G6B5";
++ case NvKmsSurfaceMemoryFormatA8R8G8B8:
++ return "A8R8G8B8";
++ case NvKmsSurfaceMemoryFormatX8R8G8B8:
++ return "X8R8G8B8";
++ case NvKmsSurfaceMemoryFormatA2B10G10R10:
++ return "A2B10G10R10";
++ case NvKmsSurfaceMemoryFormatX2B10G10R10:
++ return "X2B10G10R10";
++ case NvKmsSurfaceMemoryFormatA8B8G8R8:
++ return "A8B8G8R8";
++ case NvKmsSurfaceMemoryFormatX8B8G8R8:
++ return "X8B8G8R8";
++ }
++
++ return "Unknown";
++}
++
++/*!
++ * Description of Notifiers and Semaphores (Non-isochronous (NISO) surfaces).
++ *
++ * When flipping, the client can optionally specify a notifier and/or
++ * a semaphore to use with the flip. The surfaces used for these
++ * should be registered with NVKMS to get an NvKmsSurfaceHandle.
++ *
++ * NvKmsNIsoSurface::offsetInWords indicates the starting location, in
++ * 32-bit words, within the surface where EVO should write the
++ * notifier or semaphore. Note that only the first 4096 bytes of a
++ * surface can be used by semaphores or notifiers; offsetInWords must
++ * allow for the semaphore or notifier to be written within the first
++ * 4096 bytes of the surface. I.e., this must be satisfied:
++ *
++ * ((offsetInWords * 4) + elementSizeInBytes) <= 4096
++ *
++ * Where elementSizeInBytes is:
++ *
++ * if NISO_FORMAT_FOUR_WORD*, elementSizeInBytes = 16
++ * if NISO_FORMAT_LEGACY,
++ * if overlay && notifier, elementSizeInBytes = 16
++ * else, elementSizeInBytes = 4
++ *
++ * Note that different GPUs support different semaphore and notifier formats.
++ * Check NvKmsAllocDeviceReply::validNIsoFormatMask to determine which are
++ * valid for the given device.
++ *
++ * Note also that FOUR_WORD and FOUR_WORD_NVDISPLAY are the same size, but
++ * FOUR_WORD uses a format compatible with display class 907[ce], and
++ * FOUR_WORD_NVDISPLAY uses a format compatible with c37e (actually defined by
++ * the NV_DISP_NOTIFIER definition in clc37d.h).
++ */
++enum NvKmsNIsoFormat {
++ NVKMS_NISO_FORMAT_LEGACY,
++ NVKMS_NISO_FORMAT_FOUR_WORD,
++ NVKMS_NISO_FORMAT_FOUR_WORD_NVDISPLAY,
++};
++
++enum NvKmsEventType {
++ NVKMS_EVENT_TYPE_DPY_CHANGED,
++ NVKMS_EVENT_TYPE_DYNAMIC_DPY_CONNECTED,
++ NVKMS_EVENT_TYPE_DYNAMIC_DPY_DISCONNECTED,
++ NVKMS_EVENT_TYPE_DPY_ATTRIBUTE_CHANGED,
++ NVKMS_EVENT_TYPE_FRAMELOCK_ATTRIBUTE_CHANGED,
++ NVKMS_EVENT_TYPE_DISP_ATTRIBUTE_CHANGED,
++ NVKMS_EVENT_TYPE_FLIP_OCCURRED,
++};
++
++/*
++ * Base super sample (FOS) capabilities. Keep in this order (we rely on this
++ * when falling back)
++ */
++enum NvKmsSuperSample {
++ NVKMS_SUPER_SAMPLE_X1,
++ NVKMS_SUPER_SAMPLE_X4,
++ NVKMS_SUPER_SAMPLE_X8
++};
++
++struct NvKmsUsageBounds {
++ struct {
++ NvBool usable;
++ NvBool distRenderUsable;
++ NvU8 depth;
++ enum NvKmsSuperSample superSample;
++ } base;
++
++ struct {
++ NvBool usable;
++ NvU8 depth;
++ } overlay;
++};
++
++/*
++ * A 3x4 row-major colorspace conversion matrix.
++ *
++ * The output color C' is the CSC matrix M times the column vector
++ * [ R, G, B, 1 ].
++ *
++ * Each entry in the matrix is a signed 2's-complement fixed-point number with
++ * 3 integer bits and 16 fractional bits.
++ */
++struct NvKmsCscMatrix {
++ NvSFXP16_16 m[3][4];
++};
++
++#define NVKMS_IDENTITY_CSC_MATRIX \
++ (struct NvKmsCscMatrix){{ \
++ { 0x10000, 0, 0, 0 }, \
++ { 0, 0x10000, 0, 0 }, \
++ { 0, 0, 0x10000, 0 } \
++ }}
++
++#endif /* NVKMS_API_TYPES_H */
+diff -Naur a/kernel/nvkms-kapi.h b/kernel/nvkms-kapi.h
+--- a/kernel/nvkms-kapi.h 1970-01-01 01:00:00.000000000 +0100
++++ b/kernel/nvkms-kapi.h 2021-06-09 21:37:47.512578373 +0200
+@@ -0,0 +1,788 @@
++/* _NVRM_COPYRIGHT_BEGIN_
++ *
++ * Copyright 2015 by NVIDIA Corporation. All rights reserved. All
++ * information contained herein is proprietary and confidential to NVIDIA
++ * Corporation. Any use, reproduction, or disclosure without the written
++ * permission of NVIDIA Corporation is prohibited.
++ *
++ * _NVRM_COPYRIGHT_END_
++ */
++
++#if !defined(__NVKMS_KAPI_H__)
++
++#include "nvtypes.h"
++
++#include "nv-gpu-info.h"
++#include "nvkms-api-types.h"
++
++#define __NVKMS_KAPI_H__
++
++/*
++ * On Linux-x86, the kernel's function calling convention may pass
++ * parameters in registers. Force functions called to and from core
++ * NVKMS to pass parameters on the stack.
++ */
++#if NVCPU_IS_X86
++ #define NVKMS_KAPI_CALL __attribute__((regparm(0)))
++#else
++ #define NVKMS_KAPI_CALL
++#endif
++
++#define NVKMS_KAPI_MAX_HEADS 4
++
++#define NVKMS_KAPI_MAX_CONNECTORS 16
++#define NVKMS_KAPI_MAX_CLONE_DISPLAYS 16
++
++#define NVKMS_KAPI_EDID_BUFFER_SIZE 2048
++
++#define NVKMS_KAPI_MODE_NAME_LEN 32
++
++/**
++ * \defgroup Objects
++ * @{
++ */
++
++struct NvKmsKapiDevice;
++struct NvKmsKapiMemory;
++struct NvKmsKapiSurface;
++struct NvKmsKapiChannelEvent;
++
++typedef NvU32 NvKmsKapiConnector;
++typedef NvU32 NvKmsKapiDisplay;
++
++/** @} */
++
++/**
++ * \defgroup FuncPtrs
++ * @{
++ */
++
++typedef void NVKMS_KAPI_CALL NvKmsChannelEventProc(void *dataPtr, NvU32 dataU32);
++
++/** @} */
++
++/**
++ * \defgroup Structs
++ * @{
++ */
++
++struct NvKmsKapiDisplayModeTimings {
++
++ NvU32 refreshRate;
++ NvU32 pixelClockHz;
++ NvU32 hVisible;
++ NvU32 hSyncStart;
++ NvU32 hSyncEnd;
++ NvU32 hTotal;
++ NvU32 hSkew;
++ NvU32 vVisible;
++ NvU32 vSyncStart;
++ NvU32 vSyncEnd;
++ NvU32 vTotal;
++
++ struct {
++
++ NvU32 interlaced : 1;
++ NvU32 doubleScan : 1;
++ NvU32 hSyncPos : 1;
++ NvU32 hSyncNeg : 1;
++ NvU32 vSyncPos : 1;
++ NvU32 vSyncNeg : 1;
++
++ } flags;
++
++ NvU32 widthMM;
++ NvU32 heightMM;
++
++};
++
++struct NvKmsKapiDisplayMode {
++ struct NvKmsKapiDisplayModeTimings timings;
++ char name[NVKMS_KAPI_MODE_NAME_LEN];
++};
++
++struct NvKmsKapiDeviceResourcesInfo {
++
++ NvU32 numHeads;
++
++ NvU32 numConnectors;
++ NvKmsKapiConnector connectorHandles[NVKMS_KAPI_MAX_CONNECTORS];
++
++ struct {
++
++ NvU32 minWidthInPixels;
++ NvU32 maxWidthInPixels;
++
++ NvU32 minHeightInPixels;
++ NvU32 maxHeightInPixels;
++
++ NvU32 maxCursorSizeInPixels;
++
++ NvU32 pitchAlignment;
++
++ } caps;
++
++};
++
++typedef enum NvKmsKapiPlaneTypeRec {
++ NVKMS_KAPI_PLANE_PRIMARY = 0,
++ NVKMS_KAPI_PLANE_CURSOR = 1,
++ NVKMS_KAPI_PLANE_OVERLAY = 2,
++ NVKMS_KAPI_PLANE_MAX = 3,
++} NvKmsKapiPlaneType;
++
++#define NVKMS_KAPI_PLANE_MASK(planeType) (1 << (planeType))
++
++typedef enum NvKmsKapiMappingTypeRec {
++ NVKMS_KAPI_MAPPING_TYPE_USER = 1,
++ NVKMS_KAPI_MAPPING_TYPE_KERNEL = 2,
++} NvKmsKapiMappingType;
++
++struct NvKmsKapiConnectorInfo {
++
++ NvKmsKapiConnector handle;
++
++ NvU32 physicalIndex;
++
++ NvU32 headMask;
++
++ NvKmsConnectorSignalFormat signalFormat;
++ NvKmsConnectorType type;
++
++ /*
++ * List of connectors, not possible to serve together with this connector
++ * becase they are competing for same resources.
++ */
++ NvU32 numIncompatibleConnectors;
++ NvKmsKapiConnector incompatibleConnectorHandles[NVKMS_KAPI_MAX_CONNECTORS];
++
++};
++
++struct NvKmsKapiStaticDisplayInfo {
++
++ NvKmsKapiDisplay handle;
++
++ NvKmsKapiConnector connectorHandle;
++
++ /* Set for DisplayPort MST displays (dynamic displays) */
++ char dpAddress[NVKMS_DP_ADDRESS_STRING_LENGTH];
++
++ NvBool internal;
++
++ /* List of potential sibling display for cloning */
++ NvU32 numPossibleClones;
++ NvKmsKapiDisplay possibleCloneHandles[NVKMS_KAPI_MAX_CLONE_DISPLAYS];
++
++};
++
++struct NvKmsKapiPlaneConfig {
++ struct NvKmsKapiSurface *surface;
++
++ NvU16 srcX, srcY;
++ NvU16 srcWidth, srcHeight;
++
++ NvU16 dstX, dstY;
++ NvU16 dstWidth, dstHeight;
++};
++
++struct NvKmsKapiPlaneRequestedConfig {
++ struct NvKmsKapiPlaneConfig config;
++ struct {
++ NvBool surfaceChanged : 1;
++ NvBool srcXYChanged : 1;
++ NvBool srcWHChanged : 1;
++ NvBool dstXYChanged : 1;
++ NvBool dstWHChanged : 1;
++ } flags;
++};
++
++struct NvKmsKapiHeadModeSetConfig {
++ /*
++ * DRM distinguishes between the head state "enabled" (the specified
++ * configuration for the head is valid, its resources are allocated,
++ * etc, but the head may not necessarily be currently driving pixels
++ * to its output resource) and the head state "active" (the head is
++ * "enabled" _and_ the head is actively driving pixels to its output
++ * resource).
++ *
++ * This distinction is for DPMS:
++ *
++ * DPMS On : enabled=true, active=true
++ * DPMS Off : enabled=true, active=false
++ *
++ * "Enabled" state is indicated by numDisplays != 0.
++ * "Active" state is indicated by bActive == true.
++ */
++ NvBool bActive;
++
++ NvU32 numDisplays;
++ NvKmsKapiDisplay displays[NVKMS_KAPI_MAX_CLONE_DISPLAYS];
++
++ struct NvKmsKapiDisplayMode mode;
++};
++
++struct NvKmsKapiHeadRequestedConfig {
++ struct NvKmsKapiHeadModeSetConfig modeSetConfig;
++ struct {
++ NvBool activeChanged : 1;
++ NvBool displaysChanged : 1;
++ NvBool modeChanged : 1;
++ } flags;
++
++ struct NvKmsKapiPlaneRequestedConfig
++ planeRequestedConfig[NVKMS_KAPI_PLANE_MAX];
++};
++
++struct NvKmsKapiRequestedModeSetConfig {
++ NvU32 headsMask;
++ struct NvKmsKapiHeadRequestedConfig
++ headRequestedConfig[NVKMS_KAPI_MAX_HEADS];
++};
++
++struct NvKmsKapiEventDisplayChanged {
++ NvKmsKapiDisplay display;
++};
++
++struct NvKmsKapiEventDynamicDisplayConnected {
++ NvKmsKapiDisplay display;
++};
++
++struct NvKmsKapiEventFlipOccurred {
++ NvU32 head;
++ NvKmsKapiPlaneType plane;
++};
++
++struct NvKmsKapiEvent {
++ enum NvKmsEventType type;
++
++ struct NvKmsKapiDevice *device;
++
++ void *privateData;
++
++ union {
++ struct NvKmsKapiEventDisplayChanged displayChanged;
++ struct NvKmsKapiEventDynamicDisplayConnected dynamicDisplayConnected;
++ struct NvKmsKapiEventFlipOccurred flipOccurred;
++ } u;
++};
++
++struct NvKmsKapiAllocateDeviceParams {
++ /* [IN] GPU ID obtained from enumerateGpus() */
++ NvU32 gpuId;
++
++ /* [IN] Private data of device allocator */
++ void *privateData;
++ /* [IN] Event callback */
++ void (*eventCallback)(const struct NvKmsKapiEvent *event);
++};
++
++struct NvKmsKapiDynamicDisplayParams {
++ /* [IN] Display Handle returned by getDisplays() */
++ NvKmsKapiDisplay handle;
++
++ /* [OUT] Connection status */
++ NvU32 connected;
++
++ /* [IN/OUT] EDID of connected monitor/ Input to override EDID */
++ struct {
++ NvU16 bufferSize;
++ NvU8 buffer[NVKMS_KAPI_EDID_BUFFER_SIZE];
++ } edid;
++
++ /* [IN] Set true to override EDID */
++ NvBool overrideEdid;
++
++ /* [IN] Set true to force connected status */
++ NvBool forceConnected;
++
++ /* [IN] Set true to force disconnect status */
++ NvBool forceDisconnected;
++};
++
++struct NvKmsKapiFunctionsTable {
++
++ /*!
++ * NVIDIA Driver version string.
++ */
++ const char *versionString;
++
++ /*!
++ * System Information.
++ */
++ struct {
++ /* Availability of write combining support for video memory */
++ NvBool bAllowWriteCombining;
++ } systemInfo;
++
++ /*!
++ * Enumerate the available physical GPUs that can be used with NVKMS.
++ *
++ * \param [out] gpuInfo The information of the enumerated GPUs.
++ * It is an array of NVIDIA_MAX_GPUS elements.
++ *
++ * \return Count of enumerated gpus.
++ */
++ NvU32 NVKMS_KAPI_CALL (*enumerateGpus)(nv_gpu_info_t *gpuInfo);
++
++ /*!
++ * Allocate an NVK device using which you can query/allocate resources on
++ * GPU and do modeset.
++ *
++ * \param [in] params Parameters required for device allocation.
++ *
++ * \return An valid device handle on success, NULL on failure.
++ */
++ struct NvKmsKapiDevice* NVKMS_KAPI_CALL (*allocateDevice)
++ (
++ const struct NvKmsKapiAllocateDeviceParams *params
++ );
++
++ /*!
++ * Frees a device allocated by allocateDevice() and all its resources.
++ *
++ * \param [in] device A device returned by allocateDevice().
++ * This function is a no-op if device is not valid.
++ */
++ void NVKMS_KAPI_CALL (*freeDevice)(struct NvKmsKapiDevice *device);
++
++ /*!
++ * Grab ownership of device, ownership is required to do modeset.
++ *
++ * \param [in] device A device returned by allocateDevice().
++ *
++ * \return NV_TRUE on success, NV_FALSE on failure.
++ */
++ NvBool NVKMS_KAPI_CALL (*grabOwnership)(struct NvKmsKapiDevice *device);
++
++ /*!
++ * Release ownership of device.
++ *
++ * \param [in] device A device returned by allocateDevice().
++ */
++ void NVKMS_KAPI_CALL (*releaseOwnership)(struct NvKmsKapiDevice *device);
++
++ /*!
++ * Registers for notification, via
++ * NvKmsKapiAllocateDeviceParams::eventCallback, of the events specified
++ * in interestMask.
++ *
++ * This call does nothing if eventCallback is NULL when NvKmsKapiDevice
++ * is allocated.
++ *
++ * Supported events are DPY_CHANGED and DYNAMIC_DPY_CONNECTED.
++ *
++ * \param [in] device A device returned by allocateDevice().
++ *
++ * \param [in] interestMask A mask of events requested to listen.
++ *
++ * \return NV_TRUE on success, NV_FALSE on failure.
++ */
++ NvBool NVKMS_KAPI_CALL (*declareEventInterest)
++ (
++ const struct NvKmsKapiDevice *device,
++ const NvU32 interestMask
++ );
++
++ /*!
++ * Retrieve various static resources like connector, head etc. present on
++ * device and capacities.
++ *
++ * \param [in] device A device allocated using allocateDevice().
++ *
++ * \param [in/out] info A pointer to an NvKmsKapiDeviceResourcesInfo
++ * struct that the call will fill out with number
++ * of resources and their handles.
++ *
++ * \return NV_TRUE on success, NV_FALSE on failure.
++ */
++ NvBool NVKMS_KAPI_CALL (*getDeviceResourcesInfo)
++ (
++ struct NvKmsKapiDevice *device,
++ struct NvKmsKapiDeviceResourcesInfo *info
++ );
++
++ /*!
++ * Retrieve the number of displays on a device and an array of handles to
++ * those displays.
++ *
++ * \param [in] device A device allocated using
++ * allocateDevice().
++ *
++ * \param [in/out] displayCount The caller should set this to the size
++ * of the displayHandles array it passed
++ * in. The function will set it to the
++ * number of displays returned, or the
++ * total number of displays on the device
++ * if displayHandles is NULL or array size
++ * of less than number of number of displays.
++ *
++ * \param [out] displayHandles An array of display handles with
++ * displayCount entries.
++ *
++ * \return NV_TRUE on success, NV_FALSE on failure.
++ */
++ NvBool NVKMS_KAPI_CALL (*getDisplays)
++ (
++ struct NvKmsKapiDevice *device,
++ NvU32 *numDisplays, NvKmsKapiDisplay *displayHandles
++ );
++
++ /*!
++ * Retrieve information about a specified connector.
++ *
++ * \param [in] device A device allocated using allocateDevice().
++ *
++ * \param [in] connector Which connector to query, handle return by
++ * getDeviceResourcesInfo().
++ *
++ * \param [out] info A pointer to an NvKmsKapiConnectorInfo struct
++ * that the call will fill out with information
++ * about connector.
++ *
++ * \return NV_TRUE on success, NV_FALSE on failure.
++ */
++ NvBool NVKMS_KAPI_CALL (*getConnectorInfo)
++ (
++ struct NvKmsKapiDevice *device,
++ NvKmsKapiConnector connector, struct NvKmsKapiConnectorInfo *info
++ );
++
++ /*!
++ * Retrieve information about a specified display.
++ *
++ * \param [in] device A device allocated using allocateDevice().
++ *
++ * \param [in] display Which connector to query, handle return by
++ * getDisplays().
++ *
++ * \param [out] info A pointer to an NvKmsKapiStaticDisplayInfo struct
++ * that the call will fill out with information
++ * about display.
++ *
++ * \return NV_TRUE on success, NV_FALSE on failure.
++ */
++ NvBool NVKMS_KAPI_CALL (*getStaticDisplayInfo)
++ (
++ struct NvKmsKapiDevice *device,
++ NvKmsKapiDisplay display, struct NvKmsKapiStaticDisplayInfo *info
++ );
++
++ /*!
++ * Detect/force connection status/EDID of display.
++ *
++ * \param [in/out] params Parameters containing display
++ * handle, EDID and flags to force connection
++ * status.
++ *
++ * \return NV_TRUE on success, NV_FALSE on failure.
++ */
++ NvBool NVKMS_KAPI_CALL (*getDynamicDisplayInfo)
++ (
++ struct NvKmsKapiDevice *device,
++ struct NvKmsKapiDynamicDisplayParams *params
++ );
++
++ /*!
++ * Allocate some unformatted memory of the specified size.
++ *
++ * This function allocates displayable (Usually vidmem) memory on the
++ * specified GPU. It should be suitable for mapping on the CPU as a pitch
++ * linear surface.
++ *
++ * \param [in] device A device allocated using allocateDevice().
++ *
++ * \param [in] size Size, in bytes, of the memory to allocate.
++ *
++ * \return An valid memory handle on success, NULL on failure.
++ */
++ struct NvKmsKapiMemory* NVKMS_KAPI_CALL (*allocateMemory)
++ (
++ struct NvKmsKapiDevice *device, NvU64 size
++ );
++
++ /*!
++ * Import some unformatted memory of the specified size.
++ *
++ * This function accepts a driver-specific parameter structure representing
++ * memory allocated elsewhere and imports it to a NVKMS KAPI memory object
++ * of the specified size.
++ *
++ * \param [in] device A device allocated using allocateDevice(). The
++ * memory being imported must have been allocated
++ * against the same physical device this device object
++ * represents.
++ *
++ * \param [in] size Size, in bytes, of the memory being imported.
++ *
++ * \param [in] nvKmsParamsUser Userspace pointer to driver-specific
++ * parameters describing the memory object being
++ * imported.
++ *
++ * \param [in] nvKmsParamsSize Size of the driver-specific parameter struct.
++ *
++ * \return A valid memory handle on success, NULL on failure.
++ */
++ struct NvKmsKapiMemory* NVKMS_KAPI_CALL (*importMemory)
++ (
++ struct NvKmsKapiDevice *device, NvU64 size,
++ NvU64 nvKmsParamsUser,
++ NvU64 nvKmsParamsSize
++ );
++
++ /*!
++ * Free memory allocated using allocateMemory()
++ *
++ * \param [in] device A device allocated using allocateDevice().
++ *
++ * \param [in] memory Memory allocated using allocateMemory().
++ *
++ * \return NV_TRUE on success, NV_FALSE if memory is in use.
++ */
++ void NVKMS_KAPI_CALL (*freeMemory)
++ (
++ struct NvKmsKapiDevice *device, struct NvKmsKapiMemory *memory
++ );
++
++ /*!
++ * Create MMIO mappings for a memory object allocated using
++ * allocateMemory().
++ *
++ * \param [in] device A device allocated using allocateDevice().
++ *
++ * \param [in] memory Memory allocated using allocateMemory()
++ *
++ * \param [in] type Userspace or kernelspace mapping
++ *
++ * \param [out] ppLinearAddress The MMIO address where memory object is
++ * mapped.
++ *
++ * \return NV_TRUE on success, NV_FALSE on failure.
++ */
++ NvBool NVKMS_KAPI_CALL (*mapMemory)
++ (
++ const struct NvKmsKapiDevice *device,
++ const struct NvKmsKapiMemory *memory, NvKmsKapiMappingType type,
++ void **ppLinearAddress
++ );
++
++ /*!
++ * Destroy MMIO mappings created for a memory object allocated using
++ * allocateMemory().
++ *
++ * \param [in] device A device allocated using allocateDevice().
++ *
++ * \param [in] memory Memory allocated using allocateMemory()
++ *
++ * \param [in] type Userspace or kernelspace mapping
++ *
++ * \param [in] pLinearAddress The MMIO address return by mapMemory()
++ */
++ void NVKMS_KAPI_CALL (*unmapMemory)
++ (
++ const struct NvKmsKapiDevice *device,
++ const struct NvKmsKapiMemory *memory, NvKmsKapiMappingType type,
++ const void *pLinearAddress
++ );
++
++ /*!
++ * Create a formatted surface from an NvKmsKapiMemory object.
++ *
++ * \param [in] device A device allocated using allocateDevice().
++ *
++ * \param [in] memory Memory allocated using allocateMemory()
++ *
++ * \param [in] format The format used to interpret the memory contents of
++ * the surface being created.
++ *
++ * \param [in] width Width of the surface, in pixels.
++ *
++ * \param [in] height Height of the surface, in pixels.
++ *
++ * \param [in] pitch Byte pitch of the surface.
++ *
++ * \return An valid surface handle on success. NULL on failure.
++ */
++ struct NvKmsKapiSurface* NVKMS_KAPI_CALL (*createSurface)
++ (
++ struct NvKmsKapiDevice *device,
++ struct NvKmsKapiMemory *memory, enum NvKmsSurfaceMemoryFormat format,
++ NvU32 width, NvU32 height, NvU32 pitch
++ );
++
++ /*!
++ * Destroy a surface created by createSurface().
++ *
++ * \param [in] device A device allocated using allocateDevice().
++ *
++ * \param [in] surface A surface created using createSurface()
++ */
++ void NVKMS_KAPI_CALL (*destroySurface)
++ (
++ struct NvKmsKapiDevice *device, struct NvKmsKapiSurface *surface
++ );
++
++ /*!
++ * Enumerate the mode timings available on a given display.
++ *
++ * \param [in] device A device allocated using allocateDevice().
++ *
++ * \param [in] display A display handle returned by getDisplays().
++ *
++ * \param [in] modeIndex A mode index (Any integer >= 0).
++ *
++ * \param [out] mode A pointer to an NvKmsKapiDisplayMode struct that
++ * the call will fill out with mode-timings of mode
++ * at index modeIndex.
++ *
++ * \param [out] valid Returns TRUE in this param if mode-timings of
++ * mode at index modeIndex are valid on display.
++ *
++ * \return Value >= 1 if more modes are available, 0 if no more modes are
++ * available, and Value < 0 on failure.
++ */
++ int NVKMS_KAPI_CALL (*getDisplayMode)
++ (
++ struct NvKmsKapiDevice *device,
++ NvKmsKapiDisplay display, NvU32 modeIndex,
++ struct NvKmsKapiDisplayMode *mode, NvBool *valid
++ );
++
++ /*!
++ * Validate given mode timings available on a given display.
++ *
++ * \param [in] device A device allocated using allocateDevice().
++ *
++ * \param [in] display A display handle returned by getDisplays().
++ *
++ * \param [in] mode A pointer to an NvKmsKapiDisplayMode struct that
++ * filled with mode-timings to validate.
++ *
++ * \return NV_TRUE if mode-timings are valid, NV_FALSE on failure.
++ */
++ NvBool NVKMS_KAPI_CALL (*validateDisplayMode)
++ (
++ struct NvKmsKapiDevice *device,
++ NvKmsKapiDisplay display, const struct NvKmsKapiDisplayMode *mode
++ );
++
++ /*!
++ * Apply a mode configuration to the device.
++ *
++ * Client can describe damaged part of configuration but still it is must
++ * to describe entire configuration.
++ *
++ * \param [in] device A device allocated using allocateDevice().
++ *
++ * \param [in] requestedConfig Parameters describing a device-wide
++ * display configuration.
++ *
++ * \param [in] commit If set to 0 them call will only validate
++ * mode configuration, will not apply it.
++ *
++ * \return NV_TRUE on success, NV_FALSE on failure.
++ */
++ NvBool NVKMS_KAPI_CALL (*applyModeSetConfig)
++ (
++ struct NvKmsKapiDevice *device,
++ const struct NvKmsKapiRequestedModeSetConfig *requestedConfig,
++ const NvBool commit
++ );
++
++ /*!
++ * Return status of flip.
++ *
++ * \param [in] device A device allocated using allocateDevice().
++ *
++ * \param [in] head A head returned by getDeviceResourcesInfo().
++ *
++ * \param [in] plane A plane type.
++ *
++ * \param [out] pending Return TRUE if head has pending flip for
++ * given plane.
++ *
++ * \return NV_TRUE on success, NV_FALSE on failure.
++ */
++ NvBool NVKMS_KAPI_CALL (*getFlipPendingStatus)
++ (
++ const struct NvKmsKapiDevice *device,
++ const NvU32 head,
++ const NvKmsKapiPlaneType plane,
++ NvBool *pending
++ );
++
++ /*!
++ * Allocate an event callback.
++ *
++ * \param [in] device A device allocated using allocateDevice().
++ *
++ * \param [in] proc Function pointer to call when triggered.
++ *
++ * \param [in] data Argument to pass into function.
++ *
++ * \param [in] nvKmsParamsUser Userspace pointer to driver-specific
++ * parameters describing the event callback
++ * being created.
++ *
++ * \param [in] nvKmsParamsSize Size of the driver-specific parameter struct.
++ *
++ * \return struct NvKmsKapiChannelEvent* on success, NULL on failure.
++ */
++ struct NvKmsKapiChannelEvent* NVKMS_KAPI_CALL (*allocateChannelEvent)
++ (
++ struct NvKmsKapiDevice *device,
++ NvKmsChannelEventProc *proc,
++ void *data,
++ NvU64 nvKmsParamsUser,
++ NvU64 nvKmsParamsSize
++ );
++
++ /*!
++ * Free an event callback.
++ *
++ * \param [in] device A device allocated using allocateDevice().
++ *
++ * \param [in] cb struct NvKmsKapiChannelEvent* returned from
++ * allocateChannelEvent()
++ */
++ void NVKMS_KAPI_CALL (*freeChannelEvent)
++ (
++ struct NvKmsKapiDevice *device,
++ struct NvKmsKapiChannelEvent *cb
++ );
++
++ /*!
++ * Get 32-bit CRC value for the last contents presented on the specified
++ * head.
++ *
++ * \param [in] device A device allocated using allocateDevice().
++ *
++ * \param [in] head A head returned by getDeviceResourcesInfo().
++ *
++ * \param [out] crc32 The CRC32 generated from the content currently
++ * presented onto the given head
++ *
++ * \return NV_TRUE on success, NV_FALSE on failure.
++ */
++ NvBool NVKMS_KAPI_CALL (*getCRC32)
++ (
++ struct NvKmsKapiDevice *device,
++ NvU32 head,
++ NvU32 *crc32
++ );
++};
++
++/** @} */
++
++/**
++ * \defgroup Functions
++ * @{
++ */
++
++NvBool NVKMS_KAPI_CALL nvKmsKapiGetFunctionsTable
++(
++ struct NvKmsKapiFunctionsTable *funcsTable
++);
++
++/** @} */
++
++#endif /* defined(__NVKMS_KAPI_H__) */
+diff -Naur a/kernel/nv-mm.h b/kernel/nv-mm.h
+--- a/kernel/nv-mm.h 1970-01-01 01:00:00.000000000 +0100
++++ b/kernel/nv-mm.h 2021-06-09 21:37:47.510578416 +0200
+@@ -0,0 +1,285 @@
++/*******************************************************************************
++ Copyright (c) 2016-2017 NVIDIA Corporation
++
++ Permission is hereby granted, free of charge, to any person obtaining a copy
++ of this software and associated documentation files (the "Software"), to
++ deal in the Software without restriction, including without limitation the
++ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
++ sell copies of the Software, and to permit persons to whom the Software is
++ furnished to do so, subject to the following conditions:
++
++ The above copyright notice and this permission notice shall be
++ included in all copies or substantial portions of the Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR
++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ DEALINGS IN THE SOFTWARE.
++
++*******************************************************************************/
++#ifndef __NV_MM_H__
++#define __NV_MM_H__
++
++#include "conftest.h"
++
++#if !defined(NV_VM_FAULT_T_IS_PRESENT)
++typedef int vm_fault_t;
++#endif
++
++/* get_user_pages
++ *
++ * The 8-argument version of get_user_pages was deprecated by commit
++ * (2016 Feb 12: cde70140fed8429acf7a14e2e2cbd3e329036653)for the non-remote case
++ * (calling get_user_pages with current and current->mm).
++ *
++ * Completely moved to the 6 argument version of get_user_pages -
++ * 2016 Apr 4: c12d2da56d0e07d230968ee2305aaa86b93a6832
++ *
++ * write and force parameters were replaced with gup_flags by -
++ * 2016 Oct 12: 768ae309a96103ed02eb1e111e838c87854d8b51
++ *
++ * A 7-argument version of get_user_pages was introduced into linux-4.4.y by
++ * commit 8e50b8b07f462ab4b91bc1491b1c91bd75e4ad40 which cherry-picked the
++ * replacement of the write and force parameters with gup_flags
++ *
++ */
++
++#if defined(NV_GET_USER_PAGES_HAS_TASK_STRUCT)
++ #if defined(NV_GET_USER_PAGES_HAS_WRITE_AND_FORCE_ARGS)
++ #define NV_GET_USER_PAGES(start, nr_pages, write, force, pages, vmas) \
++ get_user_pages(current, current->mm, start, nr_pages, write, force,
pages, vmas)
++ #else
++ #include <linux/mm.h>
++ #include <linux/sched.h>
++
++ static inline long NV_GET_USER_PAGES(unsigned long start,
++ unsigned long nr_pages,
++ int write,
++ int force,
++ struct page **pages,
++ struct vm_area_struct **vmas)
++ {
++ unsigned int flags = 0;
++
++ if (write)
++ flags |= FOLL_WRITE;
++ if (force)
++ flags |= FOLL_FORCE;
++
++ return get_user_pages(current, current->mm, start, nr_pages, flags,
++ pages, vmas);
++ }
++ #endif
++#else
++ #if defined(NV_GET_USER_PAGES_HAS_WRITE_AND_FORCE_ARGS)
++ #define NV_GET_USER_PAGES get_user_pages
++ #else
++ #include <linux/mm.h>
++
++ static inline long NV_GET_USER_PAGES(unsigned long start,
++ unsigned long nr_pages,
++ int write,
++ int force,
++ struct page **pages,
++ struct vm_area_struct **vmas)
++ {
++ unsigned int flags = 0;
++
++ if (write)
++ flags |= FOLL_WRITE;
++ if (force)
++ flags |= FOLL_FORCE;
++
++ return get_user_pages(start, nr_pages, flags, pages, vmas);
++ }
++ #endif
++#endif
++
++/*
++ * get_user_pages_remote() was added by commit 1e9877902dc7
++ * ("mm/gup: Introduce get_user_pages_remote()") in v4.6 (2016-02-12).
++ *
++ * The very next commit cde70140fed8 ("mm/gup: Overload get_user_pages()
++ * functions") deprecated the 8-argument version of get_user_pages for the
++ * non-remote case (calling get_user_pages with current and current->mm).
++ *
++ * The guidelines are: call NV_GET_USER_PAGES_REMOTE if you need the 8-argument
++ * version that uses something other than current and current->mm. Use
++ * NV_GET_USER_PAGES if you are refering to current and current->mm.
++ *
++ * Note that get_user_pages_remote() requires the caller to hold a reference on
++ * the task_struct (if non-NULL and if this API has tsk argument) and the mm_struct.
++ * This will always be true when using current and current->mm. If the kernel passes
++ * the driver a vma via driver callback, the kernel holds a reference on vma->vm_mm
++ * over that callback.
++ *
++ * get_user_pages_remote() write/force parameters were replaced
++ * with gup_flags by commit 9beae1ea8930 ("mm: replace get_user_pages_remote()
++ * write/force parameters with gup_flags") in v4.9 (2016-10-13).
++ *
++ * get_user_pages_remote() added 'locked' parameter by commit 5b56d49fc31d
++ * ("mm: add locked parameter to get_user_pages_remote()") in
++ * v4.10 (2016-12-14).
++ *
++ * get_user_pages_remote() removed 'tsk' parameter by
++ * commit 64019a2e467a ("mm/gup: remove task_struct pointer for
++ * all gup code") in v5.9-rc1 (2020-08-11).
++ *
++ */
++
++#if defined(NV_GET_USER_PAGES_REMOTE_PRESENT)
++ #if defined(NV_GET_USER_PAGES_REMOTE_HAS_WRITE_AND_FORCE_ARGS)
++ #define NV_GET_USER_PAGES_REMOTE get_user_pages_remote
++ #else
++ static inline long NV_GET_USER_PAGES_REMOTE(struct task_struct *tsk,
++ struct mm_struct *mm,
++ unsigned long start,
++ unsigned long nr_pages,
++ int write,
++ int force,
++ struct page **pages,
++ struct vm_area_struct **vmas)
++ {
++ unsigned int flags = 0;
++
++ if (write)
++ flags |= FOLL_WRITE;
++ if (force)
++ flags |= FOLL_FORCE;
++
++ #if defined(NV_GET_USER_PAGES_REMOTE_HAS_LOCKED_ARG)
++ #if defined (NV_GET_USER_PAGES_REMOTE_HAS_TSK_ARG)
++ return get_user_pages_remote(tsk, mm, start, nr_pages, flags,
++ pages, vmas, NULL);
++ #else
++ return get_user_pages_remote(mm, start, nr_pages, flags,
++ pages, vmas, NULL);
++ #endif
++
++ #else
++
++ return get_user_pages_remote(tsk, mm, start, nr_pages, flags,
++ pages, vmas);
++
++ #endif
++
++ }
++ #endif
++#else
++ #if defined(NV_GET_USER_PAGES_HAS_WRITE_AND_FORCE_ARGS)
++ #define NV_GET_USER_PAGES_REMOTE NV_GET_USER_PAGES
++ #else
++ #include <linux/mm.h>
++ #include <linux/sched.h>
++
++ static inline long NV_GET_USER_PAGES_REMOTE(struct task_struct *tsk,
++ struct mm_struct *mm,
++ unsigned long start,
++ unsigned long nr_pages,
++ int write,
++ int force,
++ struct page **pages,
++ struct vm_area_struct **vmas)
++ {
++ unsigned int flags = 0;
++
++ if (write)
++ flags |= FOLL_WRITE;
++ if (force)
++ flags |= FOLL_FORCE;
++
++ return get_user_pages(tsk, mm, start, nr_pages, flags, pages, vmas);
++ }
++ #endif
++#endif
++
++
++/*
++ * The .virtual_address field was effectively renamed to .address, by these
++ * two commits:
++ *
++ * struct vm_fault: .address was added by:
++ * 2016-12-14 82b0f8c39a3869b6fd2a10e180a862248736ec6f
++ *
++ * struct vm_fault: .virtual_address was removed by:
++ * 2016-12-14 1a29d85eb0f19b7d8271923d8917d7b4f5540b3e
++ *
++ * The containing struct vm_fault was originally called fault_data. It was
++ * renamed to vm_fault by this commit:
++ * 2007-07-19 d0217ac04ca6591841e5665f518e38064f4e65bd
++ *
++ * Only define nv_page_fault_va() on kernels that have struct vm_fault.
++ * nv_page_fault_va() is only needed on kernels that have struct vm_fault.
++ * (Also, none of our drivers attempt to use page faulting on kernels that
++ * are old enough to have struct fault_data.)
++ *
++ */
++#if defined(NV_VM_FAULT_PRESENT)
++ static inline unsigned long nv_page_fault_va(struct vm_fault *vmf)
++ {
++ #if defined(NV_VM_FAULT_HAS_ADDRESS)
++ return vmf->address;
++ #else
++ return (unsigned long)(vmf->virtual_address);
++ #endif
++ }
++#endif // NV_VM_FAULT_PRESENT
++
++static inline void nv_mmap_read_lock(struct mm_struct *mm)
++{
++#if defined(NV_MM_HAS_MMAP_LOCK)
++ mmap_read_lock(mm);
++#else
++ down_read(&mm->mmap_sem);
++#endif
++}
++
++static inline void nv_mmap_read_unlock(struct mm_struct *mm)
++{
++#if defined(NV_MM_HAS_MMAP_LOCK)
++ mmap_read_unlock(mm);
++#else
++ up_read(&mm->mmap_sem);
++#endif
++}
++
++static inline void nv_mmap_write_lock(struct mm_struct *mm)
++{
++#if defined(NV_MM_HAS_MMAP_LOCK)
++ mmap_write_lock(mm);
++#else
++ down_write(&mm->mmap_sem);
++#endif
++}
++
++static inline void nv_mmap_write_unlock(struct mm_struct *mm)
++{
++#if defined(NV_MM_HAS_MMAP_LOCK)
++ mmap_write_unlock(mm);
++#else
++ up_write(&mm->mmap_sem);
++#endif
++}
++
++static inline int nv_mm_rwsem_is_locked(struct mm_struct *mm)
++{
++#if defined(NV_MM_HAS_MMAP_LOCK)
++ return rwsem_is_locked(&mm->mmap_lock);
++#else
++ return rwsem_is_locked(&mm->mmap_sem);
++#endif
++}
++
++static inline struct rw_semaphore *nv_mmap_get_lock(struct mm_struct *mm)
++{
++#if defined(NV_MM_HAS_MMAP_LOCK)
++ return &mm->mmap_lock;
++#else
++ return &mm->mmap_sem;
++#endif
++}
++
++#endif // __NV_MM_H__
+diff -Naur a/kernel/conftest.Kbuild b/kernel/conftest.Kbuild
+--- a/kernel/conftest.Kbuild 1970-01-01 01:00:00.000000000 +0100
++++ b/kernel/conftest.Kbuild 2021-06-09 21:39:15.630612177 +0200
+@@ -0,0 +1,210 @@
++NV_CONFTEST_GENERIC_COMPILE_TESTS += drm_available
++NV_CONFTEST_GENERIC_COMPILE_TESTS += drm_atomic_available
++NV_CONFTEST_GENERIC_COMPILE_TESTS += dom0_kernel_present
++NV_CONFTEST_GENERIC_COMPILE_TESTS += nvmap_support
++
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += remap_pfn_range
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += vmap
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += set_pages_uc
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += set_memory_uc
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += set_memory_array_uc
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += change_page_attr
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += pci_get_class
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += pci_choose_state
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += vm_insert_page
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += acquire_console_sem
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += console_lock
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += kmem_cache_create
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += kmem_cache_create_usercopy
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += on_each_cpu
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += smp_call_function
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += acpi_evaluate_integer
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += ioremap_cache
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += ioremap_nocache
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += ioremap_wc
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += acpi_walk_namespace
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += pci_domain_nr
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += pci_dma_mapping_error
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += file_operations
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += proc_ops
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += sg_alloc_table
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += sg_init_table
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += pci_get_domain_bus_and_slot
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += get_num_physpages
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += proc_create_data
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += pde_data
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += proc_remove
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += pm_vt_switch_required
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += pci_save_state
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += drm_pci_set_busid
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += write_cr4
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += for_each_online_node
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += node_end_pfn
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += get_user_pages
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += get_user_pages_remote
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += register_cpu_notifier
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += cpuhp_setup_state
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += drm_get_pci_dev
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += drm_pci_init
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += drm_legacy_pci_init
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += timer_setup
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += do_gettimeofday
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += drm_gem_object_put_unlocked
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += efi_enabled
++
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += drm_gem_object_get
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += drm_atomic_state_ref_counting
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += drm_gem_object_lookup
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += drm_dev_put
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += drm_framebuffer_get
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += drm_connector_for_each_possible_encoder
++NV_CONFTEST_FUNCTION_COMPILE_TESTS += vga_tryget
++
++NV_CONFTEST_SYMBOL_COMPILE_TESTS += efi_enabled
++NV_CONFTEST_SYMBOL_COMPILE_TESTS += export_symbol_gpl_conftest
++
++NV_CONFTEST_TYPE_COMPILE_TESTS += i2c_adapter
++NV_CONFTEST_TYPE_COMPILE_TESTS += pm_message_t
++NV_CONFTEST_TYPE_COMPILE_TESTS += irq_handler_t
++NV_CONFTEST_TYPE_COMPILE_TESTS += acpi_device_ops
++NV_CONFTEST_TYPE_COMPILE_TESTS += acpi_op_remove
++NV_CONFTEST_TYPE_COMPILE_TESTS += acpi_device_id
++NV_CONFTEST_TYPE_COMPILE_TESTS += outer_flush_all
++NV_CONFTEST_TYPE_COMPILE_TESTS += proc_dir_entry
++NV_CONFTEST_TYPE_COMPILE_TESTS += scatterlist
++NV_CONFTEST_TYPE_COMPILE_TESTS += sg_table
++NV_CONFTEST_TYPE_COMPILE_TESTS += file_inode
++NV_CONFTEST_TYPE_COMPILE_TESTS += drm_bus_present
++NV_CONFTEST_TYPE_COMPILE_TESTS += drm_bus_has_bus_type
++NV_CONFTEST_TYPE_COMPILE_TESTS += drm_bus_has_get_irq
++NV_CONFTEST_TYPE_COMPILE_TESTS += drm_bus_has_get_name
++NV_CONFTEST_TYPE_COMPILE_TESTS += vm_fault_t
++NV_CONFTEST_TYPE_COMPILE_TESTS += vm_fault_present
++NV_CONFTEST_TYPE_COMPILE_TESTS += vm_fault_has_address
++NV_CONFTEST_TYPE_COMPILE_TESTS += drm_driver_unload_has_int_return_type
++NV_CONFTEST_TYPE_COMPILE_TESTS += drm_driver_legacy_feature_bit_present
++NV_CONFTEST_TYPE_COMPILE_TESTS += drm_driver_prime_flag_present
++
++NV_CONFTEST_TYPE_COMPILE_TESTS += mm_has_mmap_lock
++NV_CONFTEST_TYPE_COMPILE_TESTS += drm_gem_object_vmap_has_map_arg
++NV_CONFTEST_TYPE_COMPILE_TESTS += drm_mode_object_find_has_file_priv_arg
++NV_CONFTEST_TYPE_COMPILE_TESTS += drm_prime_pages_to_sg_has_drm_device_arg
++NV_CONFTEST_TYPE_COMPILE_TESTS += drm_gem_object_has_resv
++
++NV_CONFTEST_TYPE_COMPILE_TESTS += drm_gem_prime_export_has_dev_arg
++NV_CONFTEST_TYPE_COMPILE_TESTS += drm_driver_has_gem_prime_callbacks
++NV_CONFTEST_TYPE_COMPILE_TESTS += drm_driver_has_gem_free_object
++NV_CONFTEST_TYPE_COMPILE_TESTS += drm_driver_has_gem_prime_res_obj
++NV_CONFTEST_TYPE_COMPILE_TESTS += vmalloc_has_pgprot_t_arg
++
++NV_CONFTEST_MACRO_COMPILE_TESTS += INIT_WORK
++
++# The conftest.sh script tests various aspects of the target kernel.
++# The per-module Kbuild files included above should:
++#
++# - Append to the NV_CONFTEST_*_COMPILE_TESTS variables to indicate
++# which conftests they require.
++# - Append to the NV_OBJECTS_DEPEND_ON_CONFTEST variable any object files
++# that depend on conftest.
++#
++# The conftest machinery below will run the requested tests and
++# generate the appropriate header files.
++#
++
++CC ?= cc
++HOST_CC ?= $(CC)
++LD ?= ld
++
++NV_CONFTEST_SCRIPT := $(src)/conftest.sh
++NV_CONFTEST_HEADER := $(obj)/conftest/headers.h
++
++NV_CONFTEST_CMD := /bin/sh $(NV_CONFTEST_SCRIPT) \
++ "$(CC)" "$(HOST_CC)" $(ARCH) $(KERNEL_SOURCES) $(KERNEL_OUTPUT)
++
++NV_CONFTEST_CFLAGS := $(shell $(NV_CONFTEST_CMD) build_cflags)
++
++NV_CONFTEST_COMPILE_TEST_HEADERS := $(obj)/conftest/macros.h
++NV_CONFTEST_COMPILE_TEST_HEADERS += $(obj)/conftest/functions.h
++NV_CONFTEST_COMPILE_TEST_HEADERS += $(obj)/conftest/symbols.h
++NV_CONFTEST_COMPILE_TEST_HEADERS += $(obj)/conftest/types.h
++NV_CONFTEST_COMPILE_TEST_HEADERS += $(obj)/conftest/generic.h
++
++NV_CONFTEST_HEADERS := $(obj)/conftest/patches.h
++NV_CONFTEST_HEADERS += $(obj)/conftest/headers.h
++NV_CONFTEST_HEADERS += $(NV_CONFTEST_COMPILE_TEST_HEADERS)
++
++
++#
++# Generate a header file for a single conftest compile test. Each compile test
++# header depends on conftest.sh, as well as the generated conftest/headers.h
++# file, which is included in the compile test preamble.
++#
++
++$(obj)/conftest/compile-tests/%.h: $(NV_CONFTEST_SCRIPT) $(NV_CONFTEST_HEADER)
++ @mkdir -p $(obj)/conftest/compile-tests
++ @echo " CONFTEST: $(notdir $*)"
++ @$(NV_CONFTEST_CMD) compile_tests '$(NV_CONFTEST_CFLAGS)' \
++ $(notdir $*) > $@
++
++#
++# Concatenate a conftest/*.h header from its constituent compile test headers
++#
++# $(1): The name of the concatenated header
++# $(2): The list of compile tests that make up the header
++#
++
++define NV_GENERATE_COMPILE_TEST_HEADER
++ $(obj)/conftest/$(1).h: $(addprefix $(obj)/conftest/compile-tests/,$(addsuffix
.h,$(2)))
++ @mkdir -p $(obj)/conftest
++ @# concatenate /dev/null to prevent cat from hanging when $$^ is empty
++ @cat $$^ /dev/null > $$@
++endef
++
++#
++# Generate the conftest compile test headers from the lists of compile tests
++# provided by the module-specific Kbuild files.
++#
++NV_CONFTEST_FUNCTION_COMPILE_TESTS ?=
++NV_CONFTEST_GENERIC_COMPILE_TESTS ?=
++NV_CONFTEST_MACRO_COMPILE_TESTS ?=
++NV_CONFTEST_SYMBOL_COMPILE_TESTS ?=
++NV_CONFTEST_TYPE_COMPILE_TESTS ?=
++
++$(eval $(call
NV_GENERATE_COMPILE_TEST_HEADER,functions,$(NV_CONFTEST_FUNCTION_COMPILE_TESTS)))
++$(eval $(call
NV_GENERATE_COMPILE_TEST_HEADER,generic,$(NV_CONFTEST_GENERIC_COMPILE_TESTS)))
++$(eval $(call
NV_GENERATE_COMPILE_TEST_HEADER,macros,$(NV_CONFTEST_MACRO_COMPILE_TESTS)))
++$(eval $(call
NV_GENERATE_COMPILE_TEST_HEADER,symbols,$(NV_CONFTEST_SYMBOL_COMPILE_TESTS)))
++$(eval $(call NV_GENERATE_COMPILE_TEST_HEADER,types,$(NV_CONFTEST_TYPE_COMPILE_TESTS)))
++
++$(obj)/conftest/patches.h: $(NV_CONFTEST_SCRIPT)
++ @mkdir -p $(obj)/conftest
++ @$(NV_CONFTEST_CMD) patch_check > $@
++
++$(obj)/conftest/headers.h: $(NV_CONFTEST_SCRIPT)
++ @mkdir -p $(obj)/conftest
++ @$(NV_CONFTEST_CMD) test_kernel_headers > $@
++
++clean-dirs := $(obj)/conftest
++
++
++# For any object files that depend on conftest, declare the dependency here.
++$(addprefix $(obj)/,$(NV_OBJECTS_DEPEND_ON_CONFTEST)): | $(NV_CONFTEST_HEADERS)
++
++# Sanity checks of the build environment and target system/kernel
++
++BUILD_SANITY_CHECKS = \
++ cc_sanity_check \
++ cc_version_check \
++ dom0_sanity_check \
++ xen_sanity_check \
++ preempt_rt_sanity_check \
++ vgpu_kvm_sanity_check
++
++.PHONY: $(BUILD_SANITY_CHECKS)
++
++$(BUILD_SANITY_CHECKS):
++ @$(NV_CONFTEST_CMD) $@ full_output
++
++# Perform all sanity checks before generating the conftest headers
++
++$(NV_CONFTEST_HEADERS): | $(BUILD_SANITY_CHECKS)
+diff -Naur a/kernel/conftest.sh b/kernel/conftest.sh
+--- a/kernel/conftest.sh 2021-06-09 21:37:47.510578416 +0200
++++ b/kernel/conftest.sh 2021-06-11 10:09:39.116572777 +0200
+@@ -113,6 +113,7 @@
+ FILES="$FILES drm/drm_vblank.h"
+ FILES="$FILES drm/drm_file.h"
+ FILES="$FILES drm/drm_ioctl.h"
++ FILES="$FILES drm/drm_pci.h"
+ FILES="$FILES drm/drm_device.h"
+ FILES="$FILES generated/autoconf.h"
+ FILES="$FILES generated/compile.h"
+@@ -121,6 +122,7 @@
+ FILES="$FILES linux/kconfig.h"
+ FILES="$FILES linux/screen_info.h"
+ FILES="$FILES linux/semaphore.h"
++ FILES="$FILES linux/nvmap.h"
+ FILES="$FILES linux/printk.h"
+ FILES="$FILES linux/ratelimit.h"
+ FILES="$FILES linux/prio_tree.h"
+@@ -133,6 +135,7 @@
+ FILES="$FILES xen/ioemu.h"
+ FILES="$FILES linux/fence.h"
+ FILES="$FILES linux/ktime.h"
++ FILES="$FILES linux/file.h"
+ FILES="$FILES linux/dma-resv.h"
+ FILES="$FILES linux/dma-map-ops.h"
+
+@@ -142,6 +145,8 @@
+ FILES_ARCH="$FILES_ARCH asm/powernv.h"
+ FILES_ARCH="$FILES_ARCH asm/tlbflush.h"
+ FILES_ARCH="$FILES_ARCH asm/pgtable_types.h"
++ FILES_ARCH="$FILES_ARCH asm/kmap_types.h"
++ FILES_ARCH="$FILES_ARCH asm/pgtable.h"
+
+ translate_and_find_header_files $HEADERS $FILES
+ translate_and_find_header_files $HEADERS_ARCH $FILES_ARCH
+@@ -662,6 +667,63 @@
+ compile_check_conftest "$CODE" "NV_FOLLOW_PFN_PRESENT"
"" "functions"
+ ;;
+
++ vmap)
++ #
++ # Determine if the vmap() function is present and how
++ # many arguments it takes.
++ #
++ echo "$CONFTEST_PREAMBLE
++ #include <linux/vmalloc.h>
++ void conftest_vmap(void) {
++ vmap();
++ }" > conftest$$.c
++
++ $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
++ rm -f conftest$$.c
++
++ if [ -f conftest$$.o ]; then
++ echo "#undef NV_VMAP_PRESENT" | append_conftest
"functions"
++ rm -f conftest$$.o
++ return
++ fi
++
++ echo "$CONFTEST_PREAMBLE
++ #include <linux/vmalloc.h>
++ void *conftest_vmap(struct page **pages, int count) {
++ return vmap(pages, count);
++ }" > conftest$$.c
++
++ $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
++ rm -f conftest$$.c
++
++ if [ -f conftest$$.o ]; then
++ echo "#define NV_VMAP_PRESENT" | append_conftest
"functions"
++ echo "#define NV_VMAP_ARGUMENT_COUNT 2" | append_conftest
"functions"
++ rm -f conftest$$.o
++ return
++ fi
++
++ echo "$CONFTEST_PREAMBLE
++ #include <linux/vmalloc.h>
++ #include <linux/mm.h>
++ void *conftest_vmap(struct page **pages, int count) {
++ return vmap(pages, count, 0, PAGE_KERNEL);
++ }" > conftest$$.c
++
++ $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
++ rm -f conftest$$.c
++
++ if [ -f conftest$$.o ]; then
++ echo "#define NV_VMAP_PRESENT" | append_conftest
"functions"
++ echo "#define NV_VMAP_ARGUMENT_COUNT 4" | append_conftest
"functions"
++ rm -f conftest$$.o
++ return
++ else
++ echo "#error vmap() conftest failed!" | append_conftest
"functions"
++ return
++ fi
++ ;;
++
+ i2c_adapter)
+ #
+ # Determine if the 'i2c_adapter' structure has the
+@@ -1110,6 +1172,16 @@
+ compile_check_conftest "$CODE"
"NV_CPUHP_SETUP_STATE_PRESENT" "" "functions"
+ ;;
+
++ nvmap_support)
++ # check if nvmap is supported.
++ if [ -f nv-android.h ]; then
++ echo "#define HAVE_NV_ANDROID" | append_conftest
"generic"
++ return
++ else
++ echo "#undef HAVE_NV_ANDROID" | append_conftest
"generic"
++ fi
++ ;;
++
+ acpi_evaluate_integer)
+ #
+ # Determine if the acpi_evaluate_integer() function is
+@@ -1425,6 +1497,47 @@
+ compile_check_conftest "$CODE"
"NV_FILE_OPERATIONS_HAS_COMPAT_IOCTL" "" "types"
+ ;;
+
++ sg_init_table)
++ #
++ # Determine if the sg_init_table() function is present.
++ #
++ echo "$CONFTEST_PREAMBLE
++ #include <linux/scatterlist.h>
++ void conftest_sg_init_table(struct scatterlist *sgl,
++ unsigned int nents) {
++ }" > conftest$$.c
++
++ $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
++ rm -f conftest$$.c
++
++ if [ ! -f conftest$$.o ]; then
++ echo "#undef NV_SG_INIT_TABLE_PRESENT" | append_conftest
"functions"
++ return
++
++ fi
++ rm -f conftest$$.o
++
++ echo "$CONFTEST_PREAMBLE
++ #include <linux/types.h>
++ #include <linux/scatterlist.h>
++ void conftest_sg_init_table(struct scatterlist *sgl,
++ unsigned int nents) {
++ sg_init_table();
++ }" > conftest$$.c
++
++ $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
++ rm -f conftest$$.c
++
++ if [ -f conftest$$.o ]; then
++ echo "#undef NV_SG_INIT_TABLE_PRESENT" | append_conftest
"functions"
++ rm -f conftest$$.o
++ return
++ else
++ echo "#define NV_SG_INIT_TABLE_PRESENT" | append_conftest
"functions"
++ return
++ fi
++ ;;
++
+ sg_table)
+ #
+ # Determine if the struct sg_table type is present.
+@@ -2033,6 +2146,21 @@
+ compile_check_conftest "$CODE" "NV_FILE_HAS_INODE"
"" "types"
+ ;;
+
++ drm_pci_set_busid)
++ #
++ # Determine if the drm_pci_set_busid function is present.
++ #
++ CODE="
++ #if defined(NV_DRM_DRMP_H_PRESENT)
++ #include <drm/drmP.h>
++ #endif
++ void conftest_drm_pci_set_busid(void) {
++ drm_pci_set_busid();
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_PCI_SET_BUSID_PRESENT" "" "functions"
++ ;;
++
+ xen_ioemu_inject_msi)
+ #
+ # Determine if the xen_ioemu_inject_msi() function is present.
+@@ -2049,7 +2177,7 @@
+ }"
+
+ compile_check_conftest "$CODE" "NV_XEN_IOEMU_INJECT_MSI"
"" "functions"
+- ;;
++ ;;
+
+ phys_to_dma)
+ #
+@@ -3410,6 +3538,64 @@
+ compile_check_conftest "$CODE"
"NV_DRM_DRIVER_UNLOAD_HAS_INT_RETURN_TYPE" "" "types"
+ ;;
+
++ drm_get_pci_dev)
++ #
++ # Determine if drm_get_pci_dev() is present.
++ #
++ CODE="
++ #if defined(NV_DRM_DRMP_H_PRESENT)
++ #include <drm/drmP.h>
++ #endif
++
++ #if defined(NV_DRM_DRM_PCI_H_PRESENT)
++ #include <drm/drm_pci.h>
++ #endif
++
++ void conftest_drm_legacy_pci_init(void) {
++ drm_get_pci_dev();
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_GET_PCI_DEV_PRESENT" "" "functions"
++ ;;
++
++ drm_pci_init)
++ #
++ # Determine if drm_pci_init() is present.
++ #
++ CODE="
++ #if defined(NV_DRM_DRMP_H_PRESENT)
++ #include <drm/drmP.h>
++ #endif
++
++ void conftest_drm_legacy_pci_init(void) {
++ drm_pci_init();
++ }"
++
++ compile_check_conftest "$CODE" "NV_DRM_PCI_INIT_PRESENT"
"" "functions"
++ ;;
++
++ drm_legacy_pci_init)
++ #
++ # Determine if drm_legacy_pci_init() is present. drm_pci_init() was
++ # deprecated and renamed to drm_legacy_pci_init by:
++ #
++ # 2017-05-24 10631d724deff712343d96dd3017cd323349f761
++ #
++ CODE="
++ #if defined(NV_DRM_DRMP_H_PRESENT)
++ #include <drm/drmP.h>
++ #endif
++
++ #if defined(NV_DRM_DRM_PCI_H_PRESENT)
++ #include <drm/drm_pci.h>
++ #endif
++ void conftest_drm_legacy_pci_init(void) {
++ drm_legacy_pci_init();
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_LEGACY_PCI_INIT_PRESENT" "" "functions"
++ ;;
++
+ kref_has_refcount_of_type_refcount_t)
+ CODE="
+ #include <linux/kref.h>
+@@ -3962,6 +4148,30 @@
+ compile_check_conftest "$CODE"
"NV_DMA_IS_DIRECT_PRESENT" "" "functions"
+ ;;
+
++ drm_driver_legacy_feature_bit_present)
++ #
++ # Determine if the DRIVER_LEGACY feature bit is present, either as a
++ # preprocessor macro or in an enum.
++ #
++ # The DRIVER_* feature bits were changed from CPP macros to an enum
++ # with commit 0e2a933b02c972919f7478364177eb76cd4ae00d (2019-01-29).
++ #
++ CODE="
++ #if defined(NV_DRM_DRMP_H_PRESENT)
++ #include <drm/drmP.h>
++ #endif
++
++ #if defined(NV_DRM_DRM_DRV_H_PRESENT)
++ #include <drm/drm_drv.h>
++ #endif
++
++ void conftest_drm_driver_legacy_feature_bit_present(struct drm_driver *drv)
{
++ drv->driver_features = DRIVER_LEGACY;
++ }"
++
++ compile_check_conftest "$CODE"
"NV_DRM_DRIVER_LEGACY_FEATURE_BIT_PRESENT" "" "types"
++ ;;
++
+ drm_driver_prime_flag_present)
+ #
+ # Determine whether driver feature flag DRIVER_PRIME is present.
+@@ -4094,6 +4304,11 @@
+ "
+
+ compile_check_conftest "$CODE" "NV_PROC_OPS_PRESENT"
"" "types"
++ if [ -f conftest$$.o ]; then
++ echo "#undef NV_HAVE_PROC_OPS" | append_conftest
"types"
++ else
++ echo "#define NV_HAVE_PROC_OPS" | append_conftest
"types"
++ fi
+ ;;
+
+ timeval)
+diff -Naur a/kernel/Makefile b/kernel/Makefile
+--- a/kernel/Makefile 2021-06-09 21:37:47.472579245 +0200
++++ b/kernel/Makefile 2021-06-09 21:39:15.629612199 +0200
+@@ -70,11 +70,11 @@
+ MODULE_GLUE_OBJS := $(patsubst %.c,%.o,nv-frontend.c)
+ $(MODULE_NAME)-objs := $(MODULE_GLUE_OBJS)
+ else
+- MODULE_GLUE_OBJS := $(patsubst %.c,%.o, nv.c nv-acpi.c nv-chrdev.c nv-cray.c nv-dma.c
nv-drm.c nv-gvi.c nv-i2c.c nv-mempool.c nv-mmap.c nv-p2p.c nv-pat.c nv-procfs.c
nv-usermap.c nv-vm.c nv-vtophys.c os-interface.c os-mlock.c os-pci.c os-registry.c
os-smp.c os-usermap.c nv_uvm_interface.c)
++ MODULE_GLUE_OBJS := $(patsubst %.c,%.o, nv.c nv-acpi.c nv-chrdev.c nv-cray.c nv-dma.c
nv-drm.c nv-gvi.c nv-i2c.c nv-mempool.c nv-mmap.c nv-p2p.c nv-pat.c nv-procfs.c
nv-usermap.c nv-vm.c nv-vtophys.c os-interface.c os-mlock.c os-pci.c os-registry.c
os-smp.c os-usermap.c nv_uvm_interface.c nvidia-drm-linux.c nvidia-drm-gem.c
nvidia-drm-helper.c nvidia-drm-gem-user-memory.c)
+ $(MODULE_NAME)-objs := $(CORE_OBJS) $(MODULE_GLUE_OBJS)
+ endif
+ else
+- MODULE_GLUE_OBJS := $(patsubst %.c,%.o, nv.c nv-acpi.c nv-chrdev.c nv-cray.c nv-dma.c
nv-drm.c nv-gvi.c nv-i2c.c nv-mempool.c nv-mmap.c nv-p2p.c nv-pat.c nv-procfs.c
nv-usermap.c nv-vm.c nv-vtophys.c os-interface.c os-mlock.c os-pci.c os-registry.c
os-smp.c os-usermap.c nv_uvm_interface.c) $(patsubst %.c,%.o,nv-frontend.c)
++ MODULE_GLUE_OBJS := $(patsubst %.c,%.o, nv.c nv-acpi.c nv-chrdev.c nv-cray.c nv-dma.c
nv-drm.c nv-gvi.c nv-i2c.c nv-mempool.c nv-mmap.c nv-p2p.c nv-pat.c nv-procfs.c
nv-usermap.c nv-vm.c nv-vtophys.c os-interface.c os-mlock.c os-pci.c os-registry.c
os-smp.c os-usermap.c nv_uvm_interface.c nvidia-drm-linux.c nvidia-drm-gem.c
nvidia-drm-helper.c nvidia-drm-gem-user-memory.c) $(patsubst %.c,%.o,nv-frontend.c)
+ $(MODULE_NAME)-objs := $(CORE_OBJS) $(MODULE_GLUE_OBJS)
+ endif
+
+@@ -183,6 +183,7 @@
+
+ src ?= .
+ include $(src)/nvidia-modules-common.mk
++include $(src)/conftest.Kbuild
+
+ #
+ # Generate multiple targets at runtime depending on the items present in
+diff -Naur a/kernel/nv.c b/kernel/nv.c
+--- a/kernel/nv.c 2021-06-09 21:37:47.478579114 +0200
++++ b/kernel/nv.c 2021-06-09 21:39:15.633612109 +0200
+@@ -2785,10 +2785,10 @@
+
+ #if defined(CONFIG_VGA_ARB)
+ #if defined(VGA_DEFAULT_DEVICE)
+-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
+- vga_get(VGA_DEFAULT_DEVICE, VGA_RSRC_LEGACY_MASK, 0);
+-#else
++#if defined(NV_VGA_TRYGET_PRESENT)
+ vga_tryget(VGA_DEFAULT_DEVICE, VGA_RSRC_LEGACY_MASK);
++#else
++ vga_get(VGA_DEFAULT_DEVICE, VGA_RSRC_LEGACY_MASK, 0);
+ #endif
+ #endif
+ vga_set_legacy_decoding(dev, VGA_RSRC_NONE);
+diff -Naur a/kernel/nv-drm.c b/kernel/nv-drm.c
+--- a/kernel/nv-drm.c 2021-06-09 21:37:47.474579202 +0200
++++ b/kernel/nv-drm.c 2021-06-09 22:13:02.593929252 +0200
+@@ -24,6 +24,11 @@
+ #include <linux/file.h>
+ #endif
+
++#include <nvidia-drm-priv.h>
++#include <nvidia-drm-ioctl.h>
++#include <nvidia-drm-gem-user-memory.h>
++#include <nvidia-drm-helper.h>
++
+ #if defined(NV_DRM_DRM_DRV_H_PRESENT)
+ #include <drm/drm_drv.h>
+ #endif
+@@ -51,237 +56,12 @@
+ #if defined(NV_DRM_LEGACY_PCI_INIT_PRESENT)
+ #define nv_drm_pci_init drm_legacy_pci_init
+ #define nv_drm_pci_exit drm_legacy_pci_exit
+-#elif defined(NV_DRM_PCI_INIT_PRESENT)
++#else
+ #define nv_drm_pci_init drm_pci_init
+ #define nv_drm_pci_exit drm_pci_exit
+-#else
+-#if defined(NV_DRM_GET_PCI_DEV_PRESENT)
+-#define nv_drm_get_pci_dev drm_get_pci_dev
+-#else
+-#include <drm/drm_agpsupport.h>
+-
+-struct nv_drm_agp_head {
+- struct agp_kern_info agp_info;
+- struct list_head memory;
+- unsigned long mode;
+- struct agp_bridge_data *bridge;
+- int enabled;
+- int acquired;
+- unsigned long base;
+- int agp_mtrr;
+- int cant_use_aperture;
+- unsigned long page_mask;
+-};
+-
+-struct nv_drm_agp_mem {
+- unsigned long handle;
+- struct agp_memory *memory;
+- unsigned long bound;
+- int pages;
+- struct list_head head;
+-};
+-
+-/*
+- * Code from drm_agp_init/nv_drm_{free,unbind}_agp
+- * Extracted from commit: 5b8b9d0c6d0e0f1993c6c56deaf9646942c49d94, file:
drivers/gpu/drm/drm_agpsupport.c
+- */
+-struct drm_agp_head *nv_drm_agp_init(struct drm_device *dev)
+-{
+- struct nv_drm_agp_head *head = NULL;
+-
+- head = kzalloc(sizeof(*head), GFP_KERNEL);
+- if (!head)
+- return NULL;
+- head->bridge = agp_find_bridge(dev->pdev);
+- if (!head->bridge) {
+- head->bridge = agp_backend_acquire(dev->pdev);
+- if (!head->bridge) {
+- kfree(head);
+- return NULL;
+- }
+- agp_copy_info(head->bridge, &head->agp_info);
+- agp_backend_release(head->bridge);
+- } else {
+- agp_copy_info(head->bridge, &head->agp_info);
+- }
+- if (head->agp_info.chipset == NOT_SUPPORTED) {
+- kfree(head);
+- return NULL;
+- }
+- INIT_LIST_HEAD(&head->memory);
+- head->cant_use_aperture = head->agp_info.cant_use_aperture;
+- head->page_mask = head->agp_info.page_mask;
+- head->base = head->agp_info.aper_base;
+- return (struct drm_agp_head *)head;
+-}
+-
+-void nv_drm_free_agp(struct agp_memory *handle, int pages)
+-{
+- agp_free_memory(handle);
+-}
+-
+-int nv_drm_unbind_agp(struct agp_memory *handle)
+-{
+- return agp_unbind_memory(handle);
+-}
+-
+-/*
+- * Code from drm_pci_agp_{clear,destroy,init}/drm_get_pci_dev
+- * Extracted from commit: 5b8b9d0c6d0e0f1993c6c56deaf9646942c49d94, file:
drivers/gpu/drm/drm_pci.c
+- */
+-static void nv_drm_pci_agp_init(struct drm_device *dev)
+-{
+- if (drm_core_check_feature(dev, DRIVER_USE_AGP)) {
+- if (pci_find_capability(dev->pdev, PCI_CAP_ID_AGP))
+- dev->agp = nv_drm_agp_init(dev);
+- if (dev->agp) {
+- dev->agp->agp_mtrr = arch_phys_wc_add(
+- dev->agp->agp_info.aper_base,
+- dev->agp->agp_info.aper_size *
+- 1024 * 1024);
+- }
+- }
+-}
+-
+-void nv_drm_legacy_agp_clear(struct drm_device *dev)
+-{
+- struct nv_drm_agp_mem *entry, *tempe;
+-
+- if (!dev->agp)
+- return;
+- if (!drm_core_check_feature(dev, DRIVER_LEGACY))
+- return;
+-
+- list_for_each_entry_safe(entry, tempe, &dev->agp->memory, head) {
+- if (entry->bound)
+- nv_drm_unbind_agp(entry->memory);
+- nv_drm_free_agp(entry->memory, entry->pages);
+- kfree(entry);
+- }
+- INIT_LIST_HEAD(&dev->agp->memory);
+-
+- if (dev->agp->acquired)
+- drm_agp_release(dev);
+-
+- dev->agp->acquired = 0;
+- dev->agp->enabled = 0;
+-}
+-
+-void nv_drm_pci_agp_destroy(struct drm_device *dev)
+-{
+- if (dev->agp) {
+- arch_phys_wc_del(dev->agp->agp_mtrr);
+- nv_drm_legacy_agp_clear(dev);
+- kfree(dev->agp);
+- dev->agp = NULL;
+- }
+-}
+-
+-static int nv_drm_get_pci_dev(struct pci_dev *pdev,
+- const struct pci_device_id *ent,
+- struct drm_driver *driver)
+-{
+- struct drm_device *dev;
+- int ret;
+-
+- DRM_DEBUG("\n");
+-
+- dev = drm_dev_alloc(driver, &pdev->dev);
+- if (IS_ERR(dev))
+- return PTR_ERR(dev);
+-
+- ret = pci_enable_device(pdev);
+- if (ret)
+- goto err_free;
+-
+- dev->pdev = pdev;
+-#ifdef __alpha__
+- dev->hose = pdev->sysdata;
+-#endif
+-
+- if (drm_core_check_feature(dev, DRIVER_MODESET))
+- pci_set_drvdata(pdev, dev);
+-
+- nv_drm_pci_agp_init(dev);
+-
+- ret = drm_dev_register(dev, ent->driver_data);
+- if (ret)
+- goto err_agp;
+-
+- /* No locking needed since shadow-attach is single-threaded since it may
+- * only be called from the per-driver module init hook. */
+- if (drm_core_check_feature(dev, DRIVER_LEGACY))
+- list_add_tail(&dev->legacy_dev_list, &driver->legacy_dev_list);
+-
+- return 0;
+-
+-err_agp:
+- nv_drm_pci_agp_destroy(dev);
+- pci_disable_device(pdev);
+-err_free:
+- drm_dev_put(dev);
+- return ret;
+-}
+ #endif
+
+-/*
+- * Code from drm_legacy_pci_{init,exit}
+- * Extracted from tag: v5.6.3, file: drivers/gpu/drm/drm_pci.c
+- */
+-int nv_drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver)
+-{
+- struct pci_dev *pdev = NULL;
+- const struct pci_device_id *pid;
+- int i;
+-
+- DRM_DEBUG("\n");
+-
+- if (WARN_ON(!(driver->driver_features & DRIVER_LEGACY)))
+- return -EINVAL;
+-
+- /* If not using KMS, fall back to stealth mode manual scanning. */
+- INIT_LIST_HEAD(&driver->legacy_dev_list);
+- for (i = 0; pdriver->id_table[i].vendor != 0; i++) {
+- pid = &pdriver->id_table[i];
+-
+- /* Loop around setting up a DRM device for each PCI device
+- * matching our ID and device class. If we had the internal
+- * function that pci_get_subsys and pci_get_class used, we'd
+- * be able to just pass pid in instead of doing a two-stage
+- * thing.
+- */
+- pdev = NULL;
+- while ((pdev =
+- pci_get_subsys(pid->vendor, pid->device, pid->subvendor,
+- pid->subdevice, pdev)) != NULL) {
+- if ((pdev->class & pid->class_mask) != pid->class)
+- continue;
+-
+- /* stealth mode requires a manual probe */
+- pci_dev_get(pdev);
+- nv_drm_get_pci_dev(pdev, pid, driver);
+- }
+- }
+- return 0;
+-}
+-
+-void nv_drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver)
+-{
+- struct drm_device *dev, *tmp;
+- DRM_DEBUG("\n");
+-
+- if (!(driver->driver_features & DRIVER_LEGACY)) {
+- WARN_ON(1);
+- } else {
+- list_for_each_entry_safe(dev, tmp, &driver->legacy_dev_list,
+- legacy_dev_list) {
+- list_del(&dev->legacy_dev_list);
+- drm_put_dev(dev);
+- }
+- }
+- DRM_INFO("Module unloaded\n");
+-}
+-#endif
++static struct nv_drm_device *dev_list = NULL;
+
+ extern nv_linux_state_t *nv_linux_devices;
+
+@@ -359,36 +139,49 @@
+ NV_KFREE(nv_obj, sizeof(*nv_obj));
+ }
+
+-static struct sg_table* nv_gem_prime_get_sg_table(
+- struct drm_gem_object *obj
+-)
++static int nv_drm_get_dev_info_ioctl(struct drm_device *dev,
++ void *data, struct drm_file *filep)
+ {
+- struct nv_gem_object *nv_obj = container_of(obj, struct nv_gem_object, base);
+- int page_count = obj->size >> PAGE_SHIFT;
++ struct nv_drm_device *nv_dev = to_nv_device(dev);
++ struct drm_nvidia_get_dev_info_params *params = data;
+
+- #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
+- return drm_prime_pages_to_sg(obj->dev, nv_obj->pages, page_count);
+- #else
+- return drm_prime_pages_to_sg(nv_obj->pages, page_count);
+- #endif
+-}
++ if (dev->primary == NULL) {
++ return -ENOENT;
++ }
+
+-static void* nv_gem_prime_vmap(
+- struct drm_gem_object *obj
+-)
+-{
+- struct nv_gem_object *nv_obj = container_of(obj, struct nv_gem_object, base);
+- int page_count = obj->size >> PAGE_SHIFT;
++ params->gpu_id = nv_dev->gpu_info.gpu_id;
++ params->primary_index = dev->primary->index;
+
+- return vmap(nv_obj->pages, page_count, VM_USERMAP, PAGE_KERNEL);
++ return 0;
+ }
+
+-static void nv_gem_prime_vunmap(
+- struct drm_gem_object *obj,
+- void *virtual
+-)
+-{
+- vunmap(virtual);
++static
++int nv_drm_get_client_capability_ioctl(struct drm_device *dev,
++ void *data, struct drm_file *filep)
++{
++ struct drm_nvidia_get_client_capability_params *params = data;
++
++ switch (params->capability) {
++#if defined(DRM_CLIENT_CAP_STEREO_3D)
++ case DRM_CLIENT_CAP_STEREO_3D:
++ params->value = filep->stereo_allowed;
++ break;
++#endif
++#if defined(DRM_CLIENT_CAP_UNIVERSAL_PLANES)
++ case DRM_CLIENT_CAP_UNIVERSAL_PLANES:
++ params->value = filep->universal_planes;
++ break;
++#endif
++#if defined(DRM_CLIENT_CAP_ATOMIC)
++ case DRM_CLIENT_CAP_ATOMIC:
++ params->value = filep->atomic;
++ break;
++#endif
++ default:
++ return -EINVAL;
++ }
++
++ return 0;
+ }
+
+ static const struct file_operations nv_drm_fops = {
+@@ -402,6 +195,43 @@
+ .llseek = noop_llseek,
+ };
+
++static const struct drm_ioctl_desc nv_drm_ioctls[] = {
++// #if defined(NV_DRM_ATOMIC_MODESET_AVAILABLE)
++// DRM_IOCTL_DEF_DRV(NVIDIA_GEM_IMPORT_NVKMS_MEMORY,
++// nv_drm_gem_import_nvkms_memory_ioctl,
++// DRM_UNLOCKED),
++// #endif /* NV_DRM_ATOMIC_MODESET_AVAILABLE */
++//
++ DRM_IOCTL_DEF_DRV(NVIDIA_GEM_IMPORT_USERSPACE_MEMORY,
++ nv_drm_gem_import_userspace_memory_ioctl,
++ DRM_RENDER_ALLOW|DRM_UNLOCKED),
++ DRM_IOCTL_DEF_DRV(NVIDIA_GET_DEV_INFO,
++ nv_drm_get_dev_info_ioctl,
++ DRM_RENDER_ALLOW|DRM_UNLOCKED),
++
++// #if defined(NV_DRM_FENCE_AVAILABLE)
++// DRM_IOCTL_DEF_DRV(NVIDIA_FENCE_SUPPORTED,
++// nv_drm_fence_supported_ioctl,
++// DRM_RENDER_ALLOW|DRM_UNLOCKED),
++// DRM_IOCTL_DEF_DRV(NVIDIA_FENCE_CONTEXT_CREATE,
++// nv_drm_fence_context_create_ioctl,
++// DRM_RENDER_ALLOW|DRM_UNLOCKED),
++// DRM_IOCTL_DEF_DRV(NVIDIA_GEM_FENCE_ATTACH,
++// nv_drm_gem_fence_attach_ioctl,
++// DRM_RENDER_ALLOW|DRM_UNLOCKED),
++// #endif
++
++ DRM_IOCTL_DEF_DRV(NVIDIA_GET_CLIENT_CAPABILITY,
++ nv_drm_get_client_capability_ioctl,
++ 0),
++// #if defined(NV_DRM_ATOMIC_MODESET_AVAILABLE)
++// DRM_IOCTL_DEF_DRV(NVIDIA_GET_CRTC_CRC32,
++// nv_drm_get_crtc_crc32_ioctl,
++// DRM_RENDER_ALLOW|DRM_UNLOCKED),
++// #endif /* NV_DRM_ATOMIC_MODESET_AVAILABLE */
++};
++
++
+ static struct drm_driver nv_drm_driver = {
+
+ .driver_features = DRIVER_GEM
+@@ -420,17 +250,26 @@
+ .set_busid = drm_pci_set_busid,
+ #endif
+
+-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
+- .gem_free_object_unlocked = nv_gem_free,
+-#else
++#if defined(NV_DRM_DRIVER_HAS_GEM_FREE_OBJECT)
+ .gem_free_object = nv_gem_free,
++#elif LINUX_VERSION_CODE <= KERNEL_VERSION(5, 10, 0)
++ .gem_free_object_unlocked = nv_gem_free,
+ #endif
+
++ .ioctls = nv_drm_ioctls,
++ .num_ioctls = ARRAY_SIZE(nv_drm_ioctls),
++
+ .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
+- .gem_prime_export = drm_gem_prime_export,
+- .gem_prime_get_sg_table = nv_gem_prime_get_sg_table,
+- .gem_prime_vmap = nv_gem_prime_vmap,
+- .gem_prime_vunmap = nv_gem_prime_vunmap,
++#if defined(NV_DRM_DRIVER_HAS_GEM_PRIME_CALLBACKS)
++ .gem_prime_export = nv_drm_gem_prime_export,
++ .gem_prime_get_sg_table = nv_drm_gem_prime_get_sg_table,
++ .gem_prime_vmap = nv_drm_gem_prime_vmap,
++ .gem_prime_vunmap = nv_drm_gem_prime_vunmap,
++#endif
++
++#if defined(NV_DRM_DRIVER_HAS_GEM_PRIME_RES_OBJ)
++ .gem_prime_res_obj = nv_drm_gem_prime_res_obj,
++#endif
+
+ .name = "nvidia-drm",
+ .desc = "NVIDIA DRM driver",
+@@ -438,7 +277,198 @@
+ .major = 0,
+ .minor = 0,
+ .patchlevel = 0,
++
++#if defined(NV_DRM_DRIVER_HAS_DEVICE_LIST)
++ .device_list = LIST_HEAD_INIT(nv_drm_driver.device_list),
++#elif defined(NV_DRM_DRIVER_HAS_LEGACY_DEV_LIST)
++ .legacy_dev_list = LIST_HEAD_INIT(nv_drm_driver.legacy_dev_list),
++#endif
+ };
++
++/*!
++ * Enumerate the available physical GPUs that can be used with NVKMS.
++ *
++ * \param [out] gpuInfo The information of the enumerated GPUs.
++ * It is an array of NVIDIA_MAX_GPUS elements.
++ *
++ * \return Count of enumerated gpus.
++ */
++
++/*
++ * Implemented based on code from drm_legacy_pci_{init,exit}
++ * Extracted from tag: v5.6.3, file: drivers/gpu/drm/drm_pci.c
++ */
++static NvU32 nvKmsenumerateGpus(nv_gpu_info_t *gpuInfo, struct drm_driver *driver,
struct pci_driver *pdriver)
++{
++ NvU32 gpu_count = 0;
++
++ struct pci_dev *pdev = NULL;
++ const struct pci_device_id *pid;
++ int i;
++
++ DRM_DEBUG("\n");
++
++ for (i = 0; pdriver->id_table[i].vendor != 0; i++) {
++ pid = &pdriver->id_table[i];
++
++ /* Loop around setting up a DRM device for each PCI device
++ * matching our ID and device class. If we had the internal
++ * function that pci_get_subsys and pci_get_class used, we'd
++ * be able to just pass pid in instead of doing a two-stage
++ * thing.
++ */
++ pdev = NULL;
++ while ((pdev =
++ pci_get_subsys(pid->vendor, pid->device, pid->subvendor,
++ pid->subdevice, pdev)) != NULL) {
++
++ if ((pdev->class & pid->class_mask) != pid->class)
++ continue;
++
++ /* stealth mode requires a manual probe */
++ pci_dev_get(pdev);
++
++ gpuInfo[i].gpu_id = pid->device;
++ gpuInfo[i].pci_info.domain = pci_domain_nr(pdev->bus);
++ gpuInfo[i].pci_info.bus = pdev->bus->number;
++ gpuInfo[i].pci_info.slot = PCI_SLOT(pdev->devfn);
++ gpuInfo[i].pci_info.function = PCI_FUNC(pdev->devfn);
++ gpuInfo[i].os_dev_ptr = pdev;
++ gpu_count += 1;
++ }
++ }
++ return gpu_count;
++}
++
++/*
++ * Helper function for allocate/register DRM device for given NVIDIA GPU ID.
++ */
++static void nv_drm_register_drm_device(const nv_gpu_info_t *gpu_info)
++{
++ struct nv_drm_device *nv_dev = NULL;
++ struct drm_device *dev = NULL;
++ struct pci_dev *pdev = gpu_info->os_dev_ptr;
++
++ DRM_DEBUG(
++ "Registering device for NVIDIA GPU ID 0x08%x",
++ gpu_info->gpu_id);
++
++ /* Allocate NVIDIA-DRM device */
++
++ nv_dev = nv_drm_calloc(1, sizeof(*nv_dev));
++
++ if (nv_dev == NULL) {
++ NV_DRM_LOG_ERR(
++ "Failed to allocate memmory for NVIDIA-DRM device object");
++ return;
++ }
++
++ nv_dev->gpu_info = *gpu_info;
++
++#if defined(NV_DRM_ATOMIC_MODESET_AVAILABLE)
++ mutex_init(&nv_dev->lock);
++#endif
++
++ /* Allocate DRM device */
++
++ dev = drm_dev_alloc(&nv_drm_driver, &pdev->dev);
++
++ if (dev == NULL) {
++ NV_DRM_DEV_LOG_ERR(nv_dev, "Failed to allocate device");
++ goto failed_drm_alloc;
++ }
++
++ dev->dev_private = nv_dev;
++ nv_dev->dev = dev;
++ dev->pdev = pdev;
++
++ /* Register DRM device to DRM sub-system */
++
++ if (drm_dev_register(dev, 0) != 0) {
++ NV_DRM_DEV_LOG_ERR(nv_dev, "Failed to register device");
++ goto failed_drm_register;
++ }
++
++ /* Add NVIDIA-DRM device into list */
++
++ nv_dev->next = dev_list;
++ dev_list = nv_dev;
++
++ return; /* Success */
++
++failed_drm_register:
++
++ nv_drm_dev_free(dev);
++
++failed_drm_alloc:
++
++ nv_drm_free(nv_dev);
++}
++
++/*
++ * Enumerate NVIDIA GPUs and allocate/register DRM device for each of them.
++ */
++int nv_drm_probe_devices(struct drm_driver *driver, struct pci_driver *pdriver)
++{
++ nv_gpu_info_t *gpu_info = NULL;
++ NvU32 gpu_count = 0;
++ NvU32 i;
++
++ int ret = 0;
++
++// nv_drm_update_drm_driver_features();
++
++ /* Enumerate NVIDIA GPUs */
++
++ gpu_info = nv_drm_calloc(NV_MAX_GPUS, sizeof(*gpu_info));
++
++ if (gpu_info == NULL) {
++ ret = -ENOMEM;
++
++ NV_DRM_LOG_ERR("Failed to allocate gpu ids arrays");
++ goto done;
++ }
++
++ gpu_count = nvKmsenumerateGpus(gpu_info, driver, pdriver);
++// gpu_count = nvKms->enumerateGpus(gpu_info);
++
++ if (gpu_count == 0) {
++ NV_DRM_LOG_INFO("Not found NVIDIA GPUs");
++ goto done;
++ }
++
++ WARN_ON(gpu_count > NV_MAX_GPUS);
++
++ /* Register DRM device for each NVIDIA GPU */
++
++ for (i = 0; i < gpu_count; i++) {
++ nv_drm_register_drm_device(&gpu_info[i]);
++ }
++
++done:
++
++ nv_drm_free(gpu_info);
++
++ return ret;
++}
++
++/*
++ * Unregister all NVIDIA DRM devices.
++ */
++void nv_drm_remove_devices(void)
++{
++ while (dev_list != NULL) {
++ struct nv_drm_device *next = dev_list->next;
++
++ drm_dev_unregister(dev_list->dev);
++ nv_drm_dev_free(dev_list->dev);
++
++ nv_drm_free(dev_list);
++
++ dev_list = next;
++ }
++}
++
+ #endif /* defined(NV_DRM_AVAILABLE) */
+
+ int __init nv_drm_init(
+@@ -447,7 +477,7 @@
+ {
+ int ret = 0;
+ #if defined(NV_DRM_AVAILABLE)
+- ret = nv_drm_pci_init(&nv_drm_driver, pci_driver);
++ ret = nv_drm_probe_devices(&nv_drm_driver, pci_driver);
+ #endif
+ return ret;
+ }
+@@ -457,7 +487,7 @@
+ )
+ {
+ #if defined(NV_DRM_AVAILABLE)
+- nv_drm_pci_exit(&nv_drm_driver, pci_driver);
++ nv_drm_remove_devices();
+ #endif
+ }
+
+@@ -518,15 +548,17 @@
+ goto done;
+ }
+
+-#if defined(NV_DRM_GEM_OBJECT_PUT_UNLOCKED_PRESENT)
++#if defined(NV_DRM_GEM_OBJECT_GET_PRESENT)
++
++#if defined(NV_DRM_GEM_OBJECT_PUT_UNLOCK_PRESENT)
+ drm_gem_object_put_unlocked(&nv_obj->base);
+ #else
+-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
+- drm_gem_object_put_locked(&nv_obj->base);
++ drm_gem_object_put(&nv_obj->base);
++#endif
++
+ #else
+ drm_gem_object_unreference_unlocked(&nv_obj->base);
+ #endif
+-#endif
+
+ status = RM_OK;
+
+diff -Naur a/kernel/nvidia-drm-gem.c b/kernel/nvidia-drm-gem.c
+--- a/kernel/nvidia-drm-gem.c 2021-06-09 21:37:47.511578395 +0200
++++ b/kernel/nvidia-drm-gem.c 2021-06-09 21:39:15.634612087 +0200
+@@ -26,10 +26,10 @@
+
+ #include "nvidia-drm-priv.h"
+ #include "nvidia-drm-ioctl.h"
+-#include "nvidia-drm-prime-fence.h"
++// #include "nvidia-drm-prime-fence.h"
+ #include "nvidia-drm-gem.h"
+ #include "nvidia-dma-resv-helper.h"
+-#include "nvidia-drm-gem-nvkms-memory.h"
++// #include "nvidia-drm-gem-nvkms-memory.h"
+
+ #if defined(NV_DRM_DRM_PRIME_H_PRESENT)
+ #include <drm/drm_prime.h>
+@@ -88,9 +88,9 @@
+ .vunmap = nv_drm_gem_prime_vunmap,
+ #endif
+
+-#if defined(NV_DRM_ATOMIC_MODESET_AVAILABLE)
+- .vm_ops = &nv_drm_gem_vma_ops,
+-#endif
++// #if defined(NV_DRM_ATOMIC_MODESET_AVAILABLE)
++// .vm_ops = &nv_drm_gem_vma_ops,
++// #endif
+
+ #endif
+ };
+diff -Naur a/kernel/nvidia-drm-linux.c b/kernel/nvidia-drm-linux.c
+--- a/kernel/nvidia-drm-linux.c 2021-06-09 21:37:47.511578395 +0200
++++ b/kernel/nvidia-drm-linux.c 2021-06-09 21:39:15.634612087 +0200
+@@ -25,7 +25,6 @@
+ #include <linux/err.h>
+
+ #include "nvidia-drm-os-interface.h"
+-#include "nvidia-drm.h"
+
+ #include "conftest.h"
+
+@@ -161,25 +160,3 @@
+ * Linux loading support code.
+ *************************************************************************/
+
+-static int __init nv_linux_drm_init(void)
+-{
+- return nv_drm_init();
+-}
+-
+-static void __exit nv_linux_drm_exit(void)
+-{
+- nv_drm_exit();
+-}
+-
+-module_init(nv_linux_drm_init);
+-module_exit(nv_linux_drm_exit);
+-
+-#if defined(MODULE_LICENSE)
+- MODULE_LICENSE("MIT");
+-#endif
+-#if defined(MODULE_INFO)
+- MODULE_INFO(supported, "external");
+-#endif
+-#if defined(MODULE_VERSION)
+- MODULE_VERSION(NV_VERSION_STRING);
+-#endif
+diff -Naur a/kernel/nvidia-modules-common.mk b/kernel/nvidia-modules-common.mk
+--- a/kernel/nvidia-modules-common.mk 2021-06-09 21:37:47.478579114 +0200
++++ b/kernel/nvidia-modules-common.mk 2021-06-09 21:39:15.634612087 +0200
+@@ -149,7 +149,7 @@
+ CONFTEST_HEADERS := $(obj)/conftest.h $(CONFTEST_COMPILE_TEST_HEADERS) \
+ $(obj)/conftest/patches.h
+
+-$(obj)/conftest.h $(CONFTEST_COMPILE_TEST_HEADERS): conftest-compile-test
++# $(obj)/conftest.h $(CONFTEST_COMPILE_TEST_HEADERS): conftest-compile-test
+
+ conftest-compile-test: $(src)/conftest.sh
+ @if ! $(CONFTEST) compile_tests $(COMPILE_TESTS); then exit 1; fi
+@@ -318,7 +318,7 @@
+ @$(RM) -f build-in.o nv-linux*.o *.d .*.cmd .*.flags
+ @$(RM) -f $(MODULE_NAME)*.o $(MODULE_NAME)*.ko*
+ @$(RM) -f $(MODULE_NAME)*.mod* $(VERSION_HEADER) *~
+- @$(RM) -f conftest*.c conftest.h
++ @$(RM) -f conftest*.c
+ @$(RM) -rf conftest
+ @$(RM) -rf Module*.symvers .tmp_versions modules.order
+
diff -Naur a/kernel/nv-linux.h b/kernel/nv-linux.h
---- a/kernel/nv-linux.h 2021-02-23 20:01:52.429999710 +0100
-+++ b/kernel/nv-linux.h 2021-02-23 14:48:00.163333638 +0100
-@@ -119,7 +119,9 @@
+--- a/kernel/nv-linux.h 2021-06-09 21:37:47.476579158 +0200
++++ b/kernel/nv-linux.h 2021-06-09 21:54:09.093016589 +0200
+@@ -119,12 +119,15 @@
#include <asm/tlbflush.h> /* flush_tlb(), flush_tlb_all() */
#include <linux/cpu.h> /* CPU hotplug support */
#endif
-#include <asm/kmap_types.h> /* page table entry lookup */
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0)
++#if defined(NV_ASM_KMAP_TYPES_H_PRESENT)
+ #include <asm/kmap_types.h> /* page table entry lookup */
+#endif
#include <linux/pci.h> /* pci_find_class, etc */
#include <linux/interrupt.h> /* tasklets, interrupt helpers */
---- a/kernel/uvm/nvidia_uvm_linux.h 2019-12-11 17:04:24.000000000 -0500
-+++ b/kernel/uvm/nvidia_uvm_linux.h 2021-02-24 06:26:26.237367942 -0500
+ #include <linux/timer.h>
+-
++#include <linux/file.h> /* fget(), fput()
++*/
+ #include <asm/div64.h> /* do_div() */
+ #if defined(NV_ASM_SYSTEM_H_PRESENT)
+ #include <asm/system.h> /* cli, sli, save_flags */
+@@ -134,12 +137,10 @@
+ #include <asm/page.h> /* PAGE_OFFSET */
+ #include <asm/pgtable.h> /* pte bit definitions */
+
+-#if defined(NVCPU_X86_64) && !defined(HAVE_COMPAT_IOCTL)
++#if defined(NVCPU_X86_64) && !defined(NV_FILE_OPERATIONS_HAS_COMPAT_IOCTL)
+ #include <linux/syscalls.h> /* sys_ioctl() */
+-#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0)
+ #include <linux/ioctl32.h> /* register_ioctl32_conversion() */
+ #endif
+-#endif
+
+ #if !defined(NV_FILE_OPERATIONS_HAS_IOCTL) && \
+ !defined(NV_FILE_OPERATIONS_HAS_UNLOCKED_IOCTL)
+@@ -672,7 +673,7 @@
+ # define KM_FREE_RECORD(a,b,c)
+ #endif
+
+-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
++#if !defined(NV_VMALLOC_HAS_PGPROT_T_ARG)
+ #define NV_VMALLOC(ptr, size) \
+ { \
+ (ptr) = __vmalloc(size, GFP_KERNEL); \
+@@ -2247,18 +2248,19 @@
+ flags |= FOLL_FORCE;
+
+ #if defined(NV_GET_USER_PAGES_REMOTE_HAS_LOCKED_ARG)
+-
++ #if defined (NV_GET_USER_PAGES_REMOTE_HAS_TSK_ARG)
+ return get_user_pages_remote(tsk, mm, start, nr_pages, flags,
+ pages, vmas, NULL);
+-
+- #else
+-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
++ #else
+ return get_user_pages_remote(mm, start, nr_pages, flags,
+ pages, vmas, NULL);
+-#else
++ #endif
++
++ #else
++
+ return get_user_pages_remote(tsk, mm, start, nr_pages, flags,
+ pages, vmas);
+-#endif
++
+ #endif
+
+ }
+diff -Naur a/kernel/nv-vm.c b/kernel/nv-vm.c
+--- a/kernel/nv-vm.c 2021-06-09 21:37:47.476579158 +0200
++++ b/kernel/nv-vm.c 2021-06-09 21:43:13.262501779 +0200
+@@ -12,6 +12,9 @@
+ #include "os-interface.h"
+ #include "nv.h"
+ #include "nv-linux.h"
++#if defined(NV_ASM_SET_MEMORY_H_PRESENT)
++#include <asm/set_memory.h>
++#endif
+
+ static inline void nv_set_contig_memory_uc(nv_pte_t *page_ptr, NvU32 num_pages)
+ {
+diff -Naur a/kernel/os-mlock.c b/kernel/os-mlock.c
+--- a/kernel/os-mlock.c 2021-06-09 21:37:47.478579114 +0200
++++ b/kernel/os-mlock.c 2021-06-09 21:39:15.634612087 +0200
+@@ -44,7 +44,7 @@
+ return rmStatus;
+ }
+
+-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
++#if defined(NV_MM_HAS_MMAP_LOCK)
+ down_read(&mm->mmap_lock);
+ ret = NV_GET_USER_PAGES((unsigned long)address,
+ page_count, write, force, user_pages, NULL);
+diff -Naur a/kernel/uvm/nvidia_uvm_linux.h b/kernel/uvm/nvidia_uvm_linux.h
+--- a/kernel/uvm/nvidia_uvm_linux.h 2021-06-09 21:37:47.479579092 +0200
++++ b/kernel/uvm/nvidia_uvm_linux.h 2021-06-09 21:54:25.298653372 +0200
@@ -141,7 +141,9 @@
#if !defined(NV_VMWARE)
#include <asm/tlbflush.h> /* flush_tlb(), flush_tlb_all() */
#endif
-#include <asm/kmap_types.h> /* page table entry lookup */
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0)
++#if defined(NV_ASM_KMAP_TYPES_H_PRESENT)
+ #include <asm/kmap_types.h> /* page table entry lookup */
+#endif
#include <linux/interrupt.h> /* tasklets, interrupt helpers */
#include <linux/timer.h>
+@@ -156,12 +158,10 @@
+ #include <asm/page.h> /* PAGE_OFFSET */
+ #include <asm/pgtable.h> /* pte bit definitions */
+
+-#if defined(NVCPU_X86_64) && !defined(HAVE_COMPAT_IOCTL)
++#if defined(NVCPU_X86_64) && !defined(NV_FILE_OPERATIONS_HAS_COMPAT_IOCTL)
+ #include <linux/syscalls.h> /* sys_ioctl() */
+-#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0)
+ #include <linux/ioctl32.h> /* register_ioctl32_conversion() */
+ #endif
+-#endif
+
+ #if !defined(NV_FILE_OPERATIONS_HAS_IOCTL) && \
+ !defined(NV_FILE_OPERATIONS_HAS_UNLOCKED_IOCTL)
+diff -Naur a/kernel/uvm/nvidia_uvm_lite_api.c b/kernel/uvm/nvidia_uvm_lite_api.c
+--- a/kernel/uvm/nvidia_uvm_lite_api.c 2021-06-09 21:37:47.479579092 +0200
++++ b/kernel/uvm/nvidia_uvm_lite_api.c 2021-06-09 21:39:15.635612064 +0200
+@@ -30,7 +30,7 @@
+ #include "uvm_gpu_ops_tests.h"
+ #endif
+
+-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
++#if defined (NV_MM_HAS_MMAP_LOCK)
+ #define mmap_sem mmap_lock
+ #endif
+
diff --git a/nvidia-340xx-kmod.spec b/nvidia-340xx-kmod.spec
index 5ffce9b..60c2271 100644
--- a/nvidia-340xx-kmod.spec
+++ b/nvidia-340xx-kmod.spec
@@ -12,7 +12,7 @@ Name: nvidia-340xx-kmod
Epoch: 1
Version: 340.108
# Taken over by kmodtool
-Release: 11%{?dist}
+Release: 13%{?dist}
Summary: NVIDIA display driver kernel module
Group: System Environment/Kernel
License: Redistributable, no modification permitted
@@ -62,7 +62,6 @@ for kernel_version in %{?kernel_versions} ; do
cp -a kernel _kmod_build_${kernel_version%%___*}
done
-
%build
for kernel_version in %{?kernel_versions}; do
pushd _kmod_build_${kernel_version%%___*}/
@@ -86,6 +85,9 @@ done
%{?akmod_install}
%changelog
+* Sun Jun 27 2021 Thaison Nguyen <thieson08(a)me.com> - 1:340.108-13
+- Fix patch for kernel-5.11.0 (Thanks at Łukasz Wojniłowicz
<lukasz.wojnilowicz(a)gmail.com>)
+
* Mon Mar 01 2021 Thaison Nguyen <thieson08(a)me.com> - 1:340.108-12
- Patch for kernel-5.11.0
- Cleaning up kernel-5.7.0 patch