git: cbbce9a123da - main - x11/nvidia-driver-470: Backport fix for nvidia-modeset panic

From: Gleb Popov <arrowd_at_FreeBSD.org>
Date: Fri, 22 Mar 2024 17:39:48 UTC
The branch main has been updated by arrowd:

URL: https://cgit.FreeBSD.org/ports/commit/?id=cbbce9a123da84852f289ba5aa53b4955b53a2dd

commit cbbce9a123da84852f289ba5aa53b4955b53a2dd
Author:     Austin Shafer <ashafer@badland.io>
AuthorDate: 2024-03-22 16:26:58 +0000
Commit:     Gleb Popov <arrowd@FreeBSD.org>
CommitDate: 2024-03-22 17:38:25 +0000

    x11/nvidia-driver-470: Backport fix for nvidia-modeset panic
    
    PR: 274519
    
    Differential Revision: https://reviews.freebsd.org/D44432
---
 x11/nvidia-driver-470/Makefile                     |   2 +-
 ...tch-src_nvidia-modeset_nvidia-modeset-freebsd.c | 102 +++++++++++++++++++--
 2 files changed, 94 insertions(+), 10 deletions(-)

diff --git a/x11/nvidia-driver-470/Makefile b/x11/nvidia-driver-470/Makefile
index 0c822fabda57..c2690453a1a8 100644
--- a/x11/nvidia-driver-470/Makefile
+++ b/x11/nvidia-driver-470/Makefile
@@ -1,6 +1,6 @@
 DISTVERSION=	470.161.03
 # Explicitly set PORTREVISION as it can be overridden by the master port
-PORTREVISION=	0
+PORTREVISION=	1
 
 MASTERDIR=	${.CURDIR}/../nvidia-driver
 PKGNAMESUFFIX=	-470
diff --git a/x11/nvidia-driver/files/460-patch-src_nvidia-modeset_nvidia-modeset-freebsd.c b/x11/nvidia-driver/files/460-patch-src_nvidia-modeset_nvidia-modeset-freebsd.c
index 3b39dcd424db..767174b9074b 100644
--- a/x11/nvidia-driver/files/460-patch-src_nvidia-modeset_nvidia-modeset-freebsd.c
+++ b/x11/nvidia-driver/files/460-patch-src_nvidia-modeset_nvidia-modeset-freebsd.c
@@ -1,6 +1,6 @@
---- src/nvidia-modeset/nvidia-modeset-freebsd.c.orig	2018-08-21 23:09:28 UTC
+--- src/nvidia-modeset/nvidia-modeset-freebsd.c.orig	2024-03-11 15:49:45 UTC
 +++ src/nvidia-modeset/nvidia-modeset-freebsd.c
-@@ -25,6 +25,7 @@
+@@ -27,6 +27,7 @@
  #include <sys/file.h>
  #include <sys/proc.h>
  #include <sys/stack.h>
@@ -8,7 +8,7 @@
  
  #include "nvkms-ioctl.h"
  #include "nvidia-modeset-os-interface.h"
-@@ -48,6 +49,7 @@
+@@ -52,6 +53,7 @@
      #include "machine/../linux32/linux32_proto.h"
    #endif
    #include <compat/linux/linux_ioctl.h>
@@ -16,9 +16,9 @@
  #endif
  
  
