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