diff --git a/kernel-dkms/nvidia/nvidia.Kbuild b/kernel-dkms/nvidia/nvidia.Kbuild index 5ec3e65..2897e31 100644 --- a/kernel-dkms/nvidia/nvidia.Kbuild +++ b/kernel-dkms/nvidia/nvidia.Kbuild @@ -150,6 +151,7 @@ NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_swiotlb_dma_ops NV_CONFTEST_TYPE_COMPILE_TESTS += acpi_op_remove NV_CONFTEST_TYPE_COMPILE_TESTS += outer_flush_all NV_CONFTEST_TYPE_COMPILE_TESTS += file_operations +NV_CONFTEST_TYPE_COMPILE_TESTS += proc_ops NV_CONFTEST_TYPE_COMPILE_TESTS += file_inode NV_CONFTEST_TYPE_COMPILE_TESTS += kuid_t NV_CONFTEST_TYPE_COMPILE_TESTS += dma_ops diff --git a/kernel-dkms/common/inc/nv-procfs.h b/kernel-dkms/common/inc/nv-procfs.h index 8b53f86..4c5aceb 100644 --- a/kernel-dkms/common/inc/nv-procfs.h +++ b/kernel-dkms/common/inc/nv-procfs.h @@ -28,6 +28,18 @@ #define IS_EXERCISE_ERROR_FORWARDING_ENABLED() (EXERCISE_ERROR_FORWARDING) +#if defined(NV_HAVE_PROC_OPS) +#define NV_CREATE_PROC_FILE(filename,parent,__name,__data) \ + ({ \ + struct proc_dir_entry *__entry; \ + int mode = (S_IFREG | S_IRUGO); \ + const struct proc_ops *fops = &nv_procfs_##__name##_fops; \ + if (fops->proc_write != 0) \ + mode |= S_IWUSR; \ + __entry = proc_create_data(filename, mode, parent, fops, __data);\ + __entry; \ + }) +#else #define NV_CREATE_PROC_FILE(filename,parent,__name,__data) \ ({ \ struct proc_dir_entry *__entry; \ @@ -38,6 +50,7 @@ __entry = proc_create_data(filename, mode, parent, fops, __data);\ __entry; \ }) +#endif /* * proc_mkdir_mode exists in Linux 2.6.9, but isn't exported until Linux 3.0. @@ -77,6 +90,44 @@ remove_proc_entry(entry->name, entry->parent); #endif +#if defined(NV_HAVE_PROC_OPS) +#define NV_DEFINE_SINGLE_PROCFS_FILE(name, open_callback, close_callback) \ + static int nv_procfs_open_##name( \ + struct inode *inode, \ + struct file *filep \ + ) \ + { \ + int ret; \ + ret = single_open(filep, nv_procfs_read_##name, \ + NV_PDE_DATA(inode)); \ + if (ret < 0) \ + { \ + return ret; \ + } \ + ret = open_callback(); \ + if (ret < 0) \ + { \ + single_release(inode, filep); \ + } \ + return ret; \ + } \ + \ + static int nv_procfs_release_##name( \ + struct inode *inode, \ + struct file *filep \ + ) \ + { \ + close_callback(); \ + return single_release(inode, filep); \ + } \ + \ + static const struct proc_ops nv_procfs_##name##_fops = { \ + .proc_open = nv_procfs_open_##name, \ + .proc_read = seq_read, \ + .proc_lseek = seq_lseek, \ + .proc_release = nv_procfs_release_##name, \ + }; +#else #define NV_DEFINE_SINGLE_PROCFS_FILE(name, open_callback, close_callback) \ static int nv_procfs_open_##name( \ struct inode *inode, \ @@ -114,6 +165,7 @@ .llseek = seq_lseek, \ .release = nv_procfs_release_##name, \ }; +#endif #endif /* CONFIG_PROC_FS */ diff --git a/kernel-dkms/conftest.sh b/kernel-dkms/conftest.sh index 57d85a4..4902248 100755 --- a/kernel-dkms/conftest.sh +++ b/kernel-dkms/conftest.sh @@ -806,6 +822,16 @@ compile_test() { compile_check_conftest "$CODE" "NV_FILE_OPERATIONS_HAS_IOCTL" "" "types" ;; + proc_ops) + CODE=" + #include + int conftest_proc_ops(void) { + return offsetof(struct proc_ops, proc_open); + }" + + compile_check_conftest "$CODE" "NV_HAVE_PROC_OPS" "" "types" + ;; + sg_alloc_table) # # sg_alloc_table_from_pages added by commit efc42bc98058 diff --git a/kernel-dkms/nvidia/nv-procfs.c b/kernel-dkms/nvidia/nv-procfs.c index 064d727..a7308d3 100644 --- a/kernel-dkms/nvidia/nv-procfs.c +++ b/kernel-dkms/nvidia/nv-procfs.c @@ -452,6 +452,15 @@ done: return ((status < 0) ? status : (int)count); } +#if defined(NV_HAVE_PROC_OPS) +static struct proc_ops nv_procfs_registry_fops = { + .proc_open = nv_procfs_open_registry, + .proc_read = seq_read, + .proc_write = nv_procfs_write_file, + .proc_lseek = seq_lseek, + .proc_release = nv_procfs_close_registry, +}; +#else static struct file_operations nv_procfs_registry_fops = { .owner = THIS_MODULE, .open = nv_procfs_open_registry, @@ -460,6 +469,7 @@ static struct file_operations nv_procfs_registry_fops = { .llseek = seq_lseek, .release = nv_procfs_close_registry, }; +#endif #if defined(CONFIG_PM) static int @@ -531,6 +541,15 @@ nv_procfs_open_suspend_depth( return single_open(file, nv_procfs_show_suspend_depth, NULL); } +#if defined(NV_HAVE_PROC_OPS) +static struct proc_ops nv_procfs_suspend_depth_fops = { + .proc_open = nv_procfs_open_suspend_depth, + .proc_read = seq_read, + .proc_write = nv_procfs_write_suspend_depth, + .proc_lseek = seq_lseek, + .proc_release = single_release +}; +#else static struct file_operations nv_procfs_suspend_depth_fops = { .owner = THIS_MODULE, .open = nv_procfs_open_suspend_depth, @@ -539,6 +558,7 @@ static struct file_operations nv_procfs_suspend_depth_fops = { .llseek = seq_lseek, .release = single_release }; +#endif static int nv_procfs_show_suspend( @@ -613,6 +633,15 @@ nv_procfs_open_suspend( return single_open(file, nv_procfs_show_suspend, NULL); } +#if defined(NV_HAVE_PROC_OPS) +static struct proc_ops nv_procfs_suspend_fops = { + .proc_open = nv_procfs_open_suspend, + .proc_read = seq_read, + .proc_write = nv_procfs_write_suspend, + .proc_lseek = seq_lseek, + .proc_release = single_release +}; +#else static struct file_operations nv_procfs_suspend_fops = { .owner = THIS_MODULE, .open = nv_procfs_open_suspend, @@ -622,6 +651,7 @@ static struct file_operations nv_procfs_suspend_fops = { .release = single_release }; #endif +#endif /* * Forwards error to nv_log_error which exposes data to vendor callback @@ -724,12 +754,20 @@ done: return status; } +#if defined(NV_HAVE_PROC_OPS) +static struct proc_ops nv_procfs_exercise_error_forwarding_fops = { + .proc_open = nv_procfs_open_exercise_error_forwarding, + .proc_write = nv_procfs_write_file, + .proc_release = nv_procfs_close_exercise_error_forwarding, +}; +#else static struct file_operations nv_procfs_exercise_error_forwarding_fops = { .owner = THIS_MODULE, .open = nv_procfs_open_exercise_error_forwarding, .write = nv_procfs_write_file, .release = nv_procfs_close_exercise_error_forwarding, }; +#endif static int nv_procfs_read_unbind_lock( @@ -851,6 +889,15 @@ done: return rc; } +#if defined(NV_HAVE_PROC_OPS) +static struct proc_ops nv_procfs_unbind_lock_fops = { + .proc_open = nv_procfs_open_unbind_lock, + .proc_read = seq_read, + .proc_write = nv_procfs_write_file, + .proc_lseek = seq_lseek, + .proc_release = nv_procfs_close_unbind_lock, +}; +#else static struct file_operations nv_procfs_unbind_lock_fops = { .owner = THIS_MODULE, .open = nv_procfs_open_unbind_lock, @@ -859,6 +906,7 @@ static struct file_operations nv_procfs_unbind_lock_fops = { .llseek = seq_lseek, .release = nv_procfs_close_unbind_lock, }; +#endif static const char* numa_status_describe(nv_numa_status_t state) @@ -1187,6 +1235,22 @@ done: return retval; } +#if defined(NV_HAVE_PROC_OPS) +static const struct proc_ops nv_procfs_numa_status_fops = { + .proc_open = nv_procfs_open_numa_status, + .proc_read = seq_read, + .proc_write = nv_procfs_write_file, + .proc_lseek = seq_lseek, + .proc_release = nv_procfs_close_numa_status, +}; + +static const struct proc_ops nv_procfs_offline_pages_fops = { + .proc_open = nv_procfs_open_offline_pages, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = nv_procfs_close_offline_pages, +}; +#else static const struct file_operations nv_procfs_numa_status_fops = { .owner = THIS_MODULE, .open = nv_procfs_open_numa_status, @@ -1203,6 +1267,7 @@ static const struct file_operations nv_procfs_offline_pages_fops = { .llseek = seq_lseek, .release = nv_procfs_close_offline_pages, }; +#endif static int nv_procfs_read_text_file( diff --git a/kernel-dkms/nvidia/os-interface.c b/kernel-dkms/nvidia/os-interface.c index 07f1b77..a8f1d85 100644 --- a/kernel-dkms/nvidia/os-interface.c +++ b/kernel-dkms/nvidia/os-interface.c @@ -477,9 +477,15 @@ NV_STATUS NV_API_CALL os_get_current_time( void NV_API_CALL os_get_current_tick(NvU64 *nseconds) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) + struct timespec64 ts; + + jiffies_to_timespec64(jiffies, &ts); +#else struct timespec ts; jiffies_to_timespec(jiffies, &ts); +#endif *nseconds = ((NvU64)ts.tv_sec * NSEC_PER_SEC + (NvU64)ts.tv_nsec); } diff --git a/kernel-dkms/common/inc/56rc3uglyhack.h b/kernel-dkms/common/inc/56rc3uglyhack.h new file mode 100644 index 0000000..389d02f --- /dev/null +++ b/kernel-dkms/common/inc/56rc3uglyhack.h @@ -0,0 +1,80 @@ + +typedef __kernel_long_t __kernel_time_t; + +#ifndef _STRUCT_TIMESPEC +#define _STRUCT_TIMESPEC +struct timespec { + __kernel_old_time_t tv_sec; /* seconds */ + long tv_nsec; /* nanoseconds */ +}; +#endif + +struct timeval { + __kernel_old_time_t tv_sec; /* seconds */ + __kernel_suseconds_t tv_usec; /* microseconds */ +}; + +struct itimerspec { + struct timespec it_interval;/* timer period */ + struct timespec it_value; /* timer expiration */ +}; + +struct itimerval { + struct timeval it_interval;/* timer interval */ + struct timeval it_value; /* current value */ +}; + +#if __BITS_PER_LONG == 64 + +/* timespec64 is defined as timespec here */ +static inline struct timespec timespec64_to_timespec(const struct timespec64 ts64) +{ + return *(const struct timespec *)&ts64; +} + +static inline struct timespec64 timespec_to_timespec64(const struct timespec ts) +{ + return *(const struct timespec64 *)&ts; +} + +#else +static inline struct timespec timespec64_to_timespec(const struct timespec64 ts64) +{ + struct timespec ret; + + ret.tv_sec = (time_t)ts64.tv_sec; + ret.tv_nsec = ts64.tv_nsec; + return ret; +} + +static inline struct timespec64 timespec_to_timespec64(const struct timespec ts) +{ + struct timespec64 ret; + + ret.tv_sec = ts.tv_sec; + ret.tv_nsec = ts.tv_nsec; + return ret; +} +#endif + +static inline void getnstimeofday(struct timespec *ts) +{ + struct timespec64 ts64; + + ktime_get_real_ts64(&ts64); + *ts = timespec64_to_timespec(ts64); +} + +static inline s64 timespec_to_ns(const struct timespec *ts) +{ + return ((s64) ts->tv_sec * NSEC_PER_SEC) + ts->tv_nsec; +} + +static inline void getrawmonotonic(struct timespec *ts) +{ + struct timespec64 ts64; + + ktime_get_raw_ts64(&ts64); + *ts = timespec64_to_timespec(ts64); +} + diff --git a/kernel-dkms/common/inc/nv-time.h b/kernel-dkms/common/inc/nv-time.h index 968b873..165f18b 100644 --- a/kernel-dkms/common/inc/nv-time.h +++ b/kernel-dkms/common/inc/nv-time.h @@ -27,6 +27,10 @@ #include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) +#include "56rc3uglyhack.h" +#endif + static inline void nv_gettimeofday(struct timeval *tv) { #ifdef NV_DO_GETTIMEOFDAY_PRESENT diff --git a/kernel-dkms/nvidia/linux_nvswitch.c b/kernel-dkms/nvidia/linux_nvswitch.c index 1d2c1bc..388d64f 100644 --- a/kernel-dkms/nvidia/linux_nvswitch.c +++ b/kernel-dkms/nvidia/linux_nvswitch.c @@ -26,6 +26,9 @@ #include "conftest.h" #include "nvmisc.h" #include "nv-linux.h" +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) +#include "nv-time.h" +#endif #include "nv-procfs.h" #include "nvlink_common.h" #include "nvlink_errors.h"