summarylogtreecommitdiffstats
path: root/kernel-6.12.patch
blob: 9f1497aaf8bb9e68fc0ecfad9385eaf1595c2cfe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
From 839b964bd5be20275a4d1add020e68e407380adb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Joan=20Bruguera=20Mic=C3=B3?= <joanbrugueram@gmail.com>
Date: Sat, 17 Aug 2024 14:26:04 +0000
Subject: [PATCH] Tentative fix for NVIDIA 470.256.02 driver for Linux 6.12-rc1

Note that the fix requires enabling DRM kernel mode setting
(add the `nvidia-drm.modeset=1` parameter to the kernel command line).

(Thanks xtexChooser for the memory management fixes!)
---
 nvidia-drm/nvidia-drm-drv.c | 47 +++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/nvidia-drm/nvidia-drm-drv.c b/nvidia-drm/nvidia-drm-drv.c
index f350134..d6233a5 100644
--- a/nvidia-drm/nvidia-drm-drv.c
+++ b/nvidia-drm/nvidia-drm-drv.c
@@ -84,6 +84,11 @@
 #include <drm/drm_atomic_helper.h>
 #endif
 
+#include <linux/version.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
+#include <drm/drm_client.h>
+#endif
+
 static struct nv_drm_device *dev_list = NULL;
 
 #if defined(NV_DRM_ATOMIC_MODESET_AVAILABLE)
@@ -168,7 +173,12 @@ static const struct drm_mode_config_funcs nv_mode_config_funcs = {
     .atomic_check  = nv_drm_atomic_check,
     .atomic_commit = nv_drm_atomic_commit,
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 12, 0)
+    // Rel. commit. "drm: Remove struct drm_mode_config_funcs.output_poll_changed" (Thomas Zimmermann, 12 Aug 2024)
+    // Replace this callback with a DRM client's hotplug callback.
+    // This is required for e.g. /sys/class/drm/card*/modes to work.
     .output_poll_changed = nv_drm_output_poll_changed,
+#endif
 };
 
 static void nv_drm_event_callback(const struct NvKmsKapiEvent *event)
@@ -739,6 +749,10 @@ static const struct file_operations nv_drm_fops = {
     .read           = drm_read,
 
     .llseek         = noop_llseek,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
+    // Rel. commit. "fs: move FMODE_UNSIGNED_OFFSET to fop_flags" (Christian Brauner, 9 Aug 2024)
+    .fop_flags      = FOP_UNSIGNED_OFFSET,
+#endif
 };
 
 static const struct drm_ioctl_desc nv_drm_ioctls[] = {
@@ -906,7 +920,18 @@ static void nv_drm_update_drm_driver_features(void)
 #endif /* NV_DRM_ATOMIC_MODESET_AVAILABLE */
 }
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
+static int hotplug_helper_client_hotplug(struct drm_client_dev *client)
+{
+    nv_drm_output_poll_changed(client->dev);
+    return 0;
+}
 
+static const struct drm_client_funcs nv_hotplug_helper_client_funcs = {
+    .owner      = THIS_MODULE,
+    .hotplug    = hotplug_helper_client_hotplug,
+};
+#endif
 
 /*
  * Helper function for allocate/register DRM device for given NVIDIA GPU ID.
@@ -962,6 +987,20 @@ static void nv_drm_register_drm_device(const nv_gpu_info_t *gpu_info)
         goto failed_drm_register;
     }
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
+    /* Register a DRM client for receiving hotplug events */
+    struct drm_client_dev *client = kzalloc(sizeof(*client), GFP_KERNEL);
+    if (client == NULL || drm_client_init(dev, client,
+        "nv-hotplug-helper", &nv_hotplug_helper_client_funcs)) {
+        printk(KERN_WARNING "Failed to initialize the nv-hotplug-helper DRM client"
+            " (ensure DRM kernel mode setting is enabled via nvidia-drm.modeset=1).\n");
+        goto failed_drm_client_init;
+    }
+
+    drm_client_register(client);
+    pr_info("Registered the nv-hotplug-helper DRM client.\n");
+#endif
+
     /* Add NVIDIA-DRM device into list */
 
     nv_dev->next = dev_list;
@@ -969,6 +1008,14 @@ static void nv_drm_register_drm_device(const nv_gpu_info_t *gpu_info)
 
     return; /* Success */
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
+failed_drm_client_init:
+
+    kfree(client);
+    drm_dev_unregister(dev);
+
+#endif
+
 failed_drm_register:
 
     nv_drm_dev_free(dev);
-- 
2.47.0