1{
2 config,
3 lib,
4 pkgs,
5 ...
6}: let
7 nvidiaEnabled = (lib.elem "nvidia" config.services.xserver.videoDrivers);
8 nvidia_x11 =
9 if nvidiaEnabled || cfg.datacenter.enable
10 then cfg.package
11 else null;
12
13 cfg = config.hardware.nvidia;
14
15 pCfg = cfg.prime;
16 syncCfg = pCfg.sync;
17 offloadCfg = pCfg.offload;
18 reverseSyncCfg = pCfg.reverseSync;
19 primeEnabled = syncCfg.enable || reverseSyncCfg.enable || offloadCfg.enable;
20 busIDType = lib.types.strMatching "([[:print:]]+[\:\@][0-9]{1,3}\:[0-9]{1,2}\:[0-9])?";
21 ibtSupport = cfg.open || (nvidia_x11.ibtSupport or false);
22 settingsFormat = pkgs.formats.keyValue {};
23in {
24 options = {
25 hardware.nvidia = {
26 datacenter.enable = lib.mkEnableOption (lib.mdDoc ''
27 Data Center drivers for NVIDIA cards on a NVLink topology
28 '');
29 datacenter.settings = lib.mkOption {
30 type = settingsFormat.type;
31 default = {
32 LOG_LEVEL=4;
33 LOG_FILE_NAME="/var/log/fabricmanager.log";
34 LOG_APPEND_TO_LOG=1;
35 LOG_FILE_MAX_SIZE=1024;
36 LOG_USE_SYSLOG=0;
37 DAEMONIZE=1;
38 BIND_INTERFACE_IP="127.0.0.1";
39 STARTING_TCP_PORT=16000;
40 FABRIC_MODE=0;
41 FABRIC_MODE_RESTART=0;
42 STATE_FILE_NAME="/var/tmp/fabricmanager.state";
43 FM_CMD_BIND_INTERFACE="127.0.0.1";
44 FM_CMD_PORT_NUMBER=6666;
45 FM_STAY_RESIDENT_ON_FAILURES=0;
46 ACCESS_LINK_FAILURE_MODE=0;
47 TRUNK_LINK_FAILURE_MODE=0;
48 NVSWITCH_FAILURE_MODE=0;
49 ABORT_CUDA_JOBS_ON_FM_EXIT=1;
50 TOPOLOGY_FILE_PATH=nvidia_x11.fabricmanager + "/share/nvidia-fabricmanager/nvidia/nvswitch";
51 };
52 defaultText = lib.literalExpression ''
53 {
54 LOG_LEVEL=4;
55 LOG_FILE_NAME="/var/log/fabricmanager.log";
56 LOG_APPEND_TO_LOG=1;
57 LOG_FILE_MAX_SIZE=1024;
58 LOG_USE_SYSLOG=0;
59 DAEMONIZE=1;
60 BIND_INTERFACE_IP="127.0.0.1";
61 STARTING_TCP_PORT=16000;
62 FABRIC_MODE=0;
63 FABRIC_MODE_RESTART=0;
64 STATE_FILE_NAME="/var/tmp/fabricmanager.state";
65 FM_CMD_BIND_INTERFACE="127.0.0.1";
66 FM_CMD_PORT_NUMBER=6666;
67 FM_STAY_RESIDENT_ON_FAILURES=0;
68 ACCESS_LINK_FAILURE_MODE=0;
69 TRUNK_LINK_FAILURE_MODE=0;
70 NVSWITCH_FAILURE_MODE=0;
71 ABORT_CUDA_JOBS_ON_FM_EXIT=1;
72 TOPOLOGY_FILE_PATH=nvidia_x11.fabricmanager + "/share/nvidia-fabricmanager/nvidia/nvswitch";
73 }
74 '';
75 description = lib.mdDoc ''
76 Additional configuration options for fabricmanager.
77 '';
78 };
79
80 powerManagement.enable = lib.mkEnableOption (lib.mdDoc ''
81 experimental power management through systemd. For more information, see
82 the NVIDIA docs, on Chapter 21. Configuring Power Management Support
83 '');
84
85 powerManagement.finegrained = lib.mkEnableOption (lib.mdDoc ''
86 experimental power management of PRIME offload. For more information, see
87 the NVIDIA docs, on Chapter 22. PCI-Express Runtime D3 (RTD3) Power Management
88 '');
89
90 dynamicBoost.enable = lib.mkEnableOption (lib.mdDoc ''
91 dynamic Boost balances power between the CPU and the GPU for improved
92 performance on supported laptops using the nvidia-powerd daemon. For more
93 information, see the NVIDIA docs, on Chapter 23. Dynamic Boost on Linux
94 '');
95
96 modesetting.enable = lib.mkEnableOption (lib.mdDoc ''
97 kernel modesetting when using the NVIDIA proprietary driver.
98
99 Enabling this fixes screen tearing when using Optimus via PRIME (see
100 {option}`hardware.nvidia.prime.sync.enable`. This is not enabled
101 by default because it is not officially supported by NVIDIA and would not
102 work with SLI
103 '');
104
105 prime.nvidiaBusId = lib.mkOption {
106 type = busIDType;
107 default = "";
108 example = "PCI:1:0:0";
109 description = lib.mdDoc ''
110 Bus ID of the NVIDIA GPU. You can find it using lspci; for example if lspci
111 shows the NVIDIA GPU at "01:00.0", set this option to "PCI:1:0:0".
112 '';
113 };
114
115 prime.intelBusId = lib.mkOption {
116 type = busIDType;
117 default = "";
118 example = "PCI:0:2:0";
119 description = lib.mdDoc ''
120 Bus ID of the Intel GPU. You can find it using lspci; for example if lspci
121 shows the Intel GPU at "00:02.0", set this option to "PCI:0:2:0".
122 '';
123 };
124
125 prime.amdgpuBusId = lib.mkOption {
126 type = busIDType;
127 default = "";
128 example = "PCI:4:0:0";
129 description = lib.mdDoc ''
130 Bus ID of the AMD APU. You can find it using lspci; for example if lspci
131 shows the AMD APU at "04:00.0", set this option to "PCI:4:0:0".
132 '';
133 };
134
135 prime.sync.enable = lib.mkEnableOption (lib.mdDoc ''
136 NVIDIA Optimus support using the NVIDIA proprietary driver via PRIME.
137 If enabled, the NVIDIA GPU will be always on and used for all rendering,
138 while enabling output to displays attached only to the integrated Intel/AMD
139 GPU without a multiplexer.
140
141 Note that this option only has any effect if the "nvidia" driver is specified
142 in {option}`services.xserver.videoDrivers`, and it should preferably
143 be the only driver there.
144
145 If this is enabled, then the bus IDs of the NVIDIA and Intel/AMD GPUs have to
146 be specified ({option}`hardware.nvidia.prime.nvidiaBusId` and
147 {option}`hardware.nvidia.prime.intelBusId` or
148 {option}`hardware.nvidia.prime.amdgpuBusId`).
149
150 If you enable this, you may want to also enable kernel modesetting for the
151 NVIDIA driver ({option}`hardware.nvidia.modesetting.enable`) in order
152 to prevent tearing.
153
154 Note that this configuration will only be successful when a display manager
155 for which the {option}`services.xserver.displayManager.setupCommands`
156 option is supported is used
157 '');
158
159 prime.allowExternalGpu = lib.mkEnableOption (lib.mdDoc ''
160 configuring X to allow external NVIDIA GPUs when using Prime [Reverse] sync optimus
161 '');
162
163 prime.offload.enable = lib.mkEnableOption (lib.mdDoc ''
164 render offload support using the NVIDIA proprietary driver via PRIME.
165
166 If this is enabled, then the bus IDs of the NVIDIA and Intel/AMD GPUs have to
167 be specified ({option}`hardware.nvidia.prime.nvidiaBusId` and
168 {option}`hardware.nvidia.prime.intelBusId` or
169 {option}`hardware.nvidia.prime.amdgpuBusId`)
170 '');
171
172 prime.offload.enableOffloadCmd = lib.mkEnableOption (lib.mdDoc ''
173 adding a `nvidia-offload` convenience script to {option}`environment.systemPackages`
174 for offloading programs to an nvidia device. To work, should have also enabled
175 {option}`hardware.nvidia.prime.offload.enable` or {option}`hardware.nvidia.prime.reverseSync.enable`.
176
177 Example usage `nvidia-offload sauerbraten_client`
178 '');
179
180 prime.reverseSync.enable = lib.mkEnableOption (lib.mdDoc ''
181 NVIDIA Optimus support using the NVIDIA proprietary driver via reverse
182 PRIME. If enabled, the Intel/AMD GPU will be used for all rendering, while
183 enabling output to displays attached only to the NVIDIA GPU without a
184 multiplexer.
185
186 Warning: This feature is relatively new, depending on your system this might
187 work poorly. AMD support, especially so.
188 See: https://forums.developer.nvidia.com/t/the-all-new-outputsink-feature-aka-reverse-prime/129828
189
190 Note that this option only has any effect if the "nvidia" driver is specified
191 in {option}`services.xserver.videoDrivers`, and it should preferably
192 be the only driver there.
193
194 If this is enabled, then the bus IDs of the NVIDIA and Intel/AMD GPUs have to
195 be specified ({option}`hardware.nvidia.prime.nvidiaBusId` and
196 {option}`hardware.nvidia.prime.intelBusId` or
197 {option}`hardware.nvidia.prime.amdgpuBusId`).
198
199 If you enable this, you may want to also enable kernel modesetting for the
200 NVIDIA driver ({option}`hardware.nvidia.modesetting.enable`) in order
201 to prevent tearing.
202
203 Note that this configuration will only be successful when a display manager
204 for which the {option}`services.xserver.displayManager.setupCommands`
205 option is supported is used
206 '');
207
208 nvidiaSettings =
209 (lib.mkEnableOption (lib.mdDoc ''
210 nvidia-settings, NVIDIA's GUI configuration tool
211 ''))
212 // {default = true;};
213
214 nvidiaPersistenced = lib.mkEnableOption (lib.mdDoc ''
215 nvidia-persistenced a update for NVIDIA GPU headless mode, i.e.
216 It ensures all GPUs stay awake even during headless mode
217 '');
218
219 forceFullCompositionPipeline = lib.mkEnableOption (lib.mdDoc ''
220 forcefully the full composition pipeline.
221 This sometimes fixes screen tearing issues.
222 This has been reported to reduce the performance of some OpenGL applications and may produce issues in WebGL.
223 It also drastically increases the time the driver needs to clock down after load
224 '');
225
226 package = lib.mkOption {
227 default = config.boot.kernelPackages.nvidiaPackages."${if cfg.datacenter.enable then "dc" else "stable"}";
228 defaultText = lib.literalExpression ''
229 config.boot.kernelPackages.nvidiaPackages."\$\{if cfg.datacenter.enable then "dc" else "stable"}"
230 '';
231 example = lib.mdDoc "config.boot.kernelPackages.nvidiaPackages.legacy_470";
232 description = lib.mdDoc ''
233 The NVIDIA driver package to use.
234 '';
235 };
236
237 open = lib.mkEnableOption (lib.mdDoc ''
238 the open source NVIDIA kernel module
239 '');
240 };
241 };
242
243 config = let
244 igpuDriver =
245 if pCfg.intelBusId != ""
246 then "modesetting"
247 else "amdgpu";
248 igpuBusId =
249 if pCfg.intelBusId != ""
250 then pCfg.intelBusId
251 else pCfg.amdgpuBusId;
252 in
253 lib.mkIf (nvidia_x11 != null) (lib.mkMerge [
254 # Common
255 ({
256 assertions = [
257 {
258 assertion = !(nvidiaEnabled && cfg.datacenter.enable);
259 message = "You cannot configure both X11 and Data Center drivers at the same time.";
260 }
261 ];
262 boot = {
263 blacklistedKernelModules = ["nouveau" "nvidiafb"];
264 kernelModules = [ "nvidia-uvm" ];
265 };
266 systemd.tmpfiles.rules =
267 lib.optional config.virtualisation.docker.enableNvidia
268 "L+ /run/nvidia-docker/bin - - - - ${nvidia_x11.bin}/origBin";
269 services.udev.extraRules =
270 ''
271 # Create /dev/nvidia-uvm when the nvidia-uvm module is loaded.
272 KERNEL=="nvidia", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidiactl c 195 255'"
273 KERNEL=="nvidia", RUN+="${pkgs.runtimeShell} -c 'for i in $$(cat /proc/driver/nvidia/gpus/*/information | grep Minor | cut -d \ -f 4); do mknod -m 666 /dev/nvidia$${i} c 195 $${i}; done'"
274 KERNEL=="nvidia_modeset", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-modeset c 195 254'"
275 KERNEL=="nvidia_uvm", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-uvm c $$(grep nvidia-uvm /proc/devices | cut -d \ -f 1) 0'"
276 KERNEL=="nvidia_uvm", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-uvm-tools c $$(grep nvidia-uvm /proc/devices | cut -d \ -f 1) 1'"
277 '';
278 hardware.opengl = {
279 extraPackages = [
280 nvidia_x11.out
281 ];
282 extraPackages32 = [
283 nvidia_x11.lib32
284 ];
285 };
286 environment.systemPackages = [
287 nvidia_x11.bin
288 ];
289 })
290 # X11
291 (lib.mkIf nvidiaEnabled {
292 assertions = [
293 {
294 assertion = primeEnabled -> pCfg.intelBusId == "" || pCfg.amdgpuBusId == "";
295 message = "You cannot configure both an Intel iGPU and an AMD APU. Pick the one corresponding to your processor.";
296 }
297
298 {
299 assertion = offloadCfg.enableOffloadCmd -> offloadCfg.enable || reverseSyncCfg.enable;
300 message = "Offload command requires offloading or reverse prime sync to be enabled.";
301 }
302
303 {
304 assertion = primeEnabled -> pCfg.nvidiaBusId != "" && (pCfg.intelBusId != "" || pCfg.amdgpuBusId != "");
305 message = "When NVIDIA PRIME is enabled, the GPU bus IDs must be configured.";
306 }
307
308 {
309 assertion = offloadCfg.enable -> lib.versionAtLeast nvidia_x11.version "435.21";
310 message = "NVIDIA PRIME render offload is currently only supported on versions >= 435.21.";
311 }
312
313 {
314 assertion = (reverseSyncCfg.enable && pCfg.amdgpuBusId != "") -> lib.versionAtLeast nvidia_x11.version "470.0";
315 message = "NVIDIA PRIME render offload for AMD APUs is currently only supported on versions >= 470 beta.";
316 }
317
318 {
319 assertion = !(syncCfg.enable && offloadCfg.enable);
320 message = "PRIME Sync and Offload cannot be both enabled";
321 }
322
323 {
324 assertion = !(syncCfg.enable && reverseSyncCfg.enable);
325 message = "PRIME Sync and PRIME Reverse Sync cannot be both enabled";
326 }
327
328 {
329 assertion = !(syncCfg.enable && cfg.powerManagement.finegrained);
330 message = "Sync precludes powering down the NVIDIA GPU.";
331 }
332
333 {
334 assertion = cfg.powerManagement.finegrained -> offloadCfg.enable;
335 message = "Fine-grained power management requires offload to be enabled.";
336 }
337
338 {
339 assertion = cfg.powerManagement.enable -> lib.versionAtLeast nvidia_x11.version "430.09";
340 message = "Required files for driver based power management only exist on versions >= 430.09.";
341 }
342
343 {
344 assertion = cfg.open -> (cfg.package ? open && cfg.package ? firmware);
345 message = "This version of NVIDIA driver does not provide a corresponding opensource kernel driver";
346 }
347
348 {
349 assertion = cfg.dynamicBoost.enable -> lib.versionAtLeast nvidia_x11.version "510.39.01";
350 message = "NVIDIA's Dynamic Boost feature only exists on versions >= 510.39.01";
351 }];
352
353 # If Optimus/PRIME is enabled, we:
354 # - Specify the configured NVIDIA GPU bus ID in the Device section for the
355 # "nvidia" driver.
356 # - Add the AllowEmptyInitialConfiguration option to the Screen section for the
357 # "nvidia" driver, in order to allow the X server to start without any outputs.
358 # - Add a separate Device section for the Intel GPU, using the "modesetting"
359 # driver and with the configured BusID.
360 # - OR add a separate Device section for the AMD APU, using the "amdgpu"
361 # driver and with the configures BusID.
362 # - Reference that Device section from the ServerLayout section as an inactive
363 # device.
364 # - Configure the display manager to run specific `xrandr` commands which will
365 # configure/enable displays connected to the Intel iGPU / AMD APU.
366
367 # reverse sync implies offloading
368 hardware.nvidia.prime.offload.enable = lib.mkDefault reverseSyncCfg.enable;
369
370 services.xserver.drivers =
371 lib.optional primeEnabled {
372 name = igpuDriver;
373 display = offloadCfg.enable;
374 modules = lib.optional (igpuDriver == "amdgpu") pkgs.xorg.xf86videoamdgpu;
375 deviceSection =
376 ''
377 BusID "${igpuBusId}"
378 ''
379 + lib.optionalString (syncCfg.enable && igpuDriver != "amdgpu") ''
380 Option "AccelMethod" "none"
381 '';
382 }
383 ++ lib.singleton {
384 name = "nvidia";
385 modules = [nvidia_x11.bin];
386 display = !offloadCfg.enable;
387 deviceSection =
388 lib.optionalString primeEnabled
389 ''
390 BusID "${pCfg.nvidiaBusId}"
391 ''
392 + lib.optionalString pCfg.allowExternalGpu ''
393 Option "AllowExternalGpus"
394 '';
395 screenSection =
396 ''
397 Option "RandRRotation" "on"
398 ''
399 + lib.optionalString syncCfg.enable ''
400 Option "AllowEmptyInitialConfiguration"
401 ''
402 + lib.optionalString cfg.forceFullCompositionPipeline ''
403 Option "metamodes" "nvidia-auto-select +0+0 {ForceFullCompositionPipeline=On}"
404 Option "AllowIndirectGLXProtocol" "off"
405 Option "TripleBuffer" "on"
406 '';
407 };
408
409 services.xserver.serverLayoutSection =
410 lib.optionalString syncCfg.enable ''
411 Inactive "Device-${igpuDriver}[0]"
412 ''
413 + lib.optionalString reverseSyncCfg.enable ''
414 Inactive "Device-nvidia[0]"
415 ''
416 + lib.optionalString offloadCfg.enable ''
417 Option "AllowNVIDIAGPUScreens"
418 '';
419
420 services.xserver.displayManager.setupCommands = let
421 gpuProviderName =
422 if igpuDriver == "amdgpu"
423 then
424 # find the name of the provider if amdgpu
425 "`${lib.getExe pkgs.xorg.xrandr} --listproviders | ${lib.getExe pkgs.gnugrep} -i AMD | ${lib.getExe pkgs.gnused} -n 's/^.*name://p'`"
426 else igpuDriver;
427 providerCmdParams =
428 if syncCfg.enable
429 then "\"${gpuProviderName}\" NVIDIA-0"
430 else "NVIDIA-G0 \"${gpuProviderName}\"";
431 in
432 lib.optionalString (syncCfg.enable || reverseSyncCfg.enable) ''
433 # Added by nvidia configuration module for Optimus/PRIME.
434 ${lib.getExe pkgs.xorg.xrandr} --setprovideroutputsource ${providerCmdParams}
435 ${lib.getExe pkgs.xorg.xrandr} --auto
436 '';
437
438 environment.etc = {
439 "nvidia/nvidia-application-profiles-rc" = lib.mkIf nvidia_x11.useProfiles {source = "${nvidia_x11.bin}/share/nvidia/nvidia-application-profiles-rc";};
440
441 # 'nvidia_x11' installs it's files to /run/opengl-driver/...
442 "egl/egl_external_platform.d".source = "/run/opengl-driver/share/egl/egl_external_platform.d/";
443 };
444
445 hardware.opengl = {
446 extraPackages = [
447 pkgs.nvidia-vaapi-driver
448 ];
449 extraPackages32 = [
450 pkgs.pkgsi686Linux.nvidia-vaapi-driver
451 ];
452 };
453 environment.systemPackages =
454 lib.optional cfg.nvidiaSettings nvidia_x11.settings
455 ++ lib.optional cfg.nvidiaPersistenced nvidia_x11.persistenced
456 ++ lib.optional offloadCfg.enableOffloadCmd
457 (pkgs.writeShellScriptBin "nvidia-offload" ''
458 export __NV_PRIME_RENDER_OFFLOAD=1
459 export __NV_PRIME_RENDER_OFFLOAD_PROVIDER=NVIDIA-G0
460 export __GLX_VENDOR_LIBRARY_NAME=nvidia
461 export __VK_LAYER_NV_optimus=NVIDIA_only
462 exec "$@"
463 '');
464
465 systemd.packages = lib.optional cfg.powerManagement.enable nvidia_x11.out;
466
467 systemd.services = let
468 nvidiaService = state: {
469 description = "NVIDIA system ${state} actions";
470 path = [pkgs.kbd];
471 serviceConfig = {
472 Type = "oneshot";
473 ExecStart = "${nvidia_x11.out}/bin/nvidia-sleep.sh '${state}'";
474 };
475 before = ["systemd-${state}.service"];
476 requiredBy = ["systemd-${state}.service"];
477 };
478 in
479 lib.mkMerge [
480 (lib.mkIf cfg.powerManagement.enable {
481 nvidia-suspend = nvidiaService "suspend";
482 nvidia-hibernate = nvidiaService "hibernate";
483 nvidia-resume =
484 (nvidiaService "resume")
485 // {
486 before = [];
487 after = ["systemd-suspend.service" "systemd-hibernate.service"];
488 requiredBy = ["systemd-suspend.service" "systemd-hibernate.service"];
489 };
490 })
491 (lib.mkIf cfg.nvidiaPersistenced {
492 "nvidia-persistenced" = {
493 description = "NVIDIA Persistence Daemon";
494 wantedBy = ["multi-user.target"];
495 serviceConfig = {
496 Type = "forking";
497 Restart = "always";
498 PIDFile = "/var/run/nvidia-persistenced/nvidia-persistenced.pid";
499 ExecStart = "${lib.getExe nvidia_x11.persistenced} --verbose";
500 ExecStopPost = "${pkgs.coreutils}/bin/rm -rf /var/run/nvidia-persistenced";
501 };
502 };
503 })
504 (lib.mkIf cfg.dynamicBoost.enable {
505 "nvidia-powerd" = {
506 description = "nvidia-powerd service";
507 path = [
508 pkgs.util-linux # nvidia-powerd wants lscpu
509 ];
510 wantedBy = ["multi-user.target"];
511 serviceConfig = {
512 Type = "dbus";
513 BusName = "nvidia.powerd.server";
514 ExecStart = "${nvidia_x11.bin}/bin/nvidia-powerd";
515 };
516 };
517 })
518 ];
519 services.acpid.enable = true;
520
521 services.dbus.packages = lib.optional cfg.dynamicBoost.enable nvidia_x11.bin;
522
523 hardware.firmware = lib.optional cfg.open nvidia_x11.firmware;
524
525 systemd.tmpfiles.rules =
526 lib.optional (nvidia_x11.persistenced != null && config.virtualisation.docker.enableNvidia)
527 "L+ /run/nvidia-docker/extras/bin/nvidia-persistenced - - - - ${nvidia_x11.persistenced}/origBin/nvidia-persistenced";
528
529 boot = {
530 extraModulePackages =
531 if cfg.open
532 then [nvidia_x11.open]
533 else [nvidia_x11.bin];
534 # nvidia-uvm is required by CUDA applications.
535 kernelModules =
536 lib.optionals config.services.xserver.enable ["nvidia" "nvidia_modeset" "nvidia_drm"];
537
538 # If requested enable modesetting via kernel parameter.
539 kernelParams =
540 lib.optional (offloadCfg.enable || cfg.modesetting.enable) "nvidia-drm.modeset=1"
541 ++ lib.optional cfg.powerManagement.enable "nvidia.NVreg_PreserveVideoMemoryAllocations=1"
542 ++ lib.optional cfg.open "nvidia.NVreg_OpenRmEnableUnsupportedGpus=1"
543 ++ lib.optional (config.boot.kernelPackages.kernel.kernelAtLeast "6.2" && !ibtSupport) "ibt=off";
544
545 # enable finegrained power management
546 extraModprobeConfig = lib.optionalString cfg.powerManagement.finegrained ''
547 options nvidia "NVreg_DynamicPowerManagement=0x02"
548 '';
549 };
550 services.udev.extraRules =
551 lib.optionalString cfg.powerManagement.finegrained (
552 lib.optionalString (lib.versionOlder config.boot.kernelPackages.kernel.version "5.5") ''
553 # Remove NVIDIA USB xHCI Host Controller devices, if present
554 ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x0c0330", ATTR{remove}="1"
555
556 # Remove NVIDIA USB Type-C UCSI devices, if present
557 ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x0c8000", ATTR{remove}="1"
558
559 # Remove NVIDIA Audio devices, if present
560 ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x040300", ATTR{remove}="1"
561 ''
562 + ''
563 # Enable runtime PM for NVIDIA VGA/3D controller devices on driver bind
564 ACTION=="bind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030000", TEST=="power/control", ATTR{power/control}="auto"
565 ACTION=="bind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030200", TEST=="power/control", ATTR{power/control}="auto"
566
567 # Disable runtime PM for NVIDIA VGA/3D controller devices on driver unbind
568 ACTION=="unbind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030000", TEST=="power/control", ATTR{power/control}="on"
569 ACTION=="unbind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030200", TEST=="power/control", ATTR{power/control}="on"
570 ''
571 );
572 })
573 # Data Center
574 (lib.mkIf (cfg.datacenter.enable) {
575 boot.extraModulePackages = [
576 nvidia_x11.bin
577 ];
578 systemd.services.nvidia-fabricmanager = {
579 enable = true;
580 description = "Start NVIDIA NVLink Management";
581 wantedBy = [ "multi-user.target" ];
582 unitConfig.After = [ "network-online.target" ];
583 unitConfig.Requires = [ "network-online.target" ];
584 serviceConfig = {
585 Type = "forking";
586 TimeoutStartSec = 240;
587 ExecStart = let
588 nv-fab-conf = settingsFormat.generate "fabricmanager.conf" cfg.datacenter.settings;
589 in
590 nvidia_x11.fabricmanager + "/bin/nv-fabricmanager -c " + nv-fab-conf;
591 LimitCORE="infinity";
592 };
593 };
594 environment.systemPackages =
595 lib.optional cfg.datacenter.enable nvidia_x11.fabricmanager;
596 })
597 ]);
598}