在 Ubuntu 20.04 中为 GTX 560 Ti 安装 Nvidia 驱动程序时,如何修复客户端版本和内核模块版本之间的 "NVRM: API mismatch"?

How to fix "NVRM: API mismatch" between client version and kernel module version when installing Nvidia drivers for a GTX 560 Ti in Ubuntu 20.04?

在 Intel Core i5 12600K PC 上添加 GTX 560 Ti 后,我安装了 nvidia-driver-390 运行宁 Kubuntu 20.04 LTS。

重新启动后出现以下错误:

$ dmesg|grep -i nvrm -A3
[  113.647054] NVRM: API mismatch: the client has the version 460.91.03, but
               NVRM: this kernel module has the version 390.144.  Please
               NVRM: make sure that this kernel module and all NVIDIA driver
               NVRM: components have the same version.

如何将该客户端版本设置为 390.144?

较新的驱动程序,例如 nvidia-driver-460 似乎不支持此显卡。我也收到警告:

$ ubuntu-drivers devices
WARNING:root:_pkg_get_support nvidia-driver-390: package has invalid Support Legacyheader, cannot determine support level
== /sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0 ==
modalias : pci:v000010DEd00001200sv00001043sd000083ACbc03sc00i00
vendor   : NVIDIA Corporation
model    : GF114 [GeForce GTX 560 Ti]
driver   : nvidia-340 - distro non-free
driver   : nvidia-driver-390 - distro non-free recommended
driver   : xserver-xorg-video-nouveau - distro free builtin

我 运行 更新的 内核 以便与 Intel 2.5G 以太网 IGC 驱动程序联网。我可以启动到内核 5.4.0.91-generic,但那时我就没有网络了。

$ uname -a
Linux Kairos 5.13.0-22-generic #22~20.04.1-Ubuntu SMP Tue Nov 9 15:07:24 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

此外,dkms 给出:

$ dkms status
nvidia, 390.144, 5.13.0-22-generic, x86_64: installed
nvidia, 390.144, 5.4.0-91-generic, x86_64: built

/var/lib/dkms/ 显示:

$ tree /var/lib/dkms/
/var/lib/dkms/
├── dkms_dbversion
└── nvidia
    ├── 390.144
    │   ├── 5.13.0-22-generic
    │   │   └── x86_64
    │   │       ├── log
    │   │       │   └── make.log
    │   │       └── module
    │   │           ├── nvidia-drm.ko
    │   │           ├── nvidia.ko
    │   │           └── nvidia-modeset.ko
    │   ├── 5.4.0-91-generic
    │   │   └── x86_64
    │   │       ├── log
    │   │       │   └── make.log
    │   │       └── module
    │   │           ├── nvidia-drm.ko
    │   │           ├── nvidia.ko
    │   │           ├── nvidia-modeset.ko
    │   │           └── nvidia-uvm.ko
    │   └── source -> /usr/src/nvidia-390.144
    └── kernel-5.13.0-22-generic-x86_64 -> 390.144/5.13.0-22-generic/x86_64

12 directories, 10 files

modinfo nvidia returns:

filename:       /lib/modules/5.13.0-22-generic/updates/dkms/nvidia.ko
alias:          char-major-195-*
version:        390.144
supported:      external
license:        NVIDIA
srcversion:     D635B75826DE88984609590
alias:          pci:v000010DEd00000E00sv*sd*bc04sc80i00*
alias:          pci:v000010DEd*sv*sd*bc03sc02i00*
alias:          pci:v000010DEd*sv*sd*bc03sc00i00*
depends:        ipmi_msghandler
retpoline:      Y
name:           nvidia
vermagic:       5.13.0-22-generic SMP mod_unload modversions 
parm:           NVreg_Mobile:int
parm:           NVreg_ResmanDebugLevel:int
parm:           NVreg_RmLogonRC:int
parm:           NVreg_ModifyDeviceFiles:int
parm:           NVreg_DeviceFileUID:int
parm:           NVreg_DeviceFileGID:int
parm:           NVreg_DeviceFileMode:int
parm:           NVreg_UpdateMemoryTypes:int
parm:           NVreg_InitializeSystemMemoryAllocations:int
parm:           NVreg_UsePageAttributeTable:int
parm:           NVreg_MapRegistersEarly:int
parm:           NVreg_RegisterForACPIEvents:int
parm:           NVreg_CheckPCIConfigSpace:int
parm:           NVreg_EnablePCIeGen3:int
parm:           NVreg_EnableMSI:int
parm:           NVreg_TCEBypassMode:int
parm:           NVreg_UseThreadedInterrupts:int
parm:           NVreg_EnableStreamMemOPs:int
parm:           NVreg_EnableBacklightHandler:int
parm:           NVreg_RestrictProfilingToAdminUsers:int
parm:           NVreg_EnableUserNUMAManagement:int
parm:           NVreg_EnableIBMNPURelaxedOrderingMode:int
parm:           NVreg_MemoryPoolSize:int
parm:           NVreg_KMallocHeapMaxSize:int
parm:           NVreg_VMallocHeapMaxSize:int
parm:           NVreg_IgnoreMMIOCheck:int
parm:           NVreg_RegistryDwords:charp
parm:           NVreg_RegistryDwordsPerDevice:charp
parm:           NVreg_RmMsg:charp
parm:           NVreg_AssignGpus:charp

