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