Skip to content

Instantly share code, notes, and snippets.

@joanbm
Last active November 8, 2024 22:05
Show Gist options
  • Save joanbm/a6d3f7f873a60dec0aa4a734c0f1d64e to your computer and use it in GitHub Desktop.
Save joanbm/a6d3f7f873a60dec0aa4a734c0f1d64e to your computer and use it in GitHub Desktop.
Tentative fix for NVIDIA 470.256.02 driver for Linux 6.12-rc1
From 839b964bd5be20275a4d1add020e68e407380adb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Joan=20Bruguera=20Mic=C3=B3?= <[email protected]>
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
@joanbm
Copy link
Author

joanbm commented Sep 28, 2024

Note that this applies on top of all the other patches that are already required for Linux 6.11 support - see patches 1, 2, 3, 4 from nvidia-470xx-dkms from AUR.

@xtexChooser
Copy link

#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);

Use a goto branch so that DRM device can be free on failure?

@xtexChooser
Copy link

@joanbm
Copy link
Author

joanbm commented Oct 2, 2024

Use a goto branch so that DRM device can be free on failure?

Oops, completely missed that, thanks for pointing this out @xtexChooser!

@Augusto7743
Copy link

Copying the file "nvidia-470xx-fix-linux-6.12.patch" to correct path what is the command to do an patch ?
patch executable is inside nvidia kernel driver path ?

@joanbm
Copy link
Author

joanbm commented Oct 26, 2024

[UPDATE] I noticed that my workaround for nv_drm_output_poll_changed requires DRM kernel mode setting (nvidia-drm.modeset=1 kernel parameter). For me this is fine and I'm not interested in finding some alternative way so I just added a note about that.

While testing this I also found that the failure handling code was still wrong and caused a double free when the nvidia-drm module was unloaded, I have updated the patch to fix that.

@joanbm
Copy link
Author

joanbm commented Oct 26, 2024

@Augusto7743 You need to patch the driver yourself before installing. The "quick and dirty" way to manually install the driver on Linux 6.12-rc's is as follows:

# Download and extract driver
curl "https://us.download.nvidia.com/XFree86/Linux-x86_64/470.256.02/NVIDIA-Linux-x86_64-470.256.02.run" > NVIDIA-Linux-x86_64-470.256.02.run
sh NVIDIA-Linux-x86_64-470.256.02.run --extract-only
cd NVIDIA-Linux-x86_64-470.256.02
# Download and apply patches
curl "https://aur.archlinux.org/cgit/aur.git/plain/0001-Fix-conftest-to-ignore-implicit-function-declaration.patch?h=nvidia-470xx-utils&id=df0426ab325cb0ad8909a3058d66336ce1f872ce" | patch -Np1 -d kernel
curl "https://aur.archlinux.org/cgit/aur.git/plain/0002-Fix-conftest-to-use-a-short-wchar_t.patch?h=nvidia-470xx-utils&id=df0426ab325cb0ad8909a3058d66336ce1f872ce" | patch -Np1 -d kernel
curl "https://aur.archlinux.org/cgit/aur.git/plain/0003-Fix-conftest-to-use-nv_drm_gem_vmap-which-has-the-se.patch?h=nvidia-470xx-utils&id=df0426ab325cb0ad8909a3058d66336ce1f872ce" | patch -Np1 -d kernel
curl "https://aur.archlinux.org/cgit/aur.git/plain/kernel-6.10.patch?h=nvidia-470xx-utils&id=df0426ab325cb0ad8909a3058d66336ce1f872ce" | patch -Np1 -d kernel
curl "https://gist.githubusercontent.com/joanbm/a6d3f7f873a60dec0aa4a734c0f1d64e/raw/6bae5606c033b6c6c08233523091992370e357b7/nvidia-470xx-fix-linux-6.12.patch" | patch -Np1 -d kernel
# Run the installer
sudo ./nvidia-installer 

However, note that this installs the driver outside of the distribution's package manager so it has some potential for causing conflicts. What I personally do in Arch Linux is take the PKGBUILD for the AUR package, modify it to apply the patch and rebuild the package. Generally speaking if you don't want to spend some time tinkering, it's better to wait for the update to be shipped by your distro's package manager.