我找了很多关于如何升级驱动到最新版本的帖子,目前是495,但是并没有解决我的问题,那个版本不支持我的显卡。只有版本 390 有效,但后来我收到 API 不匹配错误。

我找到了解决方案,现在 Kubuntu 正常启动了。

在开始之前,我想确认加载的内核模块和新安装的独立模块文件之间的版本不匹配。用户ladar showed in his 认为以下将证实这个问题

$ cat /proc/driver/nvidia/version
$ cat /sys/module/nvidia/version

首先,我清除了所有驱动程序和库

$ sudo apt purge nvidia-* && sudo apt purge libnvidia-*

然后我检查了是否没有安装任何nvidia驱动程序。以下没有return任何东西,应该

$ dpkg -l nvidia-*|grep ^ii

然后我从 Geforce GTX 560 Ti 下载了正确版本的驱动程序 https://www.nvidia.com/Download/driverResults.aspx/177153/en-us. You should select your driver from https://www.nvidia.com/Download/index.aspx?lang=en-us.

之后我重新启动进入终端

$ sudo init 3

我在命令行登录,然后进入我刚刚下载驱动程序的目录,然后更改权限和运行安装文件(它可能会问一些配置问题),然后重新启动

$ cd $HOME/Downloads/Nvidia/
$ chmod a+x NVIDIA-Linux-x86_64-390.144.run
$ sudo ./NVIDIA-Linux-x86_64-390.144.run 
$ sudo reboot

我现在拥有正常的 SSDM 登录屏幕,并且在登录后我的双屏幕都具有正确的分辨率。

我 运行 遇到了这个问题,但它与 CUDA(某些系统上未安装)无关。在我的系统上,内核模块被嵌入到压缩的内核映像中,然后在引导过程的早期加载。这些嵌入式但过时的模块将阻止加载正确的新 installed/compiled 独立模块文件。您可以轻松确认此问题。检查以下内容:

cat /proc/driver/nvidia/version
cat /sys/module/nvidia/version

如果加载的模块与驱动程序版本不匹配,您也可能会遇到此问题。假设正确的内核模块可用,您可以通过 运行ning 确认(假设您的发行版使用 DKMS):

dkms status

对我来说,修复只涉及重新生成我的内核映像。在 Red Hat 发行版及其衍生产品(Fedora、CentOS、Alma、Rocky、Oracle 等)上,您可以 运行:

(rpm -q --qf="%{VERSION}-%{RELEASE}.%{ARCH}\n" --whatprovides kernel ; uname -r) | \
sort | uniq | while read KERNEL ; do 
  dracut -f "/boot/initramfs-${KERNEL}.img" "${KERNEL}" || exit 1
done

这将为每个已安装的内核重新生成映像。对于 Debian 发行版及其衍生版本(包括 Ubuntu)的等效逻辑,您可以 运行:

for kernel in /boot/config-*; do 
  [ -f "$kernel" ] || continue
  KERNEL=${kernel#*-}
  mkinitramfs -o "/boot/initrd.img-${KERNEL}.img" "${KERNEL}" || exit 1
done

然后重启。您也可以临时解决问题,方法是使用 rmmod 或 modprobe 手动删除(卸载)NVIDIA 模块,然后重新加载它们。当你这样做时,modprobe 将使用独立的内核模块,它应该与你安装的驱动程序版本相匹配。

P.S。当我从 470.x 驱动程序升级到 510.x 驱动程序时遇到了这个问题,该驱动程序最近成为推荐的稳定安装版本。在使用 460.x 和 470.x 驱动程序版本时,我从未 运行 遇到过这个问题。

P.P.S。编辑 - 回顾命令:

# Red Hat Distros
dracut --regenerate-all --force

# Debian Distros
update-initramfs -u -k all

比我最初发布的需要更少的输入,并且应该适合大多数人。