-@@ -252,7 +254,12 @@ struct nvkms_ref_ptr {
+@@ -280,7 +282,12 @@ struct nvkms_ref_ptr* nvkms_alloc_ref_ptr(void *ptr)
  
- struct nvkms_ref_ptr* NVKMS_API_CALL nvkms_alloc_ref_ptr(void *ptr)
+ struct nvkms_ref_ptr* nvkms_alloc_ref_ptr(void *ptr)
  {
 -    struct nvkms_ref_ptr *ref_ptr = nvkms_alloc(sizeof(*ref_ptr), NV_FALSE);
 +    /*
@@ -30,7 +30,46 @@
      if (ref_ptr) {
          mtx_init(&ref_ptr->lock, "nvkms-ref-ptr-lock", NULL, MTX_SPIN);
          // The ref_ptr owner counts as a reference on the ref_ptr itself.
-@@ -867,29 +869,31 @@ static int nvkms_poll(
+@@ -371,7 +378,7 @@ static struct {
+  * Global list with pending timers, any change requires acquiring lock
+  */
+ static struct {
+-    struct sx lock;
++    struct mtx lock;
+     LIST_HEAD(nvkms_timers_head, nvkms_timer_t) list;
+ } nvkms_timers;
+ 
+@@ -384,9 +391,9 @@ static void nvkms_taskqueue_callback(void *arg, int pe
+      * We can delete this timer from pending timers list - it's being
+      * processed now.
+      */
+-    sx_xlock(&nvkms_timers.lock);
++    mtx_lock_spin(&nvkms_timers.lock);
+     LIST_REMOVE(timer, timers_list);
+-    sx_xunlock(&nvkms_timers.lock);
++    mtx_unlock_spin(&nvkms_timers.lock);
+ 
+     /*
+      * After taskqueue_callback we want to be sure that callout_callback
+@@ -454,7 +461,7 @@ nvkms_init_timer(struct nvkms_timer_t *timer, nvkms_ti
+      * run in parallel with this, it could race against nvkms_init_timer()
+      * and free the timer before its initialization is complete.
+      */
+-    sx_xlock(&nvkms_timers.lock);
++    mtx_lock_spin(&nvkms_timers.lock);
+     LIST_INSERT_HEAD(&nvkms_timers.list, timer, timers_list);
+ 
+     if (usec == 0) {
+@@ -468,7 +475,7 @@ nvkms_init_timer(struct nvkms_timer_t *timer, nvkms_ti
+                       NVKMS_USECS_TO_TICKS(usec),
+                       nvkms_callout_callback, (void *) timer);
+     }
+-    sx_xunlock(&nvkms_timers.lock);
++    mtx_unlock_spin(&nvkms_timers.lock);
+ }
+ 
+ nvkms_timer_handle_t*
+@@ -916,29 +923,31 @@ static int nvkms_poll(
   *************************************************************************/
  
  #if defined(NVKMS_SUPPORT_LINUX_COMPAT)
@@ -77,7 +116,7 @@
  }
  
  #define NVKMS_LINUX_IOCTL_MIN _IOC(0, NVKMS_IOCTL_MAGIC, NVKMS_IOCTL_CMD, 0)
-@@ -909,6 +909,7 @@ static struct linux_ioctl_handler nvkms_linux_ioctl_ha
+@@ -954,6 +963,7 @@ static void nvkms_linux_compat_load(void)
  static void nvkms_linux_compat_load(void)
  {
  #if defined(NVKMS_SUPPORT_LINUX_COMPAT)
@@ -85,7 +124,7 @@
      linux_ioctl_register_handler(&nvkms_linux_ioctl_handler);
  #endif
  }
-@@ -917,6 +918,7 @@ static void nvkms_linux_compat_unload(void)
+@@ -962,6 +972,7 @@ static void nvkms_linux_compat_unload(void)
  {
  #if defined(NVKMS_SUPPORT_LINUX_COMPAT)
      linux_ioctl_unregister_handler(&nvkms_linux_ioctl_handler);
@@ -93,7 +132,52 @@
  #endif
  }
  
-@@ -1100,4 +1102,9 @@ MODULE_DEPEND(nvidia_modeset,               /* module 
+@@ -1011,7 +1022,7 @@ nvidia_modeset_loader(struct module *m, int what, void
+         nvkms_module.is_unloading = NV_FALSE;
+ 
+         LIST_INIT(&nvkms_timers.list);
+-        sx_init(&nvkms_timers.lock, "nvidia-modeset timer lock");
++        mtx_init(&nvkms_timers.lock, "nvidia-modeset timer lock", NULL, MTX_SPIN);
+ 
+         nvkms_dev = make_dev(&nvkms_cdevsw,
+                              NVKMS_CDEV_MINOR,
+@@ -1020,7 +1031,7 @@ nvidia_modeset_loader(struct module *m, int what, void
+ 
+         if (nvkms_dev == NULL) {
+             sx_destroy(&nvkms_module.lock);
+-            sx_destroy(&nvkms_timers.lock);
++            mtx_destroy(&nvkms_timers.lock);
+             sx_destroy(&nvkms_lock);
+ 
+             nvkms_free_rm();
+@@ -1089,7 +1100,7 @@ nvidia_modeset_loader(struct module *m, int what, void
+          * nvkms_taskqueue_callback() doesn't get called after the
+          * module is unloaded.
+          */
+-        sx_xlock(&nvkms_timers.lock);
++        mtx_lock_spin(&nvkms_timers.lock);
+ 
+         LIST_FOREACH_SAFE(timer, &nvkms_timers.list, timers_list, tmp) {
+             if (timer->callout_created) {
+@@ -1111,7 +1122,7 @@ nvidia_modeset_loader(struct module *m, int what, void
+             }
+         }
+ 
+-        sx_xunlock(&nvkms_timers.lock);
++        mtx_unlock_spin(&nvkms_timers.lock);
+ 
+         taskqueue_run(taskqueue_nvkms);
+ 
+@@ -1119,7 +1130,7 @@ nvidia_modeset_loader(struct module *m, int what, void
+         nvkms_dev = NULL;
+ 
+         sx_destroy(&nvkms_module.lock);
+-        sx_destroy(&nvkms_timers.lock);
++        mtx_destroy(&nvkms_timers.lock);
+         sx_destroy(&nvkms_lock);
+ 
+         nvkms_free_rm();
+@@ -1151,4 +1162,9 @@ MODULE_DEPEND(nvidia_modeset,               /* module 
  MODULE_DEPEND(nvidia_modeset,               /* module name */
                linux,                        /* prerequisite module */
                1, 1, 1);                     /* vmin, vpref, vmax */