aboutsummaryrefslogtreecommitdiff
path: root/system/nvidia-legacy470-kernel/patches/nvidia-470xx-fix-linux-6.15.patch
diff options
context:
space:
mode:
Diffstat (limited to 'system/nvidia-legacy470-kernel/patches/nvidia-470xx-fix-linux-6.15.patch')
-rw-r--r--system/nvidia-legacy470-kernel/patches/nvidia-470xx-fix-linux-6.15.patch265
1 files changed, 265 insertions, 0 deletions
diff --git a/system/nvidia-legacy470-kernel/patches/nvidia-470xx-fix-linux-6.15.patch b/system/nvidia-legacy470-kernel/patches/nvidia-470xx-fix-linux-6.15.patch
new file mode 100644
index 0000000000..476bc0380f
--- /dev/null
+++ b/system/nvidia-legacy470-kernel/patches/nvidia-470xx-fix-linux-6.15.patch
@@ -0,0 +1,265 @@
+From c8980466f837b6c1e961bcfef3cfb70435394736 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Joan=20Bruguera=20Mic=C3=B3?= <joanbrugueram@gmail.com>
+Date: Sat, 12 Apr 2025 22:46:59 +0000
+Subject: [PATCH] Tentative fix for NVIDIA 470.256.02 driver for Linux 6.15-rc1
+
+This is an experimental patch! Use at your own risk!
+TODO: Verify that the fix for vm_flags_(set|clear) is correct.
+EDIT 20250426: I don't believe that this patch is clean: the VMA flags
+ piggybacks on previous calls to acquire the VMA lock,
+ which is very hacky, and most likely doesn't happen 100%
+ of the time and in all code paths.
+
+Replacing EXTRA_CFLAGS with ccflags-y is rel. commit "kbuild: remove
+EXTRA_*FLAGS support" (Masahiro Yamada, 6 Feb 2025), according to which
+they have been deprecated since 2007, so no need to add any fallback.
+
+Thanks to Willy Frissen and Satadru Pramanik, who shared patches for
+various of the necessary changes.
+---
+ Kbuild | 25 +++++++++----------------
+ common/inc/nv-mm.h | 17 +++++++++++++++++
+ common/inc/nv-timer.h | 10 ++++++++++
+ nvidia-drm/nvidia-drm-connector.c | 8 ++++++++
+ nvidia-drm/nvidia-drm-linux.c | 1 +
+ nvidia-modeset/nvidia-modeset-linux.c | 5 +++--
+ nvidia-uvm/uvm.c | 1 +
+ nvidia/nv-frontend.c | 1 +
+ nvidia/nv.c | 4 ++--
+ 9 files changed, 52 insertions(+), 20 deletions(-)
+
+diff --git a/Kbuild b/Kbuild
+index eadd8b2..f333e0b 100644
+--- a/Kbuild
++++ b/Kbuild
+@@ -59,27 +59,20 @@ $(foreach _module, $(NV_KERNEL_MODULES), \
+ $(eval include $(src)/$(_module)/$(_module).Kbuild))
+
+
+-#
+-# Define CFLAGS that apply to all the NVIDIA kernel modules. EXTRA_CFLAGS
+-# is deprecated since 2.6.24 in favor of ccflags-y, but we need to support
+-# older kernels which do not have ccflags-y. Newer kernels append
+-# $(EXTRA_CFLAGS) to ccflags-y for compatibility.
+-#
+-
+-EXTRA_CFLAGS += -I$(src)/common/inc
+-EXTRA_CFLAGS += -I$(src)
+-EXTRA_CFLAGS += -Wall -MD $(DEFINES) $(INCLUDES) -Wno-cast-qual -Wno-error -Wno-format-extra-args
+-EXTRA_CFLAGS += -D__KERNEL__ -DMODULE -DNVRM -DNV_VERSION_STRING=\"470.256.02\" -Wno-unused-function -Wuninitialized -fno-strict-aliasing -mno-red-zone -mcmodel=kernel -DNV_UVM_ENABLE
+-EXTRA_CFLAGS += $(call cc-option,-Werror=undef,)
+-EXTRA_CFLAGS += -DNV_SPECTRE_V2=$(NV_SPECTRE_V2)
+-EXTRA_CFLAGS += -DNV_KERNEL_INTERFACE_LAYER
++ccflags-y += -I$(src)/common/inc
++ccflags-y += -I$(src)
++ccflags-y += -Wall -MD $(DEFINES) $(INCLUDES) -Wno-cast-qual -Wno-error -Wno-format-extra-args
++ccflags-y += -D__KERNEL__ -DMODULE -DNVRM -DNV_VERSION_STRING=\"470.256.02\" -Wno-unused-function -Wuninitialized -fno-strict-aliasing -mno-red-zone -mcmodel=kernel -DNV_UVM_ENABLE
++ccflags-y += $(call cc-option,-Werror=undef,)
++ccflags-y += -DNV_SPECTRE_V2=$(NV_SPECTRE_V2)
++ccflags-y += -DNV_KERNEL_INTERFACE_LAYER
+
+ #
+ # Detect SGI UV systems and apply system-specific optimizations.
+ #
+
+ ifneq ($(wildcard /proc/sgi_uv),)
+- EXTRA_CFLAGS += -DNV_CONFIG_X86_UV
++ ccflags-y += -DNV_CONFIG_X86_UV
+ endif
+
+
+@@ -107,7 +100,7 @@ NV_CONFTEST_CMD := /bin/sh $(NV_CONFTEST_SCRIPT) \
+
+ NV_CFLAGS_FROM_CONFTEST := $(shell $(NV_CONFTEST_CMD) build_cflags)
+
+-NV_CONFTEST_CFLAGS = $(NV_CFLAGS_FROM_CONFTEST) $(EXTRA_CFLAGS) -fno-pie
++NV_CONFTEST_CFLAGS = $(NV_CFLAGS_FROM_CONFTEST) $(ccflags-y) -fno-pie
+
+ NV_CONFTEST_COMPILE_TEST_HEADERS := $(obj)/conftest/macros.h
+ NV_CONFTEST_COMPILE_TEST_HEADERS += $(obj)/conftest/functions.h
+diff --git a/common/inc/nv-mm.h b/common/inc/nv-mm.h
+index da5065d..1960ce5 100644
+--- a/common/inc/nv-mm.h
++++ b/common/inc/nv-mm.h
+@@ -31,6 +31,7 @@ typedef int vm_fault_t;
+
+ #include <linux/mm.h>
+ #include <linux/sched.h>
++#include <linux/version.h>
+ /* get_user_pages
+ *
+ * The 8-argument version of get_user_pages was deprecated by commit
+@@ -248,12 +249,28 @@ static inline struct rw_semaphore *nv_mmap_get_lock(struct mm_struct *mm)
+ #if defined(NV_VM_AREA_STRUCT_HAS_CONST_VM_FLAGS)
+ static inline void nv_vm_flags_set(struct vm_area_struct *vma, vm_flags_t flags)
+ {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0)
++ // Rel. commit "mm: uninline the main body of vma_start_write()" (Suren Baghdasaryan, 13 Feb 2025)
++ // Since Linux 6.15, vm_flags_set and vm_flags_clear call a GPL-only symbol
++ // for locking (__vma_start_write), which can't be called from non-GPL code.
++ // However, it appears all uses on the driver are on VMAs being initially
++ // mapped / which are already locked, so we can use vm_flags_reset, which
++ // doesn't lock the VMA, but rather just asserts it is already write-locked.
++ vm_flags_reset(vma, vma->vm_flags | flags);
++#else
+ vm_flags_set(vma, flags);
++#endif
+ }
+
+ static inline void nv_vm_flags_clear(struct vm_area_struct *vma, vm_flags_t flags)
+ {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0)
++ // Rel. commit "mm: uninline the main body of vma_start_write()" (Suren Baghdasaryan, 13 Feb 2025)
++ // See above
++ vm_flags_reset(vma, vma->vm_flags & ~flags);
++#else
+ vm_flags_clear(vma, flags);
++#endif
+ }
+ #else
+ static inline void nv_vm_flags_set(struct vm_area_struct *vma, unsigned long flags)
+diff --git a/common/inc/nv-timer.h b/common/inc/nv-timer.h
+index 18df6ea..396e121 100644
+--- a/common/inc/nv-timer.h
++++ b/common/inc/nv-timer.h
+@@ -25,6 +25,7 @@
+
+ #include <linux/timer.h>
+ #include <linux/kernel.h> // For container_of
++#include <linux/version.h>
+
+ #include "conftest.h"
+
+@@ -63,4 +64,13 @@ static inline void nv_timer_setup(struct nv_timer *nv_timer,
+ #endif
+ }
+
++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 2, 0)
++// Rel. commit "treewide: Switch/rename to timer_delete[_sync]()" (Thomas Gleixner, 5 Apr 2025)
++// This provides a shim for ancient kernels before timer_delete_sync was introduced
++static inline int timer_delete_sync(struct timer_list *timer)
++{
++ return del_timer_sync(timer);
++}
++#endif
++
+ #endif // __NV_TIMER_H__
+diff --git a/nvidia-drm/nvidia-drm-connector.c b/nvidia-drm/nvidia-drm-connector.c
+index fe838ef..c35c9ec 100644
+--- a/nvidia-drm/nvidia-drm-connector.c
++++ b/nvidia-drm/nvidia-drm-connector.c
+@@ -44,6 +44,8 @@
+ #include <drm/drm_atomic_helper.h>
+ #include <drm/drm_edid.h>
+
++#include <linux/version.h>
++
+ static void nv_drm_connector_destroy(struct drm_connector *connector)
+ {
+ struct nv_drm_connector *nv_connector = to_nv_connector(connector);
+@@ -302,8 +304,14 @@ static int nv_drm_connector_get_modes(struct drm_connector *connector)
+ return count;
+ }
+
++// Rel. commit. "drm/connector: make mode_valid take a const struct drm_display_mode" (Dmitry Baryshkov, 14 Dec 2024)
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0)
++static int nv_drm_connector_mode_valid(struct drm_connector *connector,
++ const struct drm_display_mode *mode)
++#else
+ static int nv_drm_connector_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
++#endif
+ {
+ struct drm_device *dev = connector->dev;
+ struct nv_drm_device *nv_dev = to_nv_device(dev);
+diff --git a/nvidia-drm/nvidia-drm-linux.c b/nvidia-drm/nvidia-drm-linux.c
+index 94e463e..2319640 100644
+--- a/nvidia-drm/nvidia-drm-linux.c
++++ b/nvidia-drm/nvidia-drm-linux.c
+@@ -182,6 +182,7 @@ static void __exit nv_linux_drm_exit(void)
+ module_init(nv_linux_drm_init);
+ module_exit(nv_linux_drm_exit);
+
++MODULE_DESCRIPTION("NVIDIA GPU DRM kernel module");
+ #if defined(MODULE_LICENSE)
+
+
+diff --git a/nvidia-modeset/nvidia-modeset-linux.c b/nvidia-modeset/nvidia-modeset-linux.c
+index de0c748..f6810d2 100644
+--- a/nvidia-modeset/nvidia-modeset-linux.c
++++ b/nvidia-modeset/nvidia-modeset-linux.c
+@@ -718,7 +718,7 @@ static void nvkms_kthread_q_callback(void *arg)
+ * pending timers and than waiting for workqueue callbacks.
+ */
+ if (timer->kernel_timer_created) {
+- del_timer_sync(&timer->kernel_timer);
++ timer_delete_sync(&timer->kernel_timer);
+ }
+
+ /*
+@@ -1740,7 +1740,7 @@ restart:
+ * completion, and we wait for queue completion with
+ * nv_kthread_q_stop below.
+ */
+- if (del_timer_sync(&timer->kernel_timer) == 1) {
++ if (timer_delete_sync(&timer->kernel_timer) == 1) {
+ /* We've deactivated timer so we need to clean after it */
+ list_del(&timer->timers_list);
+
+@@ -1778,6 +1778,7 @@ restart:
+ module_init(nvkms_init);
+ module_exit(nvkms_exit);
+
++MODULE_DESCRIPTION("NVIDIA GPU modeset kernel module");
+ #if defined(MODULE_LICENSE)
+
+
+diff --git a/nvidia-uvm/uvm.c b/nvidia-uvm/uvm.c
+index 73ceb70..c1e734f 100644
+--- a/nvidia-uvm/uvm.c
++++ b/nvidia-uvm/uvm.c
+@@ -1129,6 +1129,7 @@ static void __exit uvm_exit_entry(void)
+ module_init(uvm_init_entry);
+ module_exit(uvm_exit_entry);
+
++MODULE_DESCRIPTION("NVIDIA GPU UVM kernel module");
+ MODULE_LICENSE("Dual MIT/GPL");
+ MODULE_INFO(supported, "external");
+
+diff --git a/nvidia/nv-frontend.c b/nvidia/nv-frontend.c
+index 4d6d8af..ad82d6b 100644
+--- a/nvidia/nv-frontend.c
++++ b/nvidia/nv-frontend.c
+@@ -13,6 +13,7 @@
+ #include "nv-reg.h"
+ #include "nv-frontend.h"
+
++MODULE_DESCRIPTION("NVIDIA GPU frontend kernel module");
+ #if defined(MODULE_LICENSE)
+
+
+diff --git a/nvidia/nv.c b/nvidia/nv.c
+index 9d7da39..57b5024 100644
+--- a/nvidia/nv.c
++++ b/nvidia/nv.c
+@@ -3838,7 +3838,7 @@ int NV_API_CALL nv_stop_rc_timer(
+
+ nv_printf(NV_DBG_INFO, "NVRM: stopping rc timer\n");
+ nv->rc_timer_enabled = 0;
+- del_timer_sync(&nvl->rc_timer.kernel_timer);
++ timer_delete_sync(&nvl->rc_timer.kernel_timer);
+ nv_printf(NV_DBG_INFO, "NVRM: rc timer stopped\n");
+
+ return 0;
+@@ -3882,7 +3882,7 @@ void NV_API_CALL nv_stop_snapshot_timer(void)
+ NV_SPIN_UNLOCK_IRQRESTORE(&nvl->snapshot_timer_lock, flags);
+
+ if (timer_active)
+- del_timer_sync(&nvl->snapshot_timer.kernel_timer);
++ timer_delete_sync(&nvl->snapshot_timer.kernel_timer);
+ }
+
+ void NV_API_CALL nv_flush_snapshot_timer(void)
+--
+2.49.0
+