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