Skip to content

Instantly share code, notes, and snippets.

@joanbm
Last active October 16, 2020 10:27
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joanbm/7438afd6126cf216b47f866355ed71d3 to your computer and use it in GitHub Desktop.
Save joanbm/7438afd6126cf216b47f866355ed71d3 to your computer and use it in GitHub Desktop.
NVIDIA 450.57/450.66 driver patch for Linux 5.9-rc1
Tentative patch for NVIDIA driver compatibility for Linux 5.9-rc1
NOTE: This allows the module to build and mostly work, but the nvidia-uvm
module won't load due to the new patch from Christoph Hellwig that
prevents modules to simultaneously link to GPL and proprietary symbols
(torvalds/linux commit 0fd9cc6b0c72245375520ffc8d97ce5857b63b94)
It seems to be non-trivial to fix this issue "for real" (workarounds not included)
---
diff --git a/common/inc/nv-mm.h b/common/inc/nv-mm.h
index b04ff67..fc9f67e 100644
--- a/common/inc/nv-mm.h
+++ b/common/inc/nv-mm.h
@@ -23,6 +23,7 @@
#ifndef __NV_MM_H__
#define __NV_MM_H__
+#include <linux/version.h>
#include "conftest.h"
#if !defined(NV_VM_FAULT_T_IS_PRESENT)
@@ -139,7 +140,16 @@ typedef int vm_fault_t;
if (force)
flags |= FOLL_FORCE;
- #if defined(NV_GET_USER_PAGES_REMOTE_HAS_LOCKED_ARG)
+/* torvalds/linux commit 64019a2e467a288a16b65ab55ddcbf58c1b00187
+ "After the cleanup of page fault accounting, gup does not need to pass
+ task_struct around any more. Remove that parameter in the whole gup
+ stack." */
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0))
+
+ return get_user_pages_remote(mm, start, nr_pages, flags,
+ pages, vmas, NULL);
+
+ #elif defined(NV_GET_USER_PAGES_REMOTE_HAS_LOCKED_ARG)
return get_user_pages_remote(tsk, mm, start, nr_pages, flags,
pages, vmas, NULL);
diff --git a/nvidia-drm/nvidia-drm-drv.c b/nvidia-drm/nvidia-drm-drv.c
index c6ba478..fd6333e 100644
--- a/nvidia-drm/nvidia-drm-drv.c
+++ b/nvidia-drm/nvidia-drm-drv.c
@@ -20,6 +20,7 @@
* DEALINGS IN THE SOFTWARE.
*/
+#include <linux/version.h>
#include "nvidia-drm-conftest.h" /* NV_DRM_AVAILABLE and NV_DRM_DRM_GEM_H_PRESENT */
#include "nvidia-drm-priv.h"
@@ -473,16 +474,36 @@ static void nv_drm_unload(struct drm_device *dev)
#if defined(NV_DRM_ATOMIC_MODESET_AVAILABLE)
+/* torvalds/linux commit 907f53200f982cd377e75abbc1b18ed624d7ae66
+ "The function always returns zero (success). Ideally we'll remove it all
+ together - although that's requires a little more work.
+
+ For now, we can drop the return type and simplify the drm core code
+ surrounding it." */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0))
static int nv_drm_master_set(struct drm_device *dev,
+#else
+static void nv_drm_master_set(struct drm_device *dev,
+#endif
struct drm_file *file_priv, bool from_open)
{
struct nv_drm_device *nv_dev = to_nv_device(dev);
+/* torvalds/linux commit 907f53200f982cd377e75abbc1b18ed624d7ae66
+ "The function always returns zero (success). Ideally we'll remove it all
+ together - although that's requires a little more work.
+
+ For now, we can drop the return type and simplify the drm core code
+ surrounding it." */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0))
if (!nvKms->grabOwnership(nv_dev->pDevice)) {
return -EINVAL;
}
return 0;
+#else
+ nvKms->grabOwnership(nv_dev->pDevice);
+#endif
}
#if defined(NV_DRM_MASTER_DROP_HAS_FROM_RELEASE_ARG)
@@ -719,7 +740,16 @@ static struct drm_driver nv_drm_driver = {
#endif
DRIVER_GEM | DRIVER_RENDER,
+/* torvalds/linux commit 0a19b068acc47d05212f03e494381926dc0381e2
+ Should work since NVIDIA does not use struct_mutex?
+ "- More struct_mutex removal for !legacy drivers:
+ - Remove gem_free_object()
+ - Removal of drm_gem_object_put_unlocked()." */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0))
.gem_free_object = nv_drm_gem_free,
+#else
+ .gem_free_object_unlocked = nv_drm_gem_free,
+#endif
.ioctls = nv_drm_ioctls,
.num_ioctls = ARRAY_SIZE(nv_drm_ioctls),
diff --git a/nvidia-drm/nvidia-drm-gem.c b/nvidia-drm/nvidia-drm-gem.c
index ad4bca4..e63d352 100644
--- a/nvidia-drm/nvidia-drm-gem.c
+++ b/nvidia-drm/nvidia-drm-gem.c
@@ -20,6 +20,7 @@
* DEALINGS IN THE SOFTWARE.
*/
+#include <linux/version.h>
#include "nvidia-drm-conftest.h"
#if defined(NV_DRM_AVAILABLE)
@@ -46,10 +47,17 @@
void nv_drm_gem_free(struct drm_gem_object *gem)
{
- struct drm_device *dev = gem->dev;
struct nv_drm_gem_object *nv_gem = to_nv_gem_object(gem);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0))
+/* torvalds/linux commit 0a19b068acc47d05212f03e494381926dc0381e2
+ Should work since NVIDIA does not use struct_mutex?
+ "- More struct_mutex removal for !legacy drivers:
+ - Remove gem_free_object()
+ - Removal of drm_gem_object_put_unlocked()." */
+ struct drm_device *dev = gem->dev;
WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+#endif
/* Cleanup core gem object */
diff --git a/nvidia-drm/nvidia-drm-gem.h b/nvidia-drm/nvidia-drm-gem.h
index 4e7ffd3..b5dd705 100644
--- a/nvidia-drm/nvidia-drm-gem.h
+++ b/nvidia-drm/nvidia-drm-gem.h
@@ -23,6 +23,7 @@
#ifndef __NVIDIA_DRM_GEM_H__
#define __NVIDIA_DRM_GEM_H__
+#include <linux/version.h>
#include "nvidia-drm-conftest.h"
#if defined(NV_DRM_AVAILABLE)
@@ -96,7 +97,16 @@ static inline void
nv_drm_gem_object_unreference_unlocked(struct nv_drm_gem_object *nv_gem)
{
#if defined(NV_DRM_GEM_OBJECT_GET_PRESENT)
+/* torvalds/linux commit 0a19b068acc47d05212f03e494381926dc0381e2
+ Should work since NVIDIA does not use struct_mutex?
+ "- More struct_mutex removal for !legacy drivers:
+ - Remove gem_free_object()
+ - Removal of drm_gem_object_put_unlocked()." */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0))
drm_gem_object_put_unlocked(&nv_gem->base);
+#else
+ drm_gem_object_put(&nv_gem->base);
+#endif
#else
drm_gem_object_unreference_unlocked(&nv_gem->base);
#endif
diff --git a/nvidia-drm/nvidia-drm-utils.c b/nvidia-drm/nvidia-drm-utils.c
index da485c6..a5d7a2a 100644
--- a/nvidia-drm/nvidia-drm-utils.c
+++ b/nvidia-drm/nvidia-drm-utils.c
@@ -20,6 +20,7 @@
* DEALINGS IN THE SOFTWARE.
*/
+#include <linux/version.h>
#include "nvidia-drm-conftest.h" /* NV_DRM_ATOMIC_MODESET_AVAILABLE */
#if defined(NV_DRM_ATOMIC_MODESET_AVAILABLE)
@@ -103,7 +104,13 @@ void
nvkms_display_mode_to_drm_mode(const struct NvKmsKapiDisplayMode *displayMode,
struct drm_display_mode *mode)
{
+/* torvalds/linux commit 0425662fdf05665235e768e2fbcb4ced12432b43
+ "Get rid of mode->vrefresh and just calculate it on demand. Saves
+ a bit of space and avoids the cached value getting out of sync
+ with reality." */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0))
mode->vrefresh = (displayMode->timings.refreshRate + 500) / 1000; /* In Hz */
+#endif
mode->clock = (displayMode->timings.pixelClockHz + 500) / 1000; /* In Hz */
@@ -159,7 +166,15 @@ nvkms_display_mode_to_drm_mode(const struct NvKmsKapiDisplayMode *displayMode,
void drm_mode_to_nvkms_display_mode(const struct drm_display_mode *src,
struct NvKmsKapiDisplayMode *dst)
{
+/* torvalds/linux commit 0425662fdf05665235e768e2fbcb4ced12432b43
+ "Get rid of mode->vrefresh and just calculate it on demand. Saves
+ a bit of space and avoids the cached value getting out of sync
+ with reality." */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0))
dst->timings.refreshRate = src->vrefresh * 1000;
+#else
+ dst->timings.refreshRate = drm_mode_vrefresh(src) * 1000;
+#endif
dst->timings.pixelClockHz = src->clock * 1000; /* In Hz */
diff --git a/nvidia-uvm/uvm8_tools.c b/nvidia-uvm/uvm8_tools.c
index 620e1cc..1aee896 100644
--- a/nvidia-uvm/uvm8_tools.c
+++ b/nvidia-uvm/uvm8_tools.c
@@ -20,6 +20,7 @@
DEALINGS IN THE SOFTWARE.
*******************************************************************************/
+#include <linux/version.h>
#include "uvm_common.h"
#include "uvm_ioctl.h"
#include "uvm8_gpu.h"
@@ -192,7 +193,15 @@ static uvm_tools_event_tracker_t *tools_event_tracker(struct file *filp)
{
long event_tracker = atomic_long_read((atomic_long_t *)&filp->private_data);
+/* torvalds/linux commit 145ff1ec090dce9beb5a9590b5dc288e7bb2e65d
+ "Removal of the tremendously unpopular read_barrier_depends()
+ barrier, which is a NOP on all architectures apart from Alpha, in
+ favour of allowing architectures to override READ_ONCE() and do
+ whatever dance they need to do to ensure address dependencies
+ provide LOAD -> LOAD/STORE ordering." */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0))
smp_read_barrier_depends();
+#endif
return (uvm_tools_event_tracker_t *)event_tracker;
}
diff --git a/nvidia-uvm/uvm8_va_range.h b/nvidia-uvm/uvm8_va_range.h
index 69cb0a0..edc21cc 100644
--- a/nvidia-uvm/uvm8_va_range.h
+++ b/nvidia-uvm/uvm8_va_range.h
@@ -24,6 +24,7 @@
#ifndef __UVM8_VA_RANGE_H__
#define __UVM8_VA_RANGE_H__
+#include <linux/version.h>
#include "uvm_linux.h"
#include "nv-kref.h"
#include "uvm_common.h"
@@ -755,7 +756,15 @@ static uvm_va_block_t *uvm_va_range_block(uvm_va_range_t *va_range, size_t index
// make sure that any initialization of this block by the creating thread is
// visible to later accesses in this thread, which requires a data
// dependency barrier.
+/* torvalds/linux commit 145ff1ec090dce9beb5a9590b5dc288e7bb2e65d
+ "Removal of the tremendously unpopular read_barrier_depends()
+ barrier, which is a NOP on all architectures apart from Alpha, in
+ favour of allowing architectures to override READ_ONCE() and do
+ whatever dance they need to do to ensure address dependencies
+ provide LOAD -> LOAD/STORE ordering." */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0))
smp_read_barrier_depends();
+#endif
return block;
}
diff --git a/nvidia/nv-pci.c b/nvidia/nv-pci.c
index 9a8a715..1e08a7c 100644
--- a/nvidia/nv-pci.c
+++ b/nvidia/nv-pci.c
@@ -8,6 +8,7 @@
* _NVRM_COPYRIGHT_END_
*/
+#include <linux/version.h>
#include "nv-pci-table.h"
#include "nv-pci.h"
#include "nv-ibmnpu.h"
@@ -424,7 +425,15 @@ nv_pci_probe
#if defined(CONFIG_VGA_ARB) && !defined(NVCPU_PPC64LE)
#if defined(VGA_DEFAULT_DEVICE)
+/* torvalds/linux commit f369bc3f9096f5d355e8b80540bc30ac9a602912
+ Does this make sense? What happened when vga_tryget failed (ret -EBUSY)? Should be interruptible?
+ "vgaarb: mark vga_tryget static
+ This symbols isn't used anywhere outside of vgaarb.c." */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0))
vga_tryget(VGA_DEFAULT_DEVICE, VGA_RSRC_LEGACY_MASK);
+#else
+ vga_get(VGA_DEFAULT_DEVICE, VGA_RSRC_LEGACY_MASK, 0);
+#endif
#endif
vga_set_legacy_decoding(pci_dev, VGA_RSRC_NONE);
#endif
@joanbm
Copy link
Author

joanbm commented Oct 16, 2020

PS: This is obsolete since NVIDIA has released new drivers that work on 5.9 (except the nvidia-uvm problem, which remains).

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