@xtexChooser
Copy link

@joanbm Thanks for your careful testing!!

@Augusto7743
Copy link

Driver Version: 470.256.02 - Release Date: Tue Jun 04, 2024

Hello Joan. All good with you ?
Thanks very much for your good deeds helping Nvidia users using nvidia driver 470 and for replying my message.
I remember in driver 470 previous versions using your patch and had compiled and installed correctly with the current date kernel without any conflicts in Ubuntu 20.04.
After Nvidia had done driver updates allowing install the driver with kernel recent versions.
However Nvidia support for driver 470 has finished and the last version is
Driver Version: 470.256.02 - Release Date: Tue Jun 04, 2024
Nvidia has done an good support updating driver 470 for 10 years.

Now installed Ubuntu 24.04 with kernel 6.8 and the driver 470 last version is compatible without patch.
Now the problem begin ...
I had installed the kernel liquorix version 6.11 and used the commands below not being possible patch the driver.
I had renamed the patch file from "nvidia-470xx-fix-linux-6.12.patch" to "1.patch". Is problem doing it ?

./NVIDIA-Linux-x86_64-470.256.02.run -x
cd NVIDIA-Linux-x86_64-470.256.02
patch -p1 -i 1.patch

I not understand if the error was because that patch is for kernel 6.12 and I want patch in 6.11
I want share the errors messages below with you


patch -p1 -i 1.patch
can't find file to patch at input line 15
Perhaps you used the wrong -p or --strip option?
The text leading up to this was:

|From 97b7fa7b11024c53f9be828346097b2a5f54f375 Mon Sep 17 00:00:00 2001
|From: =?UTF-8?q?Joan=20Bruguera=20Mic=C3=B3?= [email protected]
|Date: Sat, 17 Aug 2024 14:26:04 +0000
|Subject: [PATCH] Tentative fix for NVIDIA 470.256.02 driver for Linux 6.12-rc1
|

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

|
|diff --git a/nvidia-drm/nvidia-drm-drv.c b/nvidia-drm/nvidia-drm-drv.c
|index f350134..2b17fd9 100644
|--- a/nvidia-drm/nvidia-drm-drv.c
|+++ b/nvidia-drm/nvidia-drm-drv.c

File to patch: 1.patch
patching file 1.patch
Hunk #1 FAILED at 84.
Hunk #2 FAILED at 168.
Hunk #3 FAILED at 739.
Hunk #4 FAILED at 906.
Hunk #5 FAILED at 967.
5 out of 5 hunks FAILED -- saving rejects to file 1.patch.rej


The file 1.patch.rej inside is below


--- nvidia-drm/nvidia-drm-drv.c
+++ 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.
    @@ -967,8 +992,27 @@ static 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);

Try update the kernel with new version from ubuntu mainline not is solution because the kernel files not are signed.
Perhaps wait for Ubuntu repositories update the driver 470 not is an good solution because the link below is related with driver repositories and driver 470 not has any update for an long time.
https://launchpad.net/~graphics-drivers/+archive/ubuntu/ppa
The solution continue being your good deed with patches.
I when install the kernel 6.12 or above will try again patch the driver with the information from your reply above.

You are an man blessed ... All good for you in your life.
Have an nice week.

@joanbm
Copy link
Author

joanbm commented Oct 30, 2024

Hi @Augusto7743,

You do not need this patch for the v6.11 kernel. Instead, you need the other 4 patches I linked above (1, 2, 3, 4). The patches are not consolidated but rather incremental.

Regarding the error you get, you are applying the patches in the wrong folder. The patches apply inside the "kernel" folder inside the extracted files. If you do something like the commands from my previous comments it should work.

Regards.

@Augusto7743
Copy link

I have done na test and the driver was patched correctly.
Thanks for your reply helping !
Now the next step ... try find an Linux kernel current version in file format deb for simple install in Ubuntu 24.04.
Ubuntu mainline kernels not are signed. When installing some softwares not make new modules using dkms because the kernel is unsigned.

All good and good luck in your path ... You have all it !

@Augusto7743
Copy link

I have patched and tested in kernel liquorix 6.11 and all works corectly.
Not any issues.
THANKS VERY MUCH !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment