1 /*
2 * SPDX-FileCopyrightText: Copyright (c) 1993-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3 * SPDX-License-Identifier: MIT
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 #include "core/system.h"
25 #include "gpu_mgr/gpu_mgr.h"
26 #include "kernel/gpu/mig_mgr/kernel_mig_manager.h"
27 #include "kernel/gpu/nvlink/kernel_nvlink.h"
28 #include "kernel/gpu/bif/kernel_bif.h"
29 #include "gpu/subdevice/subdevice.h"
30 #include "gpu/gpu.h"
31 #include "virtualization/hypervisor/hypervisor.h"
32 #include "vgpu/rpc.h"
33 #include "vgpu/vgpu_events.h"
34 #include "platform/chipset/chipset.h"
35 #include "platform/p2p/p2p_caps.h"
36 #include "nvRmReg.h"
37 #include "nvlimits.h"
38 #include "nvdevid.h"
39
40 ct_assert(NV2080_GET_P2P_CAPS_UUID_LEN == NV_GPU_UUID_LEN);
41
42 /**
43 * @brief Determines if the GPUs are P2P compatible
44 *
45 * @param[in] pGpu0
46 * @param[in] pGpu1
47 *
48 * @return NV_TRUE if the GPUs are P2P compatible
49 */
50 static NvBool
areGpusP2PCompatible(OBJGPU * pGpu0,OBJGPU * pGpu1)51 areGpusP2PCompatible(OBJGPU *pGpu0, OBJGPU *pGpu1)
52 {
53 // Mark GPUs of different arch or impl incapable of P2P over pcie
54 if ((gpuGetChipArch(pGpu0) != gpuGetChipArch(pGpu1)) ||
55 (gpuGetChipImpl(pGpu0) != gpuGetChipImpl(pGpu1)))
56 {
57 return NV_FALSE;
58 }
59
60 // Mark GPUs of different notebook implementation incapable of P2P over pcie
61 if (IsMobile(pGpu0) != IsMobile(pGpu1))
62 {
63 return NV_FALSE;
64 }
65
66 return NV_TRUE;
67 }
68
69 NV_STATUS
p2pGetCaps(NvU32 gpuMask,NvBool * pP2PWriteCapable,NvBool * pP2PReadCapable,P2P_CONNECTIVITY * pConnectivity)70 p2pGetCaps
71 (
72 NvU32 gpuMask,
73 NvBool *pP2PWriteCapable,
74 NvBool *pP2PReadCapable,
75 P2P_CONNECTIVITY *pConnectivity
76 )
77 {
78 NvU8 p2PWriteCapsStatus;
79 NvU8 p2PReadCapsStatus;
80 NV_STATUS status;
81 P2P_CONNECTIVITY connectivity;
82
83 if ((pP2PWriteCapable == NULL) || (pP2PReadCapable == NULL))
84 {
85 return NV_ERR_INVALID_ARGUMENT;
86 }
87
88 status = p2pGetCapsStatus(gpuMask, &p2PWriteCapsStatus,
89 &p2PReadCapsStatus, &connectivity
90 );
91 if (status != NV_OK)
92 {
93 return status;
94 }
95
96 //
97 // The classes like NV50_P2P, NV50_THIRD_PARTY_P2P depends on direct P2P
98 // connectivity, hence the check.
99 //
100 if (!((connectivity == P2P_CONNECTIVITY_PCIE_PROPRIETARY) ||
101 (connectivity == P2P_CONNECTIVITY_PCIE_BAR1) ||
102 (connectivity == P2P_CONNECTIVITY_NVLINK) ||
103 (connectivity == P2P_CONNECTIVITY_C2C)))
104 {
105 return NV_ERR_NOT_SUPPORTED;
106 }
107
108 *pP2PWriteCapable = (p2PWriteCapsStatus == NV0000_P2P_CAPS_STATUS_OK);
109 *pP2PReadCapable = (p2PReadCapsStatus == NV0000_P2P_CAPS_STATUS_OK);
110
111 if (pConnectivity != NULL)
112 {
113 *pConnectivity = connectivity;
114 }
115
116 return status;
117 }
118
119 static NV_STATUS
_kp2pCapsGetStatusIndirectOverNvLink(NvU32 gpuMask,NvU8 * pP2PWriteCapStatus,NvU8 * pP2PReadCapStatus)120 _kp2pCapsGetStatusIndirectOverNvLink
121 (
122 NvU32 gpuMask,
123 NvU8 *pP2PWriteCapStatus,
124 NvU8 *pP2PReadCapStatus
125 )
126 {
127 OBJGPU *pGpu = NULL;
128 NvU32 gpuInstance = 0;
129 OBJGPU *pFirstGpu = gpumgrGetNextGpu(gpuMask, &gpuInstance);
130 NvBool bIndirectPeers = NV_FALSE;
131 KernelBif *pKernelBif = GPU_GET_KERNEL_BIF(pFirstGpu);
132
133 if ((pKernelBif->forceP2PType != NV_REG_STR_RM_FORCE_P2P_TYPE_DEFAULT) &&
134 (pKernelBif->forceP2PType != NV_REG_STR_RM_FORCE_P2P_TYPE_NVLINK))
135 {
136 *pP2PReadCapStatus = NV0000_P2P_CAPS_STATUS_NOT_SUPPORTED;
137 *pP2PWriteCapStatus = NV0000_P2P_CAPS_STATUS_NOT_SUPPORTED;
138 return NV_OK;
139 }
140
141 while ((pGpu = gpumgrGetNextGpu(gpuMask, &gpuInstance)) != NULL)
142 {
143 bIndirectPeers = gpumgrCheckIndirectPeer(pFirstGpu, pGpu);
144 if (!bIndirectPeers)
145 {
146 break;
147 }
148 }
149
150 if (bIndirectPeers)
151 {
152 *pP2PReadCapStatus = NV0000_P2P_CAPS_STATUS_OK;
153 *pP2PWriteCapStatus = NV0000_P2P_CAPS_STATUS_OK;
154 }
155 else
156 {
157 *pP2PReadCapStatus = NV0000_P2P_CAPS_STATUS_NOT_SUPPORTED;
158 *pP2PWriteCapStatus = NV0000_P2P_CAPS_STATUS_NOT_SUPPORTED;
159 }
160
161 return NV_OK;
162 }
163
164 static NV_STATUS
_gpumgrGetP2PCapsStatusOverNvLink(NvU32 gpuMask,NvU8 * pP2PWriteCapStatus,NvU8 * pP2PReadCapStatus)165 _gpumgrGetP2PCapsStatusOverNvLink
166 (
167 NvU32 gpuMask,
168 NvU8 *pP2PWriteCapStatus,
169 NvU8 *pP2PReadCapStatus
170 )
171 {
172 OBJGPU *pGpu = NULL;
173 NvU32 gpuInstance = 0;
174 NV_STATUS status;
175 OBJGPU *pFirstGpu = gpumgrGetNextGpu(gpuMask, &gpuInstance);
176 RMTIMEOUT timeout;
177 NvU32 linkTrainingTimeout = 10000000;
178 KernelBif *pKernelBif = NULL;
179 KernelNvlink *pKernelNvlink = NULL;
180
181 NV_ASSERT_OR_RETURN(pFirstGpu != NULL, NV_ERR_INVALID_ARGUMENT);
182 pKernelNvlink = GPU_GET_KERNEL_NVLINK(pFirstGpu);
183 pKernelBif = GPU_GET_KERNEL_BIF(pFirstGpu);
184
185 if ((pKernelBif->forceP2PType != NV_REG_STR_RM_FORCE_P2P_TYPE_DEFAULT) &&
186 (pKernelBif->forceP2PType != NV_REG_STR_RM_FORCE_P2P_TYPE_NVLINK))
187 {
188 *pP2PReadCapStatus = NV0000_P2P_CAPS_STATUS_NOT_SUPPORTED;
189 *pP2PWriteCapStatus = NV0000_P2P_CAPS_STATUS_NOT_SUPPORTED;
190 return NV_OK;
191 }
192
193 //
194 // Re-initialize to check loop back configuration if only single GPU in
195 // requested mask.
196 //
197 gpuInstance = (gpumgrGetSubDeviceCount(gpuMask) > 1) ? gpuInstance : 0;
198
199 // Check NvLink P2P connectivity
200 while ((pGpu = gpumgrGetNextGpu(gpuMask, &gpuInstance)) != NULL)
201 {
202 //
203 // If ALI is enabled then poll to make sure that the links have
204 // finished training on the two given gpus. If timeout occurs then
205 // log an error, but continue on as there could be another gpu pair
206 // that could have connectivity
207 //
208
209 if ((pKernelNvlink != NULL) &&
210 knvlinkDiscoverPostRxDetLinks_HAL(pFirstGpu, pKernelNvlink, pGpu) == NV_OK)
211 {
212 // Check to make sure that the links are active
213
214 gpuSetTimeout(pGpu, linkTrainingTimeout, &timeout, IS_SILICON(pGpu) ?
215 (GPU_TIMEOUT_FLAGS_BYPASS_THREAD_STATE | GPU_TIMEOUT_FLAGS_DEFAULT) : 0);
216 do
217 {
218 status = gpuCheckTimeout(pGpu, &timeout);
219
220 if (knvlinkCheckTrainingIsComplete(pFirstGpu, pGpu, pKernelNvlink) == NV_OK)
221 {
222 break;
223 }
224
225 if (status == NV_ERR_TIMEOUT)
226 {
227 NV_PRINTF(LEVEL_ERROR,
228 "Links failed to train for the given gpu pairs!\n");
229 return status;
230 }
231 }
232 while(status != NV_ERR_TIMEOUT);
233 }
234
235 // Ensure that we can create a NvLink P2P object between the two object
236 if ((pKernelNvlink != NULL) &&
237 knvlinkIsNvlinkP2pSupported(pFirstGpu, pKernelNvlink, pGpu))
238 {
239 // Ensure training completes on legacy nvlink devices
240 status = knvlinkTrainP2pLinksToActive(pFirstGpu, pGpu, pKernelNvlink);
241 NV_ASSERT(status == NV_OK);
242
243 if (status != NV_OK)
244 {
245 *pP2PReadCapStatus = NV0000_P2P_CAPS_STATUS_NOT_SUPPORTED;
246 *pP2PWriteCapStatus = NV0000_P2P_CAPS_STATUS_NOT_SUPPORTED;
247 return NV_OK;
248 }
249 }
250 else
251 {
252 *pP2PReadCapStatus = NV0000_P2P_CAPS_STATUS_NOT_SUPPORTED;
253 *pP2PWriteCapStatus = NV0000_P2P_CAPS_STATUS_NOT_SUPPORTED;
254 return NV_OK;
255 }
256 }
257
258 *pP2PReadCapStatus = NV0000_P2P_CAPS_STATUS_OK;
259 *pP2PWriteCapStatus = NV0000_P2P_CAPS_STATUS_OK;
260 return NV_OK;
261 }
262
263 // Returns true if overrides are enabled for PCI-E.
264 static NvBool
_kp2pCapsCheckStatusOverridesForPcie(NvU32 gpuMask,NvU8 * pP2PWriteCapStatus,NvU8 * pP2PReadCapStatus)265 _kp2pCapsCheckStatusOverridesForPcie
266 (
267 NvU32 gpuMask,
268 NvU8 *pP2PWriteCapStatus,
269 NvU8 *pP2PReadCapStatus
270 )
271 {
272 KernelBif *pKernelBif = NULL;
273 NvU32 gpuInstance = 0;
274 OBJGPU *pGpu = NULL;
275
276 // Check overrides for all GPUs in the mask.
277 while ((pGpu = gpumgrGetNextGpu(gpuMask, &gpuInstance)) != NULL)
278 {
279 pKernelBif = GPU_GET_KERNEL_BIF(pGpu);
280 if (pKernelBif->p2pOverride != BIF_P2P_NOT_OVERRIDEN)
281 {
282 switch(DRF_VAL(_REG_STR, _CL_FORCE_P2P, _READ, pKernelBif->p2pOverride))
283 {
284 case NV_REG_STR_CL_FORCE_P2P_READ_DISABLE:
285 *pP2PReadCapStatus = NV0000_P2P_CAPS_STATUS_DISABLED_BY_REGKEY;
286 break;
287 case NV_REG_STR_CL_FORCE_P2P_READ_ENABLE:
288 *pP2PReadCapStatus = NV0000_P2P_CAPS_STATUS_OK;
289 break;
290 default:
291 break;
292 }
293
294 switch(DRF_VAL(_REG_STR, _CL_FORCE_P2P, _WRITE, pKernelBif->p2pOverride))
295 {
296 case NV_REG_STR_CL_FORCE_P2P_WRITE_DISABLE:
297 *pP2PWriteCapStatus = NV0000_P2P_CAPS_STATUS_DISABLED_BY_REGKEY;
298 break;
299 case NV_REG_STR_CL_FORCE_P2P_WRITE_ENABLE:
300 *pP2PWriteCapStatus = NV0000_P2P_CAPS_STATUS_OK;
301 break;
302 default:
303 break;
304 }
305
306 return NV_TRUE;
307 }
308
309 }
310
311 return NV_FALSE;
312 }
313
314 /**
315 * @brief Check GPU Pcie mailbox P2P capability
316 *
317 * @param[in] pGpu OBJGPU pointer
318 * @param[out] pP2PWriteCapStatus Pointer to get the P2P write capability
319 * @param[out] pP2PReadCapStatus Pointer to get the P2P read capability
320 * @param[out] pbCommonPciSwitch To return if GPUs are on a common PCIE switch
321 *
322 * @returns NV_OK, if successfully
323 * The write and read capability status are in the pP2PWriteCapStatus and pP2PReadCapStatus
324 */
325 static NV_STATUS
_kp2pCapsGetStatusOverPcie(NvU32 gpuMask,NvU8 * pP2PWriteCapStatus,NvU8 * pP2PReadCapStatus,NvBool * pbCommonPciSwitch)326 _kp2pCapsGetStatusOverPcie
327 (
328 NvU32 gpuMask,
329 NvU8 *pP2PWriteCapStatus,
330 NvU8 *pP2PReadCapStatus,
331 NvBool *pbCommonPciSwitch
332 )
333 {
334 OBJGPU *pGpu = NULL;
335 OBJGPU *pFirstGpu = NULL;
336 NvU32 gpuInstance = 0;
337 KernelBif *pKernelBif = NULL;
338 OBJSYS *pSys = SYS_GET_INSTANCE();
339 OBJCL *pCl = SYS_GET_CL(pSys);
340 NvU32 iohDomain_ref = 0xFFFFFFFF;
341 NvU8 iohBus_ref = 0xFF;
342 NvU8 pciSwitchBus = 0, pciSwitchBus_ref = 0xFF;
343 NvBool bCommonPciSwitchFound = NV_TRUE;
344 NvU16 deviceID;
345 NvU8 gpuP2PReadCapsStatus = NV0000_P2P_CAPS_STATUS_OK;
346 NvU8 gpuP2PWriteCapsStatus = NV0000_P2P_CAPS_STATUS_OK;
347 NvU32 lockedGpuMask = 0;
348 NV_STATUS status = NV_OK;
349 OBJHYPERVISOR *pHypervisor = SYS_GET_HYPERVISOR(pSys);
350
351 // Check if any overrides are enabled.
352 if (_kp2pCapsCheckStatusOverridesForPcie(gpuMask, pP2PWriteCapStatus,
353 pP2PReadCapStatus))
354 {
355 return NV_OK;
356 }
357
358 pGpu = gpumgrGetNextGpu(gpuMask, &gpuInstance);
359 if (IS_GSP_CLIENT(pGpu))
360 {
361 if (gpumgrGetPcieP2PCapsFromCache(gpuMask, pP2PWriteCapStatus, pP2PReadCapStatus))
362 {
363 return NV_OK;
364 }
365 }
366
367 // Check for hypervisor oriented PCIe P2P overrides
368 if (pHypervisor &&
369 pHypervisor->bDetected &&
370 hypervisorPcieP2pDetection(pHypervisor, gpuMask))
371 {
372 *pP2PReadCapStatus = NV0000_P2P_CAPS_STATUS_OK;
373 *pP2PWriteCapStatus = NV0000_P2P_CAPS_STATUS_OK;
374 goto done;
375 }
376
377 // PCI-E topology checks
378 gpuInstance = 0;
379 while ((pGpu = gpumgrGetNextGpu(gpuMask, &gpuInstance)) != NULL)
380 {
381 //
382 // While PCI-E P2P transactions are forwarded between different
383 // root ports implemented within a given Intel I/O hub, they
384 // are not forwarded between any two I/O hubs. We must therefore
385 // complement the table-driven chipset validation check below
386 // with an IOH-specific topology check.
387 //
388 if (pGpu->gpuClData.rootPort.addr.valid &&
389 (pGpu->gpuClData.rootPort.VendorID == PCI_VENDOR_ID_INTEL))
390 {
391 deviceID = pGpu->gpuClData.rootPort.DeviceID;
392
393 if (((deviceID >= DEVICE_ID_INTEL_3408_ROOT_PORT) &&
394 (deviceID <= DEVICE_ID_INTEL_3411_ROOT_PORT)) ||
395 ((deviceID >= DEVICE_ID_INTEL_3C02_ROOT_PORT) &&
396 (deviceID <= DEVICE_ID_INTEL_3C0B_ROOT_PORT)) ||
397 ((deviceID >= DEVICE_ID_INTEL_0E02_ROOT_PORT) &&
398 (deviceID <= DEVICE_ID_INTEL_0E0B_ROOT_PORT)) ||
399 ((deviceID >= DEVICE_ID_INTEL_2F01_ROOT_PORT) &&
400 (deviceID <= DEVICE_ID_INTEL_2F0B_ROOT_PORT)) ||
401 ((deviceID >= DEVICE_ID_INTEL_6F01_ROOT_PORT) &&
402 (deviceID <= DEVICE_ID_INTEL_6F0B_ROOT_PORT)) ||
403 (deviceID == DEVICE_ID_INTEL_3420_ROOT_PORT) ||
404 (deviceID == DEVICE_ID_INTEL_3421_ROOT_PORT))
405 {
406 if (iohDomain_ref == 0xFFFFFFFF)
407 {
408 iohDomain_ref = pGpu->gpuClData.rootPort.addr.domain;
409 iohBus_ref = pGpu->gpuClData.rootPort.addr.bus;
410 }
411 else if ((iohDomain_ref != pGpu->gpuClData.rootPort.addr.domain) ||
412 (iohBus_ref != pGpu->gpuClData.rootPort.addr.bus))
413 {
414 *pP2PReadCapStatus = NV0000_P2P_CAPS_STATUS_IOH_TOPOLOGY_NOT_SUPPORTED;
415 *pP2PWriteCapStatus = NV0000_P2P_CAPS_STATUS_IOH_TOPOLOGY_NOT_SUPPORTED;
416 goto done;
417 }
418 }
419 }
420
421 // Test common bridges. Skip first GPU
422 if (pFirstGpu == NULL)
423 {
424 pFirstGpu = pGpu;
425 continue;
426 }
427
428 if (!areGpusP2PCompatible(pFirstGpu, pGpu))
429 {
430 *pP2PReadCapStatus = NV0000_P2P_CAPS_STATUS_NOT_SUPPORTED;
431 *pP2PWriteCapStatus = NV0000_P2P_CAPS_STATUS_NOT_SUPPORTED;
432 goto done;
433 }
434
435 // This call returns the most upper bridge
436 clFindCommonDownstreamBR(pFirstGpu, pGpu, pCl, &pciSwitchBus);
437
438 if (pciSwitchBus_ref == 0xFF)
439 {
440 pciSwitchBus_ref = pciSwitchBus;
441 }
442
443 // If no bridge found or different to the one previously found
444 if ((pciSwitchBus == 0xFF) || (pciSwitchBus_ref != pciSwitchBus))
445 {
446 bCommonPciSwitchFound = NV_FALSE;
447 }
448 }
449
450 // Check if GPUs have the HW P2P implementation
451
452 // Only lock for GSP_CLIENT. Get one GPU.
453 if (pFirstGpu == NULL)
454 {
455 gpuInstance = 0;
456 pFirstGpu = gpumgrGetNextGpu(gpuMask, &gpuInstance);
457 }
458
459 if (IS_GSP_CLIENT(pFirstGpu))
460 {
461 // Lock GPUs
462 lockedGpuMask = gpuMask;
463 status = rmGpuGroupLockAcquire(0, GPU_LOCK_GRP_MASK,
464 GPU_LOCK_FLAGS_SAFE_LOCK_UPGRADE, RM_LOCK_MODULES_P2P, &lockedGpuMask);
465
466 // If we get NOTHING_TO_DO, we already have the needed locks, so don't free them
467 if (status == NV_WARN_NOTHING_TO_DO)
468 lockedGpuMask = 0;
469 else if (status != NV_OK)
470 {
471 lockedGpuMask = 0;
472 goto done;
473 }
474 }
475
476 // Reset P2P caps as statuses will be accumulated below.
477 *pP2PReadCapStatus = *pP2PWriteCapStatus = NV0000_P2P_CAPS_STATUS_OK;
478
479 gpuInstance = 0;
480 while ((pGpu = gpumgrGetNextGpu(gpuMask, &gpuInstance)) != NULL)
481 {
482 RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu);
483 NV2080_CTRL_INTERNAL_GET_PCIE_P2P_CAPS_PARAMS p2pCapsParams = {0};
484
485 p2pCapsParams.bCommonPciSwitchFound = bCommonPciSwitchFound;
486
487 NV_ASSERT_OK_OR_GOTO(status, pRmApi->Control(pRmApi,
488 pGpu->hInternalClient,
489 pGpu->hInternalSubdevice,
490 NV2080_CTRL_CMD_INTERNAL_GET_PCIE_P2P_CAPS,
491 &p2pCapsParams,
492 sizeof(NV2080_CTRL_INTERNAL_GET_PCIE_P2P_CAPS_PARAMS)),
493 done);
494
495 // GPU specific P2P caps
496 pKernelBif = GPU_GET_KERNEL_BIF(pGpu);
497 if (pKernelBif->getProperty(pKernelBif, PDB_PROP_KBIF_P2P_WRITES_DISABLED))
498 gpuP2PWriteCapsStatus = NV0000_P2P_CAPS_STATUS_GPU_NOT_SUPPORTED;
499 if (pKernelBif->getProperty(pKernelBif, PDB_PROP_KBIF_P2P_READS_DISABLED))
500 gpuP2PReadCapsStatus = NV0000_P2P_CAPS_STATUS_GPU_NOT_SUPPORTED;
501
502 //
503 // Reconcile the system and GPU specific P2P information
504 // The system P2P status takes precedence
505 // Do not override status from not OK to OK
506 //
507 if (*pP2PReadCapStatus == NV0000_P2P_CAPS_STATUS_OK)
508 *pP2PReadCapStatus = (p2pCapsParams.p2pReadCapsStatus == NV0000_P2P_CAPS_STATUS_OK ? gpuP2PReadCapsStatus : p2pCapsParams.p2pReadCapsStatus);
509 if (*pP2PWriteCapStatus == NV0000_P2P_CAPS_STATUS_OK)
510 *pP2PWriteCapStatus = (p2pCapsParams.p2pWriteCapsStatus == NV0000_P2P_CAPS_STATUS_OK ? gpuP2PWriteCapsStatus : p2pCapsParams.p2pWriteCapsStatus);
511
512 // No need to continue if P2P is not supported
513 if ((*pP2PReadCapStatus != NV0000_P2P_CAPS_STATUS_OK) &&
514 (*pP2PWriteCapStatus != NV0000_P2P_CAPS_STATUS_OK))
515 {
516 break;
517 }
518 }
519
520 done:
521 if (lockedGpuMask != 0)
522 {
523 rmGpuGroupLockRelease(lockedGpuMask, GPUS_LOCK_FLAGS_NONE);
524 }
525
526 if (status != NV_OK)
527 {
528 if (*pP2PReadCapStatus == NV0000_P2P_CAPS_STATUS_OK)
529 {
530 *pP2PReadCapStatus = NV0000_P2P_CAPS_STATUS_NOT_SUPPORTED;
531 }
532 if (*pP2PWriteCapStatus == NV0000_P2P_CAPS_STATUS_OK)
533 {
534 *pP2PWriteCapStatus = NV0000_P2P_CAPS_STATUS_NOT_SUPPORTED;
535 }
536 }
537
538 if (pbCommonPciSwitch != NULL)
539 {
540 *pbCommonPciSwitch = bCommonPciSwitchFound;
541 }
542
543 //
544 // Not fatal if failing, effect would be perf degradation as we would not hit the cache.
545 // So just assert.
546 //
547 gpuInstance = 0;
548 pGpu = gpumgrGetNextGpu(gpuMask, &gpuInstance);
549 if (IS_GSP_CLIENT(pGpu))
550 {
551 NV_ASSERT_OK(gpumgrStorePcieP2PCapsCache(gpuMask, *pP2PWriteCapStatus, *pP2PReadCapStatus));
552 }
553 return status;
554 }
555
556 /**
557 * @brief Check the host system BAR1 P2P capability
558 *
559 * @param[in] pGpu OBJGPU pointer
560 * @param[out] pP2PWriteCapStatus Pointer to get the P2P write capability
561 * @param[out] pP2PReadCapStatus Pointer to get the P2P read capability
562 * @param[out] bCommonPciSwitchFound To indicate if GPUs are on a common PCIE switch
563 *
564 * @returns NV_OK
565 */
566 static NV_STATUS
_p2pCapsGetHostSystemStatusOverPcieBar1(OBJGPU * pGpu,NvU8 * pP2PWriteCapStatus,NvU8 * pP2PReadCapStatus,NvBool bCommonPciSwitchFound)567 _p2pCapsGetHostSystemStatusOverPcieBar1
568 (
569 OBJGPU *pGpu,
570 NvU8 *pP2PWriteCapStatus,
571 NvU8 *pP2PReadCapStatus,
572 NvBool bCommonPciSwitchFound
573 )
574 {
575 OBJSYS *pSys = SYS_GET_INSTANCE();
576
577 *pP2PWriteCapStatus = NV0000_P2P_CAPS_STATUS_OK;
578
579 if (bCommonPciSwitchFound ||
580 (pSys->cpuInfo.type == NV0000_CTRL_SYSTEM_CPU_TYPE_RYZEN) ||
581 (pSys->cpuInfo.type == NV0000_CTRL_SYSTEM_CPU_TYPE_XEON_SPR))
582 {
583 *pP2PReadCapStatus = NV0000_P2P_CAPS_STATUS_OK;
584 }
585 else
586 {
587 *pP2PReadCapStatus = NV0000_P2P_CAPS_STATUS_CHIPSET_NOT_SUPPORTED;
588 NV_PRINTF(LEVEL_INFO, "Unrecognized CPU. Read Cap is disabled\n");
589 }
590
591 return NV_OK;
592 }
593
594 /**
595 * @brief Check GPU Pcie BAR1 P2P capability
596 *
597 * @param[in] pGpu OBJGPU pointer
598 * @param[out] pP2PWriteCapStatus Pointer to get the P2P write capability
599 * @param[out] pP2PReadCapStatus Pointer to get the P2P read capability
600 * @param[out] bCommonPciSwitchFound To indicate if GPUs are on a common PCIE switch
601 *
602 * @returns NV_OK, if GPUs at least support read or write
603 * NV_ERR_NOT_SUPPORTED, if GPUs does not support read and write
604 */
605 static NV_STATUS
_kp2pCapsGetStatusOverPcieBar1(NvU32 gpuMask,NvU8 * pP2PWriteCapStatus,NvU8 * pP2PReadCapStatus,NvBool bCommonPciSwitchFound)606 _kp2pCapsGetStatusOverPcieBar1
607 (
608 NvU32 gpuMask,
609 NvU8 *pP2PWriteCapStatus,
610 NvU8 *pP2PReadCapStatus,
611 NvBool bCommonPciSwitchFound
612 )
613 {
614 OBJGPU *pGpuPeer = NULL;
615 NvU32 gpuInstance = 0;
616 OBJGPU *pFirstGpu = gpumgrGetNextGpu(gpuMask, &gpuInstance);
617 KernelBif *pKernelBif = GPU_GET_KERNEL_BIF(pFirstGpu);
618 NvU8 writeCapStatus = *pP2PWriteCapStatus;
619 NvU8 readCapStatus = *pP2PReadCapStatus;
620
621 if ((pKernelBif->forceP2PType != NV_REG_STR_RM_FORCE_P2P_TYPE_BAR1P2P))
622 {
623 return NV_ERR_NOT_SUPPORTED;
624 }
625
626 // Check if any overrides are enabled.
627 if (_kp2pCapsCheckStatusOverridesForPcie(gpuMask, pP2PWriteCapStatus,
628 pP2PReadCapStatus))
629 {
630 return NV_OK;
631 }
632
633 //
634 // Re-initialize to check loop back configuration if only single GPU in
635 // requested mask.
636 //
637 gpuInstance = (gpumgrGetSubDeviceCount(gpuMask) > 1) ? gpuInstance : 0;
638
639 while ((pGpuPeer = gpumgrGetNextGpu(gpuMask, &gpuInstance)) != NULL)
640 {
641 if (!kbusIsPcieBar1P2PMappingSupported_HAL(pFirstGpu, GPU_GET_KERNEL_BUS(pFirstGpu),
642 pGpuPeer, GPU_GET_KERNEL_BUS(pGpuPeer)))
643 {
644 return NV_ERR_NOT_SUPPORTED;
645 }
646 }
647
648 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
649 _p2pCapsGetHostSystemStatusOverPcieBar1(pFirstGpu, &writeCapStatus,
650 &readCapStatus, bCommonPciSwitchFound));
651
652 if (*pP2PWriteCapStatus == NV0000_P2P_CAPS_STATUS_OK)
653 *pP2PWriteCapStatus = writeCapStatus;
654 if (*pP2PReadCapStatus == NV0000_P2P_CAPS_STATUS_OK)
655 *pP2PReadCapStatus = readCapStatus;
656
657 if ((*pP2PReadCapStatus != NV0000_P2P_CAPS_STATUS_OK) ||
658 (*pP2PWriteCapStatus != NV0000_P2P_CAPS_STATUS_OK))
659 {
660 // return not supported if it does not support both operations
661 return NV_ERR_NOT_SUPPORTED;
662 }
663
664 return NV_OK;
665 }
666
667 NV_STATUS
p2pGetCapsStatus(NvU32 gpuMask,NvU8 * pP2PWriteCapStatus,NvU8 * pP2PReadCapStatus,P2P_CONNECTIVITY * pConnectivity)668 p2pGetCapsStatus
669 (
670 NvU32 gpuMask,
671 NvU8 *pP2PWriteCapStatus,
672 NvU8 *pP2PReadCapStatus,
673 P2P_CONNECTIVITY *pConnectivity
674 )
675 {
676 OBJSYS *pSys = SYS_GET_INSTANCE();
677 KernelNvlink *pKernelNvlink = NULL;
678 OBJGPU *pGpu = NULL;
679 NvU32 gpuInstance = 0;
680 NvBool bCommonSwitchFound = NV_FALSE;
681
682 if ((pP2PWriteCapStatus == NULL) ||
683 (pP2PReadCapStatus == NULL) ||
684 (pConnectivity == NULL)
685 )
686 {
687 return NV_ERR_INVALID_ARGUMENT;
688 }
689
690 // Default values
691 *pP2PWriteCapStatus = NV0000_P2P_CAPS_STATUS_NOT_SUPPORTED;
692 *pP2PReadCapStatus = NV0000_P2P_CAPS_STATUS_NOT_SUPPORTED;
693 *pConnectivity = P2P_CONNECTIVITY_UNKNOWN;
694
695 // MIG-Nvlink-P2P can be incompatible, so check compatibility for all GPUs
696 while ((pGpu = gpumgrGetNextGpu(gpuMask, &gpuInstance)) != NULL)
697 {
698 KernelMIGManager *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu);
699 NvBool bSmcNvLinkP2PSupported = ((pKernelMIGManager != NULL) &&
700 kmigmgrIsMIGNvlinkP2PSupported(pGpu, pKernelMIGManager));
701
702 // If any of the GPU has MIG enabled, return with no P2P support
703 if (!bSmcNvLinkP2PSupported)
704 {
705 NV_PRINTF(LEVEL_NOTICE,
706 "P2P is marked unsupported with MIG for GPU instance = 0x%x\n",
707 gpuInstance);
708 return NV_OK;
709 }
710 }
711
712 gpuInstance = 0;
713
714 // Check NvLink P2P connectivity.
715 if (_gpumgrGetP2PCapsStatusOverNvLink(gpuMask, pP2PWriteCapStatus,
716 pP2PReadCapStatus) == NV_OK)
717 {
718 if (*pP2PWriteCapStatus == NV0000_P2P_CAPS_STATUS_OK &&
719 *pP2PReadCapStatus == NV0000_P2P_CAPS_STATUS_OK)
720 {
721 *pConnectivity = P2P_CONNECTIVITY_NVLINK;
722 return NV_OK;
723 }
724 }
725
726 //
727 // On NVSwitch systems, if the NVLink P2P path fails, don't fall back to
728 // other P2P paths. To ensure that, check if any GPU in the mask has NVLink
729 // support. If supported, enforce NVSwitch/NVLink connectivity by returning
730 // NV0000_P2P_CAPS_STATUS_NOT_SUPPORTED.
731 //
732 gpuInstance = 0;
733 while ((pGpu = gpumgrGetNextGpu(gpuMask, &gpuInstance)) != NULL)
734 {
735 pKernelNvlink = GPU_GET_KERNEL_NVLINK(pGpu);
736 if (pKernelNvlink != NULL && knvlinkGetDiscoveredLinkMask(pGpu, pKernelNvlink) != 0 &&
737 (pSys->getProperty(pSys, PDB_PROP_SYS_NVSWITCH_IS_PRESENT) ||
738 knvlinkIsNvswitchProxyPresent(pGpu, pKernelNvlink) ||
739 GPU_IS_NVSWITCH_DETECTED(pGpu)))
740 {
741 *pP2PReadCapStatus = NV0000_P2P_CAPS_STATUS_NOT_SUPPORTED;
742 *pP2PWriteCapStatus = NV0000_P2P_CAPS_STATUS_NOT_SUPPORTED;
743 return NV_OK;
744 }
745 }
746
747 // We didn't find direct P2P, so check for indirect P2P.
748 if (_kp2pCapsGetStatusIndirectOverNvLink(gpuMask, pP2PWriteCapStatus,
749 pP2PReadCapStatus) == NV_OK)
750 {
751 if ((*pP2PWriteCapStatus == NV0000_P2P_CAPS_STATUS_OK) &&
752 (*pP2PReadCapStatus == NV0000_P2P_CAPS_STATUS_OK))
753 {
754 *pConnectivity = P2P_CONNECTIVITY_NVLINK_INDIRECT;
755 return NV_OK;
756 }
757 }
758
759 //
760 // Check PCIE P2P connectivity.
761 //
762 // We can control P2P connectivity for PCI-E peers using regkeys, hence
763 // if either read or write is supported, return success. See
764 // _kp2pCapsCheckStatusOverridesForPcie for details.
765 //
766 if (_kp2pCapsGetStatusOverPcie(gpuMask, pP2PWriteCapStatus,
767 pP2PReadCapStatus, &bCommonSwitchFound) == NV_OK)
768 {
769 if ((*pP2PWriteCapStatus == NV0000_P2P_CAPS_STATUS_OK) ||
770 (*pP2PReadCapStatus == NV0000_P2P_CAPS_STATUS_OK))
771 {
772 NvU8 bar1P2PWriteCapStatus = *pP2PWriteCapStatus;
773 NvU8 bar1P2PReadCapStatus = *pP2PReadCapStatus;
774
775 *pConnectivity = P2P_CONNECTIVITY_PCIE_PROPRIETARY;
776
777 if (_kp2pCapsGetStatusOverPcieBar1(gpuMask, &bar1P2PWriteCapStatus,
778 &bar1P2PReadCapStatus, bCommonSwitchFound) == NV_OK)
779 {
780 *pP2PWriteCapStatus = bar1P2PWriteCapStatus;
781 *pP2PReadCapStatus = bar1P2PReadCapStatus;
782 *pConnectivity = P2P_CONNECTIVITY_PCIE_BAR1;
783 }
784
785 return NV_OK;
786 }
787 }
788
789 return NV_OK;
790 }
791
792 static NV_STATUS
_removeP2PPeerGpuCapsByGpuId(OBJGPU * pGpu,NvU32 peerGpuId)793 _removeP2PPeerGpuCapsByGpuId
794 (
795 OBJGPU *pGpu,
796 NvU32 peerGpuId
797 )
798 {
799 GPU_P2P_PEER_GPU_CAPS *pLocalPeerCaps = NULL;
800
801 pLocalPeerCaps = gpuFindP2PPeerGpuCapsByGpuId(pGpu, peerGpuId);
802 NV_CHECK_OR_RETURN(LEVEL_WARNING, pLocalPeerCaps != NULL, NV_ERR_OBJECT_NOT_FOUND);
803
804 // Swap the target element with the last element and remove the last.
805 // pLocalPeerCaps points to an item in the pGpu->P2PPeerGpuCaps array.
806 NV_ASSERT(pGpu->P2PPeerGpuCount != 0);
807 pGpu->P2PPeerGpuCount--;
808
809 portMemMove(pLocalPeerCaps,
810 sizeof(GPU_P2P_PEER_GPU_CAPS),
811 &pGpu->P2PPeerGpuCaps[pGpu->P2PPeerGpuCount],
812 sizeof(GPU_P2P_PEER_GPU_CAPS));
813
814 return NV_OK;
815 }
816
817 NV_STATUS
subdeviceCtrlCmdInternalSetP2pCaps_IMPL(Subdevice * pSubdevice,NV2080_CTRL_INTERNAL_SET_P2P_CAPS_PARAMS * pParams)818 subdeviceCtrlCmdInternalSetP2pCaps_IMPL
819 (
820 Subdevice *pSubdevice,
821 NV2080_CTRL_INTERNAL_SET_P2P_CAPS_PARAMS *pParams
822 )
823 {
824 NV_STATUS status = NV_OK;
825 NvU32 i;
826 NvU32 failingIndex;
827 OBJGPU *pGpu = gpumgrGetGpuFromSubDeviceInst(pSubdevice->deviceInst,
828 pSubdevice->subDeviceInst);
829
830 // TODO: GPUSWSEC-1433 remove this check to enable this control for baremetal
831 if (!IS_VGPU_GSP_PLUGIN_OFFLOAD_ENABLED(pGpu))
832 return NV_ERR_NOT_SUPPORTED;
833
834 NV_CHECK_OR_RETURN(LEVEL_ERROR,
835 pParams->peerGpuCount <= NV_ARRAY_ELEMENTS(pGpu->P2PPeerGpuCaps),
836 NV_ERR_INVALID_ARGUMENT);
837
838 for (i = 0; i < pParams->peerGpuCount; i++)
839 {
840 NV2080_CTRL_INTERNAL_SET_P2P_CAPS_PEER_INFO *pParamsPeerInfo = &pParams->peerGpuInfos[i];
841 GPU_P2P_PEER_GPU_CAPS *pLocalPeerCaps = NULL;
842
843 // Try to find the existing entry
844 pLocalPeerCaps = gpuFindP2PPeerGpuCapsByGpuId(pGpu, pParamsPeerInfo->gpuId);
845
846 // If no entry has been found, add a new one instead
847 if (pLocalPeerCaps == NULL)
848 {
849 NV_CHECK_OR_ELSE(LEVEL_ERROR,
850 pGpu->P2PPeerGpuCount < NV_ARRAY_ELEMENTS(pGpu->P2PPeerGpuCaps),
851 status = NV_ERR_INSUFFICIENT_RESOURCES; goto fail);
852
853 pLocalPeerCaps = &pGpu->P2PPeerGpuCaps[pGpu->P2PPeerGpuCount];
854 pLocalPeerCaps->peerGpuId = pParamsPeerInfo->gpuId;
855
856 pGpu->P2PPeerGpuCount++;
857 }
858
859 pLocalPeerCaps->peerGpuInstance = pParamsPeerInfo->gpuInstance;
860 pLocalPeerCaps->p2pCaps = pParamsPeerInfo->p2pCaps;
861 pLocalPeerCaps->p2pOptimalReadCEs = pParamsPeerInfo->p2pOptimalReadCEs;
862 pLocalPeerCaps->p2pOptimalWriteCEs = pParamsPeerInfo->p2pOptimalWriteCEs;
863 pLocalPeerCaps->busPeerId = pParamsPeerInfo->busPeerId;
864
865 portMemCopy(pLocalPeerCaps->p2pCapsStatus,
866 sizeof(pLocalPeerCaps->p2pCapsStatus),
867 pParamsPeerInfo->p2pCapsStatus,
868 sizeof(pParamsPeerInfo->p2pCapsStatus));
869 }
870
871 goto done;
872
873 fail:
874 // Remove the successfully set caps
875 failingIndex = i;
876 for (i = 0; i < failingIndex; i++)
877 {
878 NV_STATUS ignoredStatus;
879 NV_CHECK_OK(ignoredStatus, LEVEL_ERROR,
880 _removeP2PPeerGpuCapsByGpuId(pGpu, pParams->peerGpuInfos[i].gpuId));
881 }
882
883 done:
884 return status;
885 }
886
887 NV_STATUS
subdeviceCtrlCmdInternalRemoveP2pCaps_IMPL(Subdevice * pSubdevice,NV2080_CTRL_INTERNAL_REMOVE_P2P_CAPS_PARAMS * pParams)888 subdeviceCtrlCmdInternalRemoveP2pCaps_IMPL
889 (
890 Subdevice *pSubdevice,
891 NV2080_CTRL_INTERNAL_REMOVE_P2P_CAPS_PARAMS *pParams
892 )
893 {
894 NV_STATUS status = NV_OK;
895 NvU32 i;
896 OBJGPU *pGpu = gpumgrGetGpuFromSubDeviceInst(pSubdevice->deviceInst,
897 pSubdevice->subDeviceInst);
898
899 // TODO: GPUSWSEC-1433 remove this check to enable this control for baremetal
900 if (!IS_VGPU_GSP_PLUGIN_OFFLOAD_ENABLED(pGpu))
901 return NV_ERR_NOT_SUPPORTED;
902
903 NV_CHECK_OR_RETURN(LEVEL_ERROR,
904 pParams->peerGpuIdCount <= NV_ARRAY_ELEMENTS(pGpu->P2PPeerGpuCaps),
905 NV_ERR_INVALID_ARGUMENT);
906
907 for (i = 0; i < pParams->peerGpuIdCount; i++)
908 {
909 // Capture only the first error here, as trying to remove all caps
910 // is the best effort here.
911 NV_CHECK_OK_OR_CAPTURE_FIRST_ERROR(status, LEVEL_ERROR,
912 _removeP2PPeerGpuCapsByGpuId(pGpu, pParams->peerGpuIds[i]));
913 }
914
915 return status;
916 }
917
918 static NV_STATUS
subdeviceGetP2pCaps_VIRTUAL(OBJGPU * pGpu,NV2080_CTRL_GET_P2P_CAPS_PARAMS * pParams)919 subdeviceGetP2pCaps_VIRTUAL
920 (
921 OBJGPU *pGpu,
922 NV2080_CTRL_GET_P2P_CAPS_PARAMS *pParams
923 )
924 {
925 NvU32 i;
926 NV_STATUS status = NV_OK;
927 CALL_CONTEXT *pCallContext = resservGetTlsCallContext();
928 RS_RES_CONTROL_PARAMS_INTERNAL *pControlParams = pCallContext->pControlParams;
929 NV2080_CTRL_GET_P2P_CAPS_PARAMS *pShimParams =
930 portMemAllocNonPaged(sizeof *pShimParams);
931
932 NV_CHECK_OR_RETURN(LEVEL_INFO, pShimParams != NULL, NV_ERR_NO_MEMORY);
933
934 portMemCopy(pShimParams, sizeof *pShimParams, pParams, sizeof *pParams);
935
936 if (!pShimParams->bAllCaps)
937 {
938 // Must translate Guest GpuIds to Guest UUIDs
939 for (i = 0; i < pShimParams->peerGpuCount; i++)
940 {
941 NV2080_CTRL_GPU_P2P_PEER_CAPS_PEER_INFO *pParamsPeerInfo = &pShimParams->peerGpuCaps[i];
942 OBJGPU *pRemoteGpu = gpumgrGetGpuFromId(pParamsPeerInfo->gpuId);
943
944 NV_CHECK_OR_ELSE(LEVEL_INFO, pRemoteGpu != NULL,
945 status = NV_ERR_INVALID_ARGUMENT; goto done);
946
947 portMemCopy(pParamsPeerInfo->gpuUuid,
948 sizeof(pParamsPeerInfo->gpuUuid),
949 pRemoteGpu->gpuUuid.uuid,
950 sizeof(pRemoteGpu->gpuUuid.uuid));
951 }
952 }
953
954 pShimParams->bUseUuid = 1;
955
956 NV_RM_RPC_CONTROL(pGpu,
957 pControlParams->hClient,
958 pControlParams->hObject,
959 pControlParams->cmd,
960 pShimParams,
961 sizeof *pShimParams,
962 status);
963 if (status != NV_OK)
964 {
965 goto done;
966 }
967
968 // If bAllCaps, transfer additional output gpuIds and peerGpuCount
969 if (pParams->bAllCaps)
970 {
971 pParams->peerGpuCount = pShimParams->peerGpuCount;
972
973 for (i = 0; i < pParams->peerGpuCount; ++i)
974 {
975 // Use UUID to compute corresponding Guest GPU ID
976 OBJGPU *pRemoteGpu = gpumgrGetGpuFromUuid(pShimParams->peerGpuCaps[i].gpuUuid,
977 DRF_DEF(2080_GPU_CMD, _GPU_GET_GID_FLAGS, _TYPE, _SHA1) |
978 DRF_DEF(2080_GPU_CMD, _GPU_GET_GID_FLAGS, _FORMAT, _BINARY));
979
980 NV_CHECK_OR_ELSE(LEVEL_INFO, pRemoteGpu != NULL,
981 status = NV_ERR_GPU_UUID_NOT_FOUND; goto done);
982
983 pParams->peerGpuCaps[i].gpuId = pRemoteGpu->gpuId;
984 }
985 }
986
987 // Transfer output values from shimParams to user params.
988 for (i = 0; i < pParams->peerGpuCount; ++i)
989 {
990 pParams->peerGpuCaps[i].p2pCaps = pShimParams->peerGpuCaps[i].p2pCaps;
991 pParams->peerGpuCaps[i].p2pOptimalReadCEs = pShimParams->peerGpuCaps[i].p2pOptimalReadCEs;
992 pParams->peerGpuCaps[i].p2pOptimalWriteCEs = pShimParams->peerGpuCaps[i].p2pOptimalWriteCEs;
993 portMemCopy(pParams->peerGpuCaps[i].p2pCapsStatus,
994 sizeof(pParams->peerGpuCaps[i].p2pCapsStatus),
995 pShimParams->peerGpuCaps[i].p2pCapsStatus,
996 sizeof(pShimParams->peerGpuCaps[i].p2pCapsStatus));
997 pParams->peerGpuCaps[i].busPeerId = pShimParams->peerGpuCaps[i].busPeerId;
998 }
999
1000 done:
1001 portMemFree(pShimParams);
1002
1003 return status;
1004 }
1005
1006 NV_STATUS
subdeviceCtrlCmdGetP2pCaps_IMPL(Subdevice * pSubdevice,NV2080_CTRL_GET_P2P_CAPS_PARAMS * pParams)1007 subdeviceCtrlCmdGetP2pCaps_IMPL
1008 (
1009 Subdevice *pSubdevice,
1010 NV2080_CTRL_GET_P2P_CAPS_PARAMS *pParams
1011 )
1012 {
1013 NvU32 i;
1014 NvU32 gfid = GPU_GFID_PF;
1015 OBJGPU *pGpu = gpumgrGetGpuFromSubDeviceInst(pSubdevice->deviceInst,
1016 pSubdevice->subDeviceInst);
1017
1018 // TODO: GPUSWSEC-1433 remove this check to enable this control for baremetal
1019 if (!IS_VGPU_GSP_PLUGIN_OFFLOAD_ENABLED(pGpu))
1020 return NV_ERR_NOT_SUPPORTED;
1021
1022 NV_CHECK_OR_RETURN(LEVEL_ERROR, pGpu != NULL, NV_ERR_INVALID_STATE);
1023 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, vgpuGetCallingContextGfid(pGpu, &gfid));
1024
1025 NV_CHECK_OR_RETURN(LEVEL_ERROR,
1026 (pParams->bAllCaps ||
1027 (pParams->peerGpuCount <= NV_ARRAY_ELEMENTS(pGpu->P2PPeerGpuCaps))),
1028 NV_ERR_INVALID_ARGUMENT);
1029
1030 NV_CHECK_OR_RETURN(LEVEL_ERROR, (pParams->bUseUuid == NV_FALSE), NV_ERR_NOT_SUPPORTED);
1031
1032 if (IS_VIRTUAL(pGpu))
1033 {
1034 return subdeviceGetP2pCaps_VIRTUAL(pGpu, pParams);
1035 }
1036
1037 NV_CHECK_OR_RETURN(LEVEL_ERROR, RMCFG_FEATURE_PLATFORM_GSP, NV_ERR_NOT_SUPPORTED);
1038
1039 if (pParams->bAllCaps)
1040 {
1041 pParams->peerGpuCount = pGpu->P2PPeerGpuCount;
1042
1043 for (i = 0; i < pParams->peerGpuCount; i++)
1044 {
1045 pParams->peerGpuCaps[i].gpuId = pGpu->P2PPeerGpuCaps[i].peerGpuId;
1046 }
1047 }
1048
1049 for (i = 0; i < pParams->peerGpuCount; i++)
1050 {
1051 NV2080_CTRL_GPU_P2P_PEER_CAPS_PEER_INFO *pParamsPeerInfo = &pParams->peerGpuCaps[i];
1052 GPU_P2P_PEER_GPU_CAPS *pLocalPeerCaps = NULL;
1053
1054 pLocalPeerCaps = gpuFindP2PPeerGpuCapsByGpuId(pGpu, pParamsPeerInfo->gpuId);
1055 NV_CHECK_OR_RETURN(LEVEL_ERROR, pLocalPeerCaps != NULL, NV_ERR_OBJECT_NOT_FOUND);
1056
1057 //
1058 // TODO: Currently, vGPU-GSP Guest only supports NVLINK DIRECT so unset caps for other modes.
1059 // May remove once vGPU adds support for other modes.
1060 //
1061 if (IS_GFID_VF(gfid) &&
1062 !REF_VAL(NV0000_CTRL_SYSTEM_GET_P2P_CAPS_NVLINK_SUPPORTED, pLocalPeerCaps->p2pCaps))
1063 {
1064 pParamsPeerInfo->p2pCaps = 0;
1065 pParamsPeerInfo->p2pOptimalReadCEs = 0;
1066 pParamsPeerInfo->p2pOptimalWriteCEs = 0;
1067 pParamsPeerInfo->busPeerId = NV0000_CTRL_SYSTEM_GET_P2P_CAPS_INVALID_PEER;
1068
1069 portMemSet(pParamsPeerInfo->p2pCapsStatus,
1070 NV0000_P2P_CAPS_STATUS_NOT_SUPPORTED,
1071 sizeof(pParamsPeerInfo->p2pCapsStatus));
1072 }
1073 else
1074 {
1075 pParamsPeerInfo->p2pCaps = pLocalPeerCaps->p2pCaps;
1076 pParamsPeerInfo->p2pOptimalReadCEs = pLocalPeerCaps->p2pOptimalReadCEs;
1077 pParamsPeerInfo->p2pOptimalWriteCEs = pLocalPeerCaps->p2pOptimalWriteCEs;
1078 pParamsPeerInfo->busPeerId = pLocalPeerCaps->busPeerId;
1079
1080 portMemCopy(pParamsPeerInfo->p2pCapsStatus,
1081 sizeof(pParamsPeerInfo->p2pCapsStatus),
1082 pLocalPeerCaps->p2pCapsStatus,
1083 sizeof(pLocalPeerCaps->p2pCapsStatus));
1084 }
1085 }
1086
1087 return NV_OK;
1088 }
1089