From d9c29dc72db55db98c2430dc3783835ef881da5e Mon Sep 17 00:00:00 2001
From: Peter Jung <admin@ptr1337.dev>
Date: Fri, 18 Oct 2024 22:42:42 +0200
Subject: [PATCH 4/7] Fix for 6.12.0-rc1
 drm_mode_config_funcs.output_poll_changed removal

Tentative fix for NVIDIA 560.35.03 driver for Linux 6.12-rc1.

Based on https://gist.github.com/joanbm/a6d3f7f873a60dec0aa4a734c0f1d64e

Signed-off-by: Peter Jung <admin@ptr1337.dev>
---
 kernel-open/nvidia-drm/nvidia-drm-drv.c | 48 +++++++++++++++++++++++--
 1 file changed, 45 insertions(+), 3 deletions(-)

diff --git a/kernel-open/nvidia-drm/nvidia-drm-drv.c b/kernel-open/nvidia-drm/nvidia-drm-drv.c
index 8cb94219..c82feef6 100644
--- a/kernel-open/nvidia-drm/nvidia-drm-drv.c
+++ b/kernel-open/nvidia-drm/nvidia-drm-drv.c
@@ -100,6 +100,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 int nv_drm_revoke_modeset_permission(struct drm_device *dev,
                                             struct drm_file *filep,
                                             NvU32 dpyId);
@@ -147,7 +152,7 @@ static char* nv_get_transfer_function_name(
 
 #if defined(NV_DRM_ATOMIC_MODESET_AVAILABLE)
 
-#if defined(NV_DRM_OUTPUT_POLL_CHANGED_PRESENT)
+//#if defined(NV_DRM_OUTPUT_POLL_CHANGED_PRESENT)
 static void nv_drm_output_poll_changed(struct drm_device *dev)
 {
     struct drm_connector *connector = NULL;
@@ -191,7 +196,7 @@ static void nv_drm_output_poll_changed(struct drm_device *dev)
     nv_drm_connector_list_iter_end(&conn_iter);
 #endif
 }
-#endif /* NV_DRM_OUTPUT_POLL_CHANGED_PRESENT */
+//#endif /* NV_DRM_OUTPUT_POLL_CHANGED_PRESENT */
 
 static struct drm_framebuffer *nv_drm_framebuffer_create(
     struct drm_device *dev,
@@ -229,7 +234,7 @@ static const struct drm_mode_config_funcs nv_mode_config_funcs = {
     .atomic_check  = nv_drm_atomic_check,
     .atomic_commit = nv_drm_atomic_commit,
 
-    #if defined(NV_DRM_OUTPUT_POLL_CHANGED_PRESENT)
+    #if LINUX_VERSION_CODE < KERNEL_VERSION(6, 12, 0)
     .output_poll_changed = nv_drm_output_poll_changed,
     #endif
 };
@@ -1711,6 +1716,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[] = {
@@ -1939,6 +1948,20 @@ void nv_drm_update_drm_driver_features(void)
 }
 
 
+#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.
@@ -2029,8 +2052,27 @@ void nv_drm_register_drm_device(const nv_gpu_info_t *gpu_info)
     nv_dev->next = dev_list;
     dev_list = nv_dev;
 
+#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.");
+        goto failed_drm_client_init;
+    }
+
+    drm_client_register(client);
+    pr_info("Registered the nv-hotplug-helper DRM client.");
+#endif
+
     return; /* Success */
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
+failed_drm_client_init:
+
+    kfree(client);
+#endif
+
 failed_drm_register:
 
     nv_drm_dev_free(dev);
-- 
2.47.0

