1 /* 2 * SPDX-FileCopyrightText: Copyright (c) 2004-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 /*! 25 * @file 26 * @brief This module contains the gpu control interfaces for the 27 * subdevice (NV20_SUBDEVICE_0) class. Subdevice-level control calls 28 * are directed unicast to the associated GPU. 29 * File contains ctrls related to general GPU 30 */ 31 32 #include "core/core.h" 33 #include "core/locks.h" 34 #include "gpu/subdevice/subdevice.h" 35 #include "gpu/gpu.h" 36 #include "gpu_mgr/gpu_db.h" 37 #include "nvrm_registry.h" 38 #include "nvVer.h" 39 #include "gpu/bif/kernel_bif.h" 40 #include "gpu/bus/kern_bus.h" 41 #include "gpu/disp/kern_disp.h" 42 #include "disp/nvfbc_session.h" 43 #include "gpu/mmu/kern_gmmu.h" 44 #include "kernel/gpu/intr/intr.h" 45 #include "kernel/gpu/mc/kernel_mc.h" 46 #include "kernel/gpu/nvlink/kernel_nvlink.h" 47 #include "gpu/gpu_fabric_probe.h" 48 #include "objtmr.h" 49 #include "platform/chipset/chipset.h" 50 #include "kernel/gpu/gr/kernel_graphics.h" 51 #include "kernel/gpu/mig_mgr/kernel_mig_manager.h" 52 #include "kernel/gpu/gr/kernel_graphics_manager.h" 53 #include "vgpu/rpc.h" 54 #include "gpu/mem_mgr/mem_mgr.h" 55 56 #include "gpu/mem_sys/kern_mem_sys.h" 57 #include "gpu/nvenc/nvencsession.h" 58 59 #include "kernel/gpu/fifo/kernel_fifo.h" 60 #include "rmapi/resource_fwd_decls.h" 61 #include "rmapi/client.h" 62 63 #include "class/cl900e.h" 64 65 66 67 // bit to set when telling physical to fill in an info entry 68 #define INDEX_FORWARD_TO_PHYSICAL 0x80000000 69 70 static NV_STATUS 71 getGpuInfos(Subdevice *pSubdevice, NV2080_CTRL_GPU_GET_INFO_V2_PARAMS *pParams, NvBool bCanAccessHw) 72 { 73 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 74 NV_STATUS status = NV_OK; 75 NvU32 i = 0; 76 NvU32 data = 0; 77 NvBool bPhysicalForward = NV_FALSE; 78 79 if ((pParams->gpuInfoListSize > NV2080_CTRL_GPU_INFO_MAX_LIST_SIZE) || 80 (pParams->gpuInfoListSize == 0)) 81 { 82 return NV_ERR_INVALID_ARGUMENT; 83 } 84 85 for (i = 0; i < pParams->gpuInfoListSize; i++) 86 { 87 if (pParams->gpuInfoList[i].index >= NV2080_CTRL_GPU_INFO_MAX_LIST_SIZE) 88 { 89 return NV_ERR_INVALID_ARGUMENT; 90 } 91 92 switch (pParams->gpuInfoList[i].index) 93 { 94 case NV2080_CTRL_GPU_INFO_INDEX_GPU_FLA_CAPABILITY: 95 { 96 KernelBus *pKernelBus = GPU_GET_KERNEL_BUS(pGpu); 97 98 if (kbusIsFlaSupported(pKernelBus)) 99 { 100 data = NV2080_CTRL_GPU_INFO_INDEX_GPU_FLA_CAPABILITY_YES; 101 } 102 else 103 { 104 data = NV2080_CTRL_GPU_INFO_INDEX_GPU_FLA_CAPABILITY_NO; 105 } 106 break; 107 } 108 case NV2080_CTRL_GPU_INFO_INDEX_MINOR_REVISION_EXT: 109 { 110 data = gpuGetChipMinExtRev(pGpu); 111 break; 112 } 113 case NV2080_CTRL_GPU_INFO_INDEX_NETLIST_REV0: 114 { 115 data = 0; 116 break; 117 } 118 case NV2080_CTRL_GPU_INFO_INDEX_NETLIST_REV1: 119 { 120 data = 0; 121 break; 122 } 123 case NV2080_CTRL_GPU_INFO_INDEX_SYSMEM_ACCESS: 124 { 125 data = NV2080_CTRL_GPU_INFO_SYSMEM_ACCESS_YES; 126 break; 127 } 128 case NV2080_CTRL_GPU_INFO_INDEX_GEMINI_BOARD: 129 { 130 data = !!pGpu->getProperty(pGpu, PDB_PROP_GPU_IS_GEMINI); 131 break; 132 } 133 case NV2080_CTRL_GPU_INFO_INDEX_SURPRISE_REMOVAL_POSSIBLE: 134 { 135 OBJSYS *pSys = SYS_GET_INSTANCE(); 136 OBJCL *pCl = SYS_GET_CL(pSys); 137 data = !!pCl->getProperty(pCl, PDB_PROP_CL_IS_EXTERNAL_GPU); 138 break; 139 } 140 case NV2080_CTRL_GPU_INFO_INDEX_IBMNPU_RELAXED_ORDERING: 141 { 142 NvBool mode = NV_FALSE; 143 data = NV2080_CTRL_GPU_INFO_IBMNPU_RELAXED_ORDERING_UNSUPPORTED; 144 145 if (osGetIbmnpuRelaxedOrderingMode(pGpu->pOsGpuInfo, &mode) == NV_OK) 146 { 147 data = NV2080_CTRL_GPU_INFO_IBMNPU_RELAXED_ORDERING_DISABLED; 148 149 if (mode) 150 { 151 data = NV2080_CTRL_GPU_INFO_IBMNPU_RELAXED_ORDERING_ENABLED; 152 } 153 } 154 break; 155 } 156 case NV2080_CTRL_GPU_INFO_INDEX_GLOBAL_POISON_FUSE_ENABLED: 157 { 158 if (gpuIsGlobalPoisonFuseEnabled(pGpu)) 159 { 160 data = NV2080_CTRL_GPU_INFO_INDEX_GLOBAL_POISON_FUSE_ENABLED_YES; 161 } 162 else 163 { 164 data = NV2080_CTRL_GPU_INFO_INDEX_GLOBAL_POISON_FUSE_ENABLED_NO; 165 } 166 break; 167 } 168 case NV2080_CTRL_GPU_INFO_INDEX_NVSWITCH_PROXY_DETECTED: 169 { 170 NV_CHECK_OR_ELSE(LEVEL_WARNING, bCanAccessHw, 171 { data = 0; status = NV_ERR_INVALID_ARGUMENT; break; }); 172 173 KernelNvlink *pKernelNvlink = GPU_GET_KERNEL_NVLINK(pGpu); 174 175 data = NV2080_CTRL_GPU_INFO_NVSWITCH_PROXY_DETECTED_NO; 176 177 if (pKernelNvlink != NULL && 178 knvlinkIsNvswitchProxyPresent(pGpu, pKernelNvlink)) 179 { 180 data = NV2080_CTRL_GPU_INFO_NVSWITCH_PROXY_DETECTED_YES; 181 } 182 break; 183 } 184 case NV2080_CTRL_GPU_INFO_INDEX_GPU_SMC_MODE: 185 { 186 NV_CHECK_OR_ELSE(LEVEL_WARNING, bCanAccessHw, 187 { data = 0; status = NV_ERR_INVALID_ARGUMENT; break; }); 188 189 RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu); 190 NV2080_CTRL_INTERNAL_GPU_GET_SMC_MODE_PARAMS params; 191 192 if (IS_VIRTUAL(pGpu)) 193 { 194 KernelMIGManager *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu); 195 196 if ((pKernelMIGManager == NULL) || !kmigmgrIsMIGSupported(pGpu, pKernelMIGManager)) 197 { 198 data = NV2080_CTRL_GPU_INFO_GPU_SMC_MODE_UNSUPPORTED; 199 break; 200 } 201 202 data = IS_MIG_ENABLED(pGpu) ? 203 NV2080_CTRL_GPU_INFO_GPU_SMC_MODE_ENABLED : 204 NV2080_CTRL_GPU_INFO_GPU_SMC_MODE_DISABLED; 205 206 break; 207 } 208 209 portMemSet(¶ms, 0x0, sizeof(params)); 210 status = pRmApi->Control(pRmApi, 211 pGpu->hInternalClient, 212 pGpu->hInternalSubdevice, 213 NV2080_CTRL_CMD_INTERNAL_GPU_GET_SMC_MODE, 214 ¶ms, 215 sizeof(params)); 216 data = params.smcMode; 217 break; 218 } 219 case NV2080_CTRL_GPU_INFO_INDEX_SPLIT_VAS_MGMT_SERVER_CLIENT_RM: 220 { 221 if (gpuIsSplitVasManagementServerClientRmEnabled(pGpu)) 222 { 223 data = NV2080_CTRL_GPU_INFO_SPLIT_VAS_MGMT_SERVER_CLIENT_RM_YES; 224 } 225 else 226 { 227 data = NV2080_CTRL_GPU_INFO_SPLIT_VAS_MGMT_SERVER_CLIENT_RM_NO; 228 } 229 break; 230 } 231 case NV2080_CTRL_GPU_INFO_INDEX_GPU_SM_VERSION: 232 { 233 KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu); 234 235 if ((pKernelGraphicsManager == NULL) || 236 !kgrmgrGetLegacyKGraphicsStaticInfo(pGpu, pKernelGraphicsManager)->bInitialized || 237 (kgrmgrGetLegacyKGraphicsStaticInfo(pGpu, pKernelGraphicsManager)->pGrInfo == NULL)) 238 { 239 NV_PRINTF(LEVEL_ERROR, "Unable to retrieve SM version!\n"); 240 data = NV2080_CTRL_GR_INFO_SM_VERSION_NONE; 241 status = NV_ERR_INVALID_STATE; 242 } 243 else 244 { 245 data = kgrmgrGetLegacyKGraphicsStaticInfo(pGpu, pKernelGraphicsManager)->pGrInfo->infoList[NV2080_CTRL_GR_INFO_INDEX_SM_VERSION].data; 246 } 247 break; 248 } 249 case NV2080_CTRL_GPU_INFO_INDEX_PER_RUNLIST_CHANNEL_RAM: 250 { 251 KernelFifo *pKernelFifo = GPU_GET_KERNEL_FIFO(pGpu); 252 253 if (kfifoIsPerRunlistChramEnabled(pKernelFifo)) 254 { 255 data = NV2080_CTRL_GPU_INFO_INDEX_PER_RUNLIST_CHANNEL_RAM_ENABLED; 256 } 257 else 258 { 259 data = NV2080_CTRL_GPU_INFO_INDEX_PER_RUNLIST_CHANNEL_RAM_DISABLED; 260 } 261 break; 262 } 263 case NV2080_CTRL_GPU_INFO_INDEX_GPU_ATS_CAPABILITY: 264 { 265 if (pGpu->getProperty(pGpu, PDB_PROP_GPU_ATS_SUPPORTED)) 266 { 267 data = NV2080_CTRL_GPU_INFO_INDEX_GPU_ATS_CAPABILITY_YES; 268 } 269 else 270 { 271 data = NV2080_CTRL_GPU_INFO_INDEX_GPU_ATS_CAPABILITY_NO; 272 } 273 break; 274 } 275 case NV2080_CTRL_GPU_INFO_INDEX_NVENC_STATS_REPORTING_STATE: 276 { 277 if (IS_VIRTUAL(pGpu)) 278 { 279 // On vGPU, if encoding is supported then we need to keep the NvEnc stats reporting state enabled 280 // all the time so that NvEnc UMD keeps pushing the raw timestamp data. 281 // This is to handle the migration case where on source host the NvEnc stats reporting was disabled, 282 // but on target host the NvEnc stats reporting is enabled. If UMD doesn't keep pushing raw data 283 // even if stats reporting was disabled on source host, we won't be able to report NvEnc stats on 284 // target host data reporting is enabled. 285 if (pGpu->encSessionStatsReportingState == NV2080_CTRL_GPU_INFO_NVENC_STATS_REPORTING_STATE_NOT_SUPPORTED) 286 { 287 data = NV2080_CTRL_GPU_INFO_NVENC_STATS_REPORTING_STATE_NOT_SUPPORTED; 288 } 289 else 290 { 291 data = NV2080_CTRL_GPU_INFO_NVENC_STATS_REPORTING_STATE_ENABLED; 292 } 293 } 294 else 295 { 296 data = pGpu->encSessionStatsReportingState; 297 } 298 break; 299 } 300 case NV2080_CTRL_GPU_INFO_INDEX_4K_PAGE_ISOLATION_REQUIRED: 301 { 302 if (pGpu->bNeed4kPageIsolation) 303 { 304 data = NV2080_CTRL_GPU_INFO_INDEX_4K_PAGE_ISOLATION_REQUIRED_YES; 305 } 306 else 307 { 308 data = NV2080_CTRL_GPU_INFO_INDEX_4K_PAGE_ISOLATION_REQUIRED_NO; 309 } 310 break; 311 } 312 case NV2080_CTRL_GPU_INFO_INDEX_DISPLAY_ENABLED: 313 { 314 if (GPU_GET_KERNEL_DISPLAY(pGpu) != NULL) 315 { 316 data = NV2080_CTRL_GPU_INFO_DISPLAY_ENABLED_YES; 317 } 318 else 319 { 320 data = NV2080_CTRL_GPU_INFO_DISPLAY_ENABLED_NO; 321 } 322 break; 323 } 324 case NV2080_CTRL_GPU_INFO_INDEX_MOBILE_CONFIG_ENABLED: 325 { 326 if (IsMobile(pGpu)) 327 { 328 data = NV2080_CTRL_GPU_INFO_INDEX_MOBILE_CONFIG_ENABLED_YES; 329 } 330 else 331 { 332 data = NV2080_CTRL_GPU_INFO_INDEX_MOBILE_CONFIG_ENABLED_NO; 333 } 334 break; 335 } 336 case NV2080_CTRL_GPU_INFO_INDEX_GPU_PROFILING_CAPABILITY: 337 { 338 if (IS_VIRTUAL(pGpu)) 339 { 340 VGPU_STATIC_INFO *pVSI = GPU_GET_STATIC_INFO(pGpu); 341 if (pVSI) 342 { 343 data = pVSI->vgpuStaticProperties.bProfilingTracingEnabled ? 344 NV2080_CTRL_GPU_INFO_INDEX_GPU_PROFILING_CAPABILITY_ENABLED : 345 NV2080_CTRL_GPU_INFO_INDEX_GPU_PROFILING_CAPABILITY_DISABLED; 346 } 347 else 348 { 349 data = NV2080_CTRL_GPU_INFO_INDEX_GPU_PROFILING_CAPABILITY_DISABLED; 350 } 351 } 352 else 353 { 354 // Always return ENABLED for Baremetal/Host 355 data = NV2080_CTRL_GPU_INFO_INDEX_GPU_PROFILING_CAPABILITY_ENABLED; 356 } 357 break; 358 } 359 case NV2080_CTRL_GPU_INFO_INDEX_GPU_DEBUGGING_CAPABILITY: 360 { 361 if (IS_VIRTUAL(pGpu)) 362 { 363 VGPU_STATIC_INFO *pVSI = GPU_GET_STATIC_INFO(pGpu); 364 if (pVSI) 365 { 366 data = pVSI->vgpuStaticProperties.bDebuggingEnabled ? 367 NV2080_CTRL_GPU_INFO_INDEX_GPU_DEBUGGING_CAPABILITY_ENABLED : 368 NV2080_CTRL_GPU_INFO_INDEX_GPU_DEBUGGING_CAPABILITY_DISABLED; 369 } 370 else 371 { 372 data = NV2080_CTRL_GPU_INFO_INDEX_GPU_DEBUGGING_CAPABILITY_DISABLED; 373 } 374 } 375 else 376 { 377 // Always return ENABLED for Baremetal/Host 378 data = NV2080_CTRL_GPU_INFO_INDEX_GPU_DEBUGGING_CAPABILITY_ENABLED; 379 } 380 break; 381 } 382 case NV2080_CTRL_GPU_INFO_INDEX_GPU_LOCAL_EGM_CAPABILITY: 383 { 384 MemoryManager *pMemoryManager = GPU_GET_MEMORY_MANAGER(pGpu); 385 if (memmgrIsLocalEgmEnabled(pMemoryManager)) 386 { 387 data = NV2080_CTRL_GPU_INFO_INDEX_GPU_LOCAL_EGM_CAPABILITY_YES; 388 data = FLD_SET_DRF_NUM(2080_CTRL_GPU_INFO, _INDEX_GPU_LOCAL_EGM, _PEERID, pMemoryManager->localEgmPeerId, data); 389 } 390 else 391 { 392 data = NV2080_CTRL_GPU_INFO_INDEX_GPU_LOCAL_EGM_CAPABILITY_NO; 393 } 394 break; 395 } 396 case NV2080_CTRL_GPU_INFO_INDEX_GPU_SELF_HOSTED_CAPABILITY: 397 { 398 KernelBif *pKernelBif = GPU_GET_KERNEL_BIF(pGpu); 399 400 if (gpuIsSelfHosted(pGpu) && 401 pKernelBif->getProperty(pKernelBif, PDB_PROP_KBIF_IS_C2C_LINK_UP)) 402 { 403 data = NV2080_CTRL_GPU_INFO_INDEX_GPU_SELF_HOSTED_CAPABILITY_YES; 404 } 405 else 406 { 407 data = NV2080_CTRL_GPU_INFO_INDEX_GPU_SELF_HOSTED_CAPABILITY_NO; 408 } 409 break; 410 } 411 case NV2080_CTRL_GPU_INFO_INDEX_CMP_SKU: 412 { 413 if (gpuGetChipInfo(pGpu) && gpuGetChipInfo(pGpu)->isCmpSku) 414 { 415 data = NV2080_CTRL_GPU_INFO_INDEX_CMP_SKU_YES; 416 } 417 else 418 { 419 data = NV2080_CTRL_GPU_INFO_INDEX_CMP_SKU_NO; 420 } 421 break; 422 } 423 case NV2080_CTRL_GPU_INFO_INDEX_DMABUF_CAPABILITY: 424 { 425 data = NV2080_CTRL_GPU_INFO_INDEX_DMABUF_CAPABILITY_NO; 426 427 if (osDmabufIsSupported() && 428 (!IS_VIRTUAL(pGpu)) && 429 (!gpuIsApmFeatureEnabled(pGpu)) && 430 (!NVCPU_IS_PPC64LE)) 431 { 432 data = NV2080_CTRL_GPU_INFO_INDEX_DMABUF_CAPABILITY_YES; 433 } 434 break; 435 } 436 case NV2080_CTRL_GPU_INFO_INDEX_IS_RESETLESS_MIG_SUPPORTED: 437 { 438 data = NV2080_CTRL_GPU_INFO_INDEX_IS_RESETLESS_MIG_SUPPORTED_NO; 439 440 if (pGpu->getProperty(pGpu, PDB_PROP_GPU_RESETLESS_MIG_SUPPORTED)) 441 { 442 data = NV2080_CTRL_GPU_INFO_INDEX_IS_RESETLESS_MIG_SUPPORTED_YES; 443 } 444 break; 445 } 446 default: 447 { 448 // Only forward to physical if we're in the HW-access-enabled control 449 if ((IS_GSP_CLIENT(pGpu) || IS_VIRTUAL(pGpu)) && bCanAccessHw) 450 { 451 pParams->gpuInfoList[i].index |= INDEX_FORWARD_TO_PHYSICAL; 452 bPhysicalForward = NV_TRUE; 453 } 454 else 455 { 456 data = 0; 457 status = NV_ERR_INVALID_ARGUMENT; 458 } 459 break; 460 } 461 } 462 463 if (status != NV_OK) 464 { 465 break; 466 } 467 468 // save off data value 469 pParams->gpuInfoList[i].data = data; 470 } 471 472 if ((IS_GSP_CLIENT(pGpu) || IS_VIRTUAL(pGpu)) && bPhysicalForward && (status == NV_OK)) 473 { 474 NV_RM_RPC_CONTROL(pGpu, 475 RES_GET_CLIENT_HANDLE(pSubdevice), 476 RES_GET_HANDLE(pSubdevice), 477 NV2080_CTRL_CMD_GPU_GET_INFO_V2, 478 pParams, sizeof(*pParams), status); 479 } 480 481 return status; 482 } 483 484 #undef INDEX_FORWARD_TO_PHYSICAL 485 486 NV_STATUS 487 subdeviceCtrlCmdGpuGetInfoV2_IMPL 488 ( 489 Subdevice *pSubdevice, 490 NV2080_CTRL_GPU_GET_INFO_V2_PARAMS *pGpuInfoParams 491 ) 492 { 493 return getGpuInfos(pSubdevice, pGpuInfoParams, NV_TRUE); 494 } 495 496 // 497 // subdeviceCtrlCmdGpuGetCachedInfo: As subdeviceCtrlCmdGpuGetInfoV2, except 498 // does not perform any HW access (NO_GPUS_ACCESS and NO_GPUS_LOCK flags) 499 // 500 NV_STATUS 501 subdeviceCtrlCmdGpuGetCachedInfo_IMPL 502 ( 503 Subdevice *pSubdevice, 504 NV2080_CTRL_GPU_GET_INFO_V2_PARAMS *pGpuInfoParams 505 ) 506 { 507 return getGpuInfos(pSubdevice, pGpuInfoParams, NV_FALSE); 508 } 509 510 static POBJHWBC 511 getBridgeObject(OBJHWBC *pHWBC, NvU32 hwbcId) 512 { 513 OBJHWBC *pBridgeObject = NULL; 514 if (NULL != pHWBC) 515 { 516 if (hwbcId == pHWBC->hwbcId) 517 { 518 pBridgeObject = pHWBC; 519 } 520 else 521 { 522 pBridgeObject = getBridgeObject(pHWBC->pSibling, hwbcId); 523 if (NULL == pBridgeObject) 524 { 525 pBridgeObject = getBridgeObject(pHWBC->pFirstChild, hwbcId); 526 } 527 } 528 } 529 return pBridgeObject; 530 } 531 532 static NV_STATUS 533 getPlxFirmwareAndBusInfo 534 ( 535 OBJHWBC *pHWBC, 536 NvU32 *domainId, 537 NvU8 *busId, 538 NvU8 *deviceId, 539 NvU8 *funcId, 540 NvU32 *fwVersion, 541 NvU8 *oemVersion, 542 NvU8 *siliconRevision, 543 NvU8 *bcRes 544 ) 545 { 546 if (NULL == pHWBC) 547 { 548 return NV_ERR_INVALID_ARGUMENT; 549 } 550 551 if (domainId) 552 *domainId = pHWBC->ctrlDev.domain; 553 if (busId) 554 *busId = pHWBC->ctrlDev.bus; 555 if (deviceId) 556 *deviceId = pHWBC->ctrlDev.device; 557 if (funcId) 558 *funcId = pHWBC->ctrlDev.func; 559 if (fwVersion) 560 *fwVersion = pHWBC->fwVersion; 561 if (oemVersion) 562 *oemVersion = pHWBC->fwOemVersion; 563 if (siliconRevision) 564 *siliconRevision = pHWBC->plxRevision; 565 if (bcRes) 566 *bcRes = (NvU8)pHWBC->bcRes; 567 return NV_OK; 568 } 569 570 static NV_STATUS 571 getPlxFirmwareVersion 572 ( 573 NvU32 hwbcId, 574 NvU32 *fwVersion, 575 NvU8 *oemVersion, 576 NvU8 *siliconRevision, 577 NvU8 *bcRes 578 ) 579 { 580 OBJSYS *pSys = SYS_GET_INSTANCE(); 581 OBJCL *pCl = SYS_GET_CL(pSys); 582 OBJHWBC *pHWBC = getBridgeObject(pCl->pHWBC, hwbcId); 583 584 return getPlxFirmwareAndBusInfo(pHWBC, NULL, NULL, NULL, NULL, fwVersion, 585 oemVersion, siliconRevision, bcRes); 586 } 587 588 static NvU8 589 getBridgeCountAndId(OBJHWBC *pHWBC, NvU32 pBridgeId[], NvU32 *bridgeIndex) 590 { 591 NvU8 count = 0; 592 if ((NULL == bridgeIndex) || 593 (*bridgeIndex >= NV2080_CTRL_MAX_PHYSICAL_BRIDGE)) 594 { 595 return count; 596 } 597 if (NULL != pHWBC) 598 { 599 if ((HWBC_PLX_PEX8747 == pHWBC->bcRes) || (HWBC_NVIDIA_BR04 == pHWBC->bcRes)) 600 { 601 pBridgeId[*bridgeIndex] = pHWBC->hwbcId; 602 (*bridgeIndex)++; 603 count++; 604 } 605 count += getBridgeCountAndId(pHWBC->pSibling, pBridgeId, bridgeIndex); 606 count += getBridgeCountAndId(pHWBC->pFirstChild, pBridgeId, bridgeIndex); 607 } 608 return count; 609 } 610 611 static NV_STATUS 612 getBridgeData 613 ( 614 NvU8 *pPlxCount, 615 NvU32 pBridgeId[] 616 ) 617 { 618 OBJSYS *pSys = SYS_GET_INSTANCE(); 619 OBJCL *pCl = SYS_GET_CL(pSys); 620 NvU32 bridgeIndex = 0; 621 622 if (NULL == pPlxCount) 623 { 624 return NV_ERR_INVALID_ARGUMENT; 625 } 626 627 *pPlxCount = getBridgeCountAndId(pCl->pHWBC, pBridgeId, &bridgeIndex); 628 NV_ASSERT_OR_RETURN(*pPlxCount < NV2080_CTRL_MAX_PHYSICAL_BRIDGE, 629 NV_ERR_OUT_OF_RANGE); 630 return NV_OK; 631 } 632 633 static NV_STATUS 634 getUpstreamBridgeIds 635 ( 636 OBJGPU *pGpu, 637 NvU8 *pPlxCount, 638 NvU32 pBridgeId[] 639 ) 640 { 641 HWBC_LIST *pGpuHWBCList; 642 NvU8 bridgeIndex = 0; 643 644 if (NULL == pPlxCount) 645 { 646 return NV_ERR_INVALID_ARGUMENT; 647 } 648 649 pGpuHWBCList = pGpu->pHWBCList; 650 while(pGpuHWBCList) 651 { 652 NV_ASSERT_OR_RETURN(pGpuHWBCList->pHWBC != NULL, NV_ERR_INVALID_POINTER); 653 pBridgeId[bridgeIndex] = pGpuHWBCList->pHWBC->hwbcId; 654 pGpuHWBCList = pGpuHWBCList->pNext; 655 bridgeIndex++; 656 NV_ASSERT_OR_RETURN(bridgeIndex < NV2080_CTRL_MAX_PHYSICAL_BRIDGE, 657 NV_ERR_OUT_OF_RANGE); 658 } 659 *pPlxCount = bridgeIndex; 660 661 return NV_OK; 662 } 663 664 NV_STATUS 665 subdeviceCtrlCmdGpuGetPhysicalBridgeVersionInfo_IMPL 666 ( 667 Subdevice *pSubdevice, 668 NV2080_CTRL_GPU_GET_PHYSICAL_BRIDGE_VERSION_INFO_PARAMS *pBridgeInfoParams 669 ) 670 { 671 NV_STATUS status = NV_OK; 672 NvU8 bridgeIndex; 673 status = getBridgeData(&pBridgeInfoParams->bridgeCount, 674 pBridgeInfoParams->hPhysicalBridges); 675 if (status == NV_OK) 676 { 677 NV2080_CTRL_GPU_PHYSICAL_BRIDGE_VERSION_PARAMS *pBridgeVersionParams = 678 pBridgeInfoParams->bridgeList; 679 for (bridgeIndex = 0; 680 bridgeIndex < pBridgeInfoParams->bridgeCount; 681 bridgeIndex++) 682 { 683 status = getPlxFirmwareVersion(pBridgeInfoParams->hPhysicalBridges[bridgeIndex], 684 &pBridgeVersionParams->fwVersion, 685 &pBridgeVersionParams->oemVersion, 686 &pBridgeVersionParams->siliconRevision, 687 &pBridgeVersionParams->hwbcResourceType); 688 if (status != NV_OK) 689 { 690 break; 691 } 692 pBridgeVersionParams++; 693 } 694 } 695 return status; 696 } 697 698 NV_STATUS 699 subdeviceCtrlCmdGpuGetAllBridgesUpstreamOfGpu_IMPL 700 ( 701 Subdevice *pSubdevice, 702 NV2080_CTRL_GPU_GET_ALL_BRIDGES_UPSTREAM_OF_GPU_PARAMS *pBridgeInfoParams 703 ) 704 { 705 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 706 NV_STATUS status = NV_OK; 707 NvU8 bridgeIndex; 708 HWBC_LIST *pGpuHWBCList; 709 status = getUpstreamBridgeIds(pGpu, 710 &pBridgeInfoParams->bridgeCount, 711 pBridgeInfoParams->physicalBridgeIds); 712 if (status == NV_OK) 713 { 714 NV2080_CTRL_GPU_BRIDGE_VERSION_PARAMS *pBridgeVersionParams = 715 pBridgeInfoParams->bridgeList; 716 pGpuHWBCList = pGpu->pHWBCList; 717 for (bridgeIndex = 0; 718 bridgeIndex < pBridgeInfoParams->bridgeCount && pGpuHWBCList; 719 bridgeIndex++) 720 { 721 status = getPlxFirmwareAndBusInfo(pGpuHWBCList->pHWBC, 722 &pBridgeVersionParams->domain, 723 &pBridgeVersionParams->bus, 724 &pBridgeVersionParams->device, 725 &pBridgeVersionParams->func, 726 &pBridgeVersionParams->fwVersion, 727 &pBridgeVersionParams->oemVersion, 728 &pBridgeVersionParams->siliconRevision, 729 &pBridgeVersionParams->hwbcResourceType); 730 if (status != NV_OK) 731 { 732 break; 733 } 734 pGpuHWBCList = pGpuHWBCList->pNext; 735 pBridgeVersionParams++; 736 } 737 } 738 return status; 739 } 740 741 /*! 742 * @brief This command can be used for Optimus enabled system. 743 * 744 * @return : 745 * NV_OK 746 */ 747 NV_STATUS 748 subdeviceCtrlCmdGpuSetOptimusInfo_IMPL 749 ( 750 Subdevice *pSubdevice, 751 NV2080_CTRL_GPU_OPTIMUS_INFO_PARAMS *pGpuOptimusInfoParams 752 ) 753 { 754 NvU32 status = NV_OK; 755 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 756 757 if (pGpuOptimusInfoParams->isOptimusEnabled) 758 { 759 // 760 // Setting pMemoryManager->bPersistentStandbyBuffer for Optimus system. 761 // It is used for sys_mem allocation which is pinned across 762 // S3 transitions.Sys_mem allocations are done at first S3 cycle 763 // and release during driver unload, which reduces system 764 // VM fragmentation, which was a problem in optimus system. 765 // For more details refer bug 754122. 766 // 767 GPU_GET_MEMORY_MANAGER(pGpu)->bPersistentStandbyBuffer = NV_TRUE; 768 } 769 return status; 770 } 771 772 // RM reports dynamic encoder capacity as a percentage (0-100) of the encoders fixed 773 // capacity. Fixed capacity is readable via NvEncode API and is defined in 774 // drivers/video/encode/src/CNVVAEncoder.cpp#200 775 // 776 // Dynamic capacity of 0x0 indicates that encoder performance may be minimal for this 777 // GPU and software should fall back to CPU-based encode. 778 // 779 780 #define NV_ENC_CAPACITY_MAX_VALUE 100 781 // 782 // subdeviceCtrlCmdGpuGetEncoderCapacity 783 // 784 // Lock Requirements: 785 // Assert that API lock and GPUs lock held on entry 786 // 787 NV_STATUS 788 subdeviceCtrlCmdGpuGetEncoderCapacity_IMPL 789 ( 790 Subdevice *pSubdevice, 791 NV2080_CTRL_GPU_GET_ENCODER_CAPACITY_PARAMS *pEncoderCapacityParams 792 ) 793 { 794 NV_STATUS rmStatus = NV_OK; 795 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 796 NvHandle hClient = RES_GET_CLIENT_HANDLE(pSubdevice); 797 NvHandle hObject = RES_GET_HANDLE(pSubdevice); 798 799 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner()); 800 801 if (pEncoderCapacityParams->queryType == NV2080_CTRL_GPU_GET_ENCODER_CAPACITY_AV1) 802 { 803 if (pGpu->bGpuNvEncAv1Supported == NV_FALSE) 804 { 805 return NV_ERR_NOT_SUPPORTED; 806 } 807 } 808 else if ((pEncoderCapacityParams->queryType != NV2080_CTRL_GPU_GET_ENCODER_CAPACITY_H264) && 809 (pEncoderCapacityParams->queryType != NV2080_CTRL_GPU_GET_ENCODER_CAPACITY_HEVC)) 810 { 811 return NV_ERR_INVALID_ARGUMENT; 812 } 813 814 pEncoderCapacityParams->encoderCapacity = NV_ENC_CAPACITY_MAX_VALUE; 815 816 // 817 // vGPU: Since vGPU does all real hardware management 818 // in the host, there is nothing to do at this point in 819 // the guest OS (where IS_VIRTUAL(pGpu) is true). 820 // 821 if (IS_VIRTUAL(pGpu)) // Otherwise default for vGPU host/baremetal/NMOS/GSP_CLIENT 822 { 823 NV_RM_RPC_GET_ENCODER_CAPACITY(pGpu, 824 hClient, 825 hObject, 826 &pEncoderCapacityParams->encoderCapacity, 827 rmStatus); 828 } 829 return rmStatus; 830 } 831 832 // 833 // subdeviceCtrlCmdGpuGetNvencSwSessionStats 834 // 835 // Lock Requirements: 836 // Assert that API lock and GPUs lock held on entry 837 // 838 NV_STATUS 839 subdeviceCtrlCmdGpuGetNvencSwSessionStats_IMPL 840 ( 841 Subdevice *pSubdevice, 842 NV2080_CTRL_GPU_GET_NVENC_SW_SESSION_STATS_PARAMS *pParams 843 ) 844 { 845 846 NvU32 averageEncodeFps = 0, averageEncodeLatency = 0; 847 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 848 NvencSession *pNvencSession = NULL; 849 PNVENC_SESSION_LIST_ITEM pNvencSessionListItem = NULL; 850 851 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner()); 852 853 // 854 // For GSP vGPU host, get the data from GSP RM for CPU RM and it's client 855 // 856 if (IS_GSP_CLIENT(pGpu) && IS_VGPU_GSP_PLUGIN_OFFLOAD_ENABLED(pGpu)) 857 { 858 CALL_CONTEXT *pCallContext = resservGetTlsCallContext(); 859 RmCtrlParams *pRmCtrlParams = pCallContext->pControlParams; 860 RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu); 861 862 return pRmApi->Control(pRmApi, 863 pRmCtrlParams->hClient, 864 pRmCtrlParams->hObject, 865 pRmCtrlParams->cmd, 866 pRmCtrlParams->pParams, 867 pRmCtrlParams->paramsSize); 868 } 869 870 if (listCount(&(pGpu->nvencSessionList)) == 0) 871 { 872 pParams->encoderSessionCount = 0; 873 pParams->averageEncodeFps = 0; 874 pParams->averageEncodeLatency = 0; 875 return NV_OK; 876 } 877 878 pParams->encoderSessionCount = listCount(&(pGpu->nvencSessionList)); 879 880 for (pNvencSessionListItem = listHead(&(pGpu->nvencSessionList)); 881 pNvencSessionListItem != NULL; 882 pNvencSessionListItem = listNext(&(pGpu->nvencSessionList), pNvencSessionListItem)) 883 { 884 if (pNvencSessionListItem->sessionPtr) 885 { 886 pNvencSession = pNvencSessionListItem->sessionPtr; 887 888 averageEncodeFps += pNvencSession->nvencSessionEntry.averageEncodeFps; 889 averageEncodeLatency += pNvencSession->nvencSessionEntry.averageEncodeLatency; 890 } 891 } 892 893 // average FPS and latency over all active sessions on this GPU. 894 pParams->averageEncodeFps = averageEncodeFps / listCount(&(pGpu->nvencSessionList)); 895 pParams->averageEncodeLatency = averageEncodeLatency / listCount(&(pGpu->nvencSessionList)); 896 897 return NV_OK; 898 } 899 900 NV_STATUS 901 _subdeviceCtrlCmdGpuGetNvencSwSessionInfo 902 ( 903 OBJGPU *pGpu, 904 NvU32 sessionInfoTblEntry, 905 NV2080_CTRL_NVENC_SW_SESSION_INFO *pSessionInfo, 906 NvU32 *entryCount 907 ) 908 { 909 910 NvencSession *pNvencSession = NULL; 911 PNVENC_SESSION_LIST_ITEM pNvencSessionListItem = NULL; 912 NvU32 i = 0; 913 NV2080_CTRL_NVENC_SW_SESSION_INFO *pSession; 914 915 NV_ASSERT_OR_RETURN(sessionInfoTblEntry == 916 NV2080_CTRL_GPU_NVENC_SESSION_INFO_MAX_COPYOUT_ENTRIES, 917 NV_ERR_INVALID_ARGUMENT); 918 919 portMemSet(pSessionInfo, 0, sizeof(NV2080_CTRL_NVENC_SW_SESSION_INFO) * sessionInfoTblEntry); 920 921 for (pNvencSessionListItem = listHead(&(pGpu->nvencSessionList)); 922 pNvencSessionListItem != NULL; 923 pNvencSessionListItem = listNext(&(pGpu->nvencSessionList), pNvencSessionListItem)) 924 { 925 if (pNvencSessionListItem->sessionPtr) 926 { 927 pNvencSession = pNvencSessionListItem->sessionPtr; 928 pSession = &pSessionInfo[i]; 929 930 pSession->sessionId = pNvencSession->nvencSessionEntry.sessionId; 931 pSession->processId = pNvencSession->nvencSessionEntry.processId; 932 pSession->subProcessId = pNvencSession->nvencSessionEntry.subProcessId; 933 pSession->codecType = pNvencSession->nvencSessionEntry.codecType; 934 pSession->hResolution = pNvencSession->nvencSessionEntry.hResolution; 935 pSession->vResolution = pNvencSession->nvencSessionEntry.vResolution; 936 pSession->averageEncodeFps = pNvencSession->nvencSessionEntry.averageEncodeFps; 937 pSession->averageEncodeLatency = pNvencSession->nvencSessionEntry.averageEncodeLatency; 938 939 i++; 940 941 if (i == NV2080_CTRL_GPU_NVENC_SESSION_INFO_MAX_COPYOUT_ENTRIES) 942 { 943 // Stop copying beyond max size otherwise we might corrupt other kernel data 944 break; 945 } 946 } 947 } 948 949 // 950 // Copy the data only if sessionInfoTbl entry is equals or greater 951 // than current active sessions i.e. listCount(&(pGpu->nvencSessionList)) 952 // 953 *entryCount = i; 954 955 return NV_OK; 956 } 957 958 // 959 // subdeviceCtrlCmdGpuGetNvencSwSessionInfo 960 // 961 // Lock Requirements: 962 // Assert that API lock and GPUs lock held on entry 963 // 964 965 NV_STATUS 966 subdeviceCtrlCmdGpuGetNvencSwSessionInfo_IMPL 967 ( 968 Subdevice *pSubdevice, 969 NV2080_CTRL_GPU_GET_NVENC_SW_SESSION_INFO_PARAMS *pParams 970 ) 971 { 972 NV_STATUS status = NV_OK; 973 NV2080_CTRL_NVENC_SW_SESSION_INFO *pSessionInfo = NvP64_VALUE(pParams->sessionInfoTbl); 974 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 975 NvU32 entryCount = 0; 976 977 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner()); 978 979 if ((!IS_VIRTUAL(pGpu)) && (pGpu->encSessionStatsReportingState != NV2080_CTRL_GPU_INFO_NVENC_STATS_REPORTING_STATE_ENABLED)) 980 { 981 pParams->sessionInfoTblEntry = 0; 982 return status; 983 } 984 985 if (pParams->sessionInfoTbl == NvP64_NULL || listCount(&(pGpu->nvencSessionList)) == 0) 986 { 987 pParams->sessionInfoTblEntry = listCount(&(pGpu->nvencSessionList)); 988 return status; 989 } 990 991 status = _subdeviceCtrlCmdGpuGetNvencSwSessionInfo(pGpu, pParams->sessionInfoTblEntry, pSessionInfo, &entryCount); 992 if (status != NV_OK) 993 return status; 994 995 pParams->sessionInfoTblEntry = entryCount; 996 997 return status; 998 } 999 1000 NV_STATUS 1001 subdeviceCtrlCmdGpuGetNvencSwSessionInfoV2_IMPL 1002 ( 1003 Subdevice *pSubdevice, 1004 NV2080_CTRL_GPU_GET_NVENC_SW_SESSION_INFO_V2_PARAMS *pParams 1005 ) 1006 { 1007 NV_STATUS status = NV_OK; 1008 NV2080_CTRL_NVENC_SW_SESSION_INFO *pSessionInfo = pParams->sessionInfoTbl; 1009 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 1010 NvU32 entryCount = 0; 1011 1012 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner()); 1013 1014 if ((!IS_VIRTUAL(pGpu)) && (pGpu->encSessionStatsReportingState != NV2080_CTRL_GPU_INFO_NVENC_STATS_REPORTING_STATE_ENABLED)) 1015 { 1016 pParams->sessionInfoTblEntry = 0; 1017 return status; 1018 } 1019 1020 if (pParams->sessionInfoTblEntry == 0 || listCount(&(pGpu->nvencSessionList)) == 0) 1021 { 1022 pParams->sessionInfoTblEntry = listCount(&(pGpu->nvencSessionList)); 1023 return status; 1024 } 1025 1026 status = _subdeviceCtrlCmdGpuGetNvencSwSessionInfo(pGpu, pParams->sessionInfoTblEntry, pSessionInfo, &entryCount); 1027 if (status != NV_OK) 1028 return status; 1029 1030 pParams->sessionInfoTblEntry = entryCount; 1031 1032 return status; 1033 } 1034 1035 // 1036 // subdeviceCtrlCmdGpuGetNvfbcSwSessionStats 1037 // 1038 // Lock Requirements: 1039 // Assert that API lock and GPUs lock held on entry 1040 // 1041 NV_STATUS 1042 subdeviceCtrlCmdGpuGetNvfbcSwSessionStats_IMPL 1043 ( 1044 Subdevice *pSubdevice, 1045 NV2080_CTRL_GPU_GET_NVFBC_SW_SESSION_STATS_PARAMS *pParams 1046 ) 1047 { 1048 1049 NvU32 averageFPS = 0, averageLatency = 0, localSessionCount = 0; 1050 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 1051 NvfbcSession *pNvfbcSession = NULL; 1052 PNVFBC_SESSION_LIST_ITEM pNvfbcSessionListItem = NULL; 1053 1054 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner()); 1055 1056 if (listCount(&(pGpu->nvfbcSessionList)) == 0) 1057 { 1058 pParams->sessionCount = 0; 1059 pParams->averageFPS = 0; 1060 pParams->averageLatency = 0; 1061 return NV_OK; 1062 } 1063 1064 for (pNvfbcSessionListItem = listHead(&(pGpu->nvfbcSessionList)); 1065 pNvfbcSessionListItem != NULL; 1066 pNvfbcSessionListItem = listNext(&(pGpu->nvfbcSessionList), pNvfbcSessionListItem)) 1067 { 1068 if (pNvfbcSessionListItem->sessionPtr) 1069 { 1070 pNvfbcSession = pNvfbcSessionListItem->sessionPtr; 1071 1072 averageFPS += pNvfbcSession->nvfbcSessionEntry.averageFPS; 1073 averageLatency += pNvfbcSession->nvfbcSessionEntry.averageLatency; 1074 1075 localSessionCount++; 1076 } 1077 } 1078 1079 // average FPS and latency over all active sessions on this GPU. 1080 pParams->averageFPS = localSessionCount == 0 ? 0 : (averageFPS / localSessionCount); 1081 pParams->averageLatency = localSessionCount == 0 ? 0 : (averageLatency / localSessionCount); 1082 1083 pParams->sessionCount = localSessionCount; 1084 1085 return NV_OK; 1086 } 1087 1088 // 1089 // subdeviceCtrlCmdGpuGetNvfbcSwSessionInfo 1090 // 1091 // Lock Requirements: 1092 // Assert that API lock and GPUs lock held on entry 1093 // 1094 1095 NV_STATUS 1096 subdeviceCtrlCmdGpuGetNvfbcSwSessionInfo_IMPL 1097 ( 1098 Subdevice *pSubdevice, 1099 NV2080_CTRL_GPU_GET_NVFBC_SW_SESSION_INFO_PARAMS *pParams 1100 ) 1101 { 1102 1103 NV2080_CTRL_NVFBC_SW_SESSION_INFO *pSession, *pSessionInfo = pParams->sessionInfoTbl; 1104 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 1105 NvU32 i = 0; 1106 NvfbcSession *pNvfbcSession = NULL; 1107 PNVFBC_SESSION_LIST_ITEM pNvfbcSessionListItem = NULL; 1108 1109 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner()); 1110 1111 portMemSet(pParams, 0, sizeof(NV2080_CTRL_GPU_GET_NVFBC_SW_SESSION_INFO_PARAMS)); 1112 1113 for (pNvfbcSessionListItem = listHead(&(pGpu->nvfbcSessionList)); 1114 pNvfbcSessionListItem != NULL; 1115 pNvfbcSessionListItem = listNext(&(pGpu->nvfbcSessionList), pNvfbcSessionListItem)) 1116 { 1117 if (pNvfbcSessionListItem->sessionPtr) 1118 { 1119 pNvfbcSession = pNvfbcSessionListItem->sessionPtr; 1120 pSession = &pSessionInfo[i]; 1121 1122 pSession->processId = pNvfbcSession->nvfbcSessionEntry.processId; 1123 pSession->vgpuInstanceId = pNvfbcSession->nvfbcSessionEntry.vgpuInstanceId; 1124 pSession->sessionId = pNvfbcSession->nvfbcSessionEntry.sessionId; 1125 pSession->displayOrdinal = pNvfbcSession->nvfbcSessionEntry.displayOrdinal; 1126 pSession->sessionType = pNvfbcSession->nvfbcSessionEntry.sessionType; 1127 pSession->sessionFlags = pNvfbcSession->nvfbcSessionEntry.sessionFlags; 1128 pSession->hMaxResolution = pNvfbcSession->nvfbcSessionEntry.hMaxResolution; 1129 pSession->vMaxResolution = pNvfbcSession->nvfbcSessionEntry.vMaxResolution; 1130 1131 // All the following fields are dynamic fields. 1132 // We will return these as 0 if these are stale values. 1133 if (nvfbcIsSessionDataStale(pNvfbcSession->nvfbcSessionEntry.lastUpdateTimeStamp)) 1134 { 1135 pSession->hResolution = 0; 1136 pSession->vResolution = 0; 1137 pSession->averageFPS = 0; 1138 pSession->averageLatency = 0; 1139 } 1140 else 1141 { 1142 pSession->hResolution = pNvfbcSession->nvfbcSessionEntry.hResolution; 1143 pSession->vResolution = pNvfbcSession->nvfbcSessionEntry.vResolution; 1144 pSession->averageFPS = pNvfbcSession->nvfbcSessionEntry.averageFPS; 1145 pSession->averageLatency = pNvfbcSession->nvfbcSessionEntry.averageLatency; 1146 } 1147 1148 i++; 1149 1150 if (i == NV2080_GPU_NVFBC_MAX_SESSION_COUNT) 1151 { 1152 NV_ASSERT(0); 1153 NV_PRINTF(LEVEL_ERROR, 1154 "more entries in pGpu->nvencSessionList than " 1155 "NV2080_CTRL_GPU_NVENC_SESSION_INFO_MAX_COPYOUT_ENTRIES\n"); 1156 1157 // Stop copying beyond max size otherwise we might corrupt other kernel data. 1158 break; 1159 } 1160 } 1161 } 1162 1163 pParams->sessionInfoCount = i; 1164 1165 return NV_OK; 1166 } 1167 1168 // 1169 // subdeviceCtrlCmdGpuGetSdm 1170 // 1171 // Lock Requirements: 1172 // Assert that API lock held on entry 1173 // 1174 NV_STATUS 1175 subdeviceCtrlCmdGpuGetSdm_IMPL 1176 ( 1177 Subdevice *pSubdevice, 1178 NV2080_CTRL_GPU_GET_SDM_PARAMS *pSdmParams 1179 ) 1180 { 1181 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 1182 1183 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner()); 1184 1185 pSdmParams->subdeviceMask = gpuGetSubdeviceMask(pGpu); 1186 1187 return NV_OK; 1188 } 1189 1190 // 1191 // subdeviceCtrlCmdGpuSetSdm 1192 // 1193 // Lock Requirements: 1194 // Assert that API lock held on entry 1195 // 1196 NV_STATUS 1197 subdeviceCtrlCmdGpuSetSdm_IMPL 1198 ( 1199 Subdevice* pSubdevice, 1200 NV2080_CTRL_GPU_SET_SDM_PARAMS* pSdmParams 1201 ) 1202 { 1203 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 1204 NvU32 subdeviceInstance; 1205 1206 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner()); 1207 1208 if (!ONEBITSET(pSdmParams->subdeviceMask)) 1209 { 1210 NV_PRINTF(LEVEL_ERROR, "Subdevice mask has none or more than one bit set"); 1211 return NV_ERR_INVALID_DATA; 1212 } 1213 1214 if (gpuIsStateLoaded(pGpu)) 1215 { 1216 NV_PRINTF(LEVEL_ERROR, "NV2080_CTRL_CMD_GPU_SET_SDM cannot be called after the GPU is loaded"); 1217 return NV_ERR_INVALID_STATE; 1218 } 1219 subdeviceInstance = BIT_IDX_32(pSdmParams->subdeviceMask); 1220 1221 if (subdeviceInstance >= NV_MAX_SUBDEVICES) 1222 { 1223 NV_PRINTF(LEVEL_ERROR, "Subdevice mask exceeds the max count of subdevices"); 1224 return NV_ERR_INVALID_DATA; 1225 } 1226 pGpu->subdeviceInstance = subdeviceInstance; 1227 1228 return NV_OK; 1229 } 1230 1231 // 1232 // subdeviceCtrlCmdGpuGetSimulationInfo 1233 // 1234 // Lock Requirements: 1235 // Assert that API lock held on entry 1236 // 1237 NV_STATUS 1238 subdeviceCtrlCmdGpuGetSimulationInfo_IMPL 1239 ( 1240 Subdevice *pSubdevice, 1241 NV2080_CTRL_GPU_GET_SIMULATION_INFO_PARAMS *pGpuSimulationInfoParams 1242 ) 1243 { 1244 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 1245 1246 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner()); 1247 1248 if (IS_SILICON(pGpu)) 1249 { 1250 pGpuSimulationInfoParams->type = NV2080_CTRL_GPU_GET_SIMULATION_INFO_TYPE_NONE; 1251 } 1252 else 1253 { 1254 pGpuSimulationInfoParams->type = NV2080_CTRL_GPU_GET_SIMULATION_INFO_TYPE_UNKNOWN; 1255 } 1256 1257 return NV_OK; 1258 } 1259 1260 // 1261 // subdeviceCtrlCmdGpuGetEngines 1262 // 1263 // Lock Requirements: 1264 // Assert that API lock held on entry 1265 // 1266 NV_STATUS 1267 subdeviceCtrlCmdGpuGetEngines_IMPL 1268 ( 1269 Subdevice *pSubdevice, 1270 NV2080_CTRL_GPU_GET_ENGINES_PARAMS *pParams 1271 ) 1272 { 1273 NV2080_CTRL_GPU_GET_ENGINES_V2_PARAMS getEngineParamsV2; 1274 NvU32 *pKernelEngineList = NvP64_VALUE(pParams->engineList); 1275 NV_STATUS status = NV_OK; 1276 1277 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner()); 1278 1279 portMemSet(&getEngineParamsV2, 0, sizeof(getEngineParamsV2)); 1280 1281 status = subdeviceCtrlCmdGpuGetEnginesV2(pSubdevice, &getEngineParamsV2); 1282 NV_CHECK_OR_RETURN(LEVEL_INFO, NV_OK == status, status); 1283 1284 // NULL clients just want an engine count 1285 if (NULL != pKernelEngineList) 1286 { 1287 NV_CHECK_OR_RETURN(LEVEL_INFO, pParams->engineCount >= getEngineParamsV2.engineCount, 1288 NV_ERR_BUFFER_TOO_SMALL); 1289 portMemCopy(pKernelEngineList, 1290 getEngineParamsV2.engineCount * sizeof(*getEngineParamsV2.engineList), getEngineParamsV2.engineList, 1291 getEngineParamsV2.engineCount * sizeof(*getEngineParamsV2.engineList)); 1292 } 1293 1294 pParams->engineCount = getEngineParamsV2.engineCount; 1295 1296 return status; 1297 } 1298 1299 // 1300 // subdeviceCtrlCmdGpuGetEnginesV2 1301 // 1302 // Lock Requirements: 1303 // Assert that API lock held on entry 1304 // 1305 NV_STATUS 1306 subdeviceCtrlCmdGpuGetEnginesV2_IMPL 1307 ( 1308 Subdevice *pSubdevice, 1309 NV2080_CTRL_GPU_GET_ENGINES_V2_PARAMS *pEngineParams 1310 ) 1311 { 1312 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 1313 NV_STATUS status = NV_OK; 1314 1315 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner()); 1316 1317 // Update the engine Database 1318 NV_ASSERT_OK_OR_RETURN(gpuUpdateEngineTable(pGpu)); 1319 1320 // Validate engine count 1321 if (pGpu->engineDB.size > NV2080_GPU_MAX_ENGINES_LIST_SIZE) 1322 { 1323 NV_PRINTF(LEVEL_ERROR, "The engine database's size (0x%x) exceeds " 1324 "NV2080_GPU_MAX_ENGINES_LIST_SIZE (0x%x)!\n", 1325 pGpu->engineDB.size, NV2080_GPU_MAX_ENGINES_LIST_SIZE); 1326 DBG_BREAKPOINT(); 1327 return NV_ERR_INVALID_STATE; 1328 } 1329 1330 { 1331 // Need this null check in case object doesn't exist when using Orin trimmed profile 1332 KernelMIGManager *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu); 1333 if (pKernelMIGManager != NULL) 1334 { 1335 RM_ENGINE_TYPE rmEngineTypeList[NV2080_GPU_MAX_ENGINES_LIST_SIZE]; 1336 1337 // Filter engines based on current partitioning scheme 1338 status = kmigmgrFilterEngineList(pGpu, 1339 pKernelMIGManager, 1340 pSubdevice, 1341 rmEngineTypeList, 1342 &pEngineParams->engineCount); 1343 1344 if (status == NV_OK) 1345 { 1346 // Convert the RM_ENGINE_TYPE list to NV2080_ENGINE_TYPE list 1347 gpuGetNv2080EngineTypeList(rmEngineTypeList, 1348 pEngineParams->engineCount, 1349 pEngineParams->engineList); 1350 } 1351 } 1352 } 1353 1354 return status; 1355 } 1356 1357 // 1358 // subdeviceCtrlCmdGpuGetEngineClasslist 1359 // 1360 // Lock Requirements: 1361 // Assert that API lock held on entry 1362 // 1363 NV_STATUS 1364 subdeviceCtrlCmdGpuGetEngineClasslist_IMPL 1365 ( 1366 Subdevice *pSubdevice, 1367 NV2080_CTRL_GPU_GET_ENGINE_CLASSLIST_PARAMS *pClassParams 1368 ) 1369 { 1370 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 1371 ENGDESCRIPTOR engDesc; 1372 NV_STATUS status = NV_OK; 1373 RM_ENGINE_TYPE rmEngineType = gpuGetRmEngineType(pClassParams->engineType); 1374 1375 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner()); 1376 1377 { 1378 if (IS_MIG_IN_USE(pGpu)) 1379 { 1380 KernelMIGManager *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu); 1381 MIG_INSTANCE_REF ref; 1382 1383 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, 1384 kmigmgrGetInstanceRefFromDevice(pGpu, pKernelMIGManager, GPU_RES_GET_DEVICE(pSubdevice), &ref)); 1385 1386 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, 1387 kmigmgrGetLocalToGlobalEngineType(pGpu, pKernelMIGManager, ref, 1388 rmEngineType, 1389 &rmEngineType)); 1390 } 1391 } 1392 1393 status = gpuXlateClientEngineIdToEngDesc(pGpu, rmEngineType, &engDesc); 1394 1395 NV_ASSERT(status == NV_OK); 1396 1397 if (status != NV_OK) 1398 { 1399 NV_PRINTF(LEVEL_ERROR, 1400 "NV2080_CTRL_CMD_GPU_GET_ENGINE_CLASSLIST Invalid engine ID 0x%x\n", 1401 pClassParams->engineType); 1402 DBG_BREAKPOINT(); 1403 return status; 1404 } 1405 1406 status = gpuGetClassList(pGpu, &pClassParams->numClasses, NvP64_VALUE(pClassParams->classList), engDesc); 1407 1408 if (status != NV_OK) 1409 { 1410 NV_PRINTF(LEVEL_ERROR, 1411 "NV2080_CTRL_CMD_GPU_GET_ENGINE_CLASSLIST Class List query failed\n"); 1412 } 1413 1414 return status; 1415 } 1416 1417 // 1418 // subdeviceCtrlCmdGpuGetEnginePartnerList 1419 // 1420 // Lock Requirements: 1421 // Assert that API lock held on entry 1422 // 1423 NV_STATUS 1424 subdeviceCtrlCmdGpuGetEnginePartnerList_IMPL 1425 ( 1426 Subdevice *pSubdevice, 1427 NV2080_CTRL_GPU_GET_ENGINE_PARTNERLIST_PARAMS *pPartnerListParams 1428 ) 1429 { 1430 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 1431 KernelMIGManager *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu); 1432 ENGDESCRIPTOR engDesc; 1433 NvU32 localNv2080EngineType; 1434 RM_ENGINE_TYPE rmEngineType; 1435 NvU32 i; 1436 PCLASSDESCRIPTOR pClass; 1437 NV_STATUS status = NV_OK; 1438 1439 pPartnerListParams->numPartners = 0; 1440 1441 rmEngineType = gpuGetRmEngineType(pPartnerListParams->engineType); 1442 1443 status = gpuXlateClientEngineIdToEngDesc(pGpu, rmEngineType, &engDesc); 1444 if (NV_OK != status) 1445 { 1446 NV_PRINTF(LEVEL_ERROR, "Invalid engine ID 0x%x (0x%x)\n", 1447 pPartnerListParams->engineType, rmEngineType); 1448 return status; 1449 } 1450 1451 // find class in class db 1452 status = gpuGetClassByClassId(pGpu, pPartnerListParams->partnershipClassId, &pClass); 1453 if (NV_OK != status) 1454 { 1455 NV_PRINTF(LEVEL_ERROR, "Invalid class ID 0x%x\n", 1456 pPartnerListParams->partnershipClassId); 1457 return status; 1458 } 1459 1460 // Make sure that the engine related to this class is FIFO... 1461 if (pClass->engDesc != ENG_KERNEL_FIFO) 1462 { 1463 NV_PRINTF(LEVEL_ERROR, 1464 "Class 0x%x is not considered a partnership class.\n", 1465 pPartnerListParams->partnershipClassId); 1466 return NV_ERR_NOT_SUPPORTED; 1467 } 1468 1469 localNv2080EngineType = pPartnerListParams->engineType; 1470 1471 // Translate the instance-local engine type to the global engine type in MIG mode 1472 if (IS_MIG_IN_USE(pGpu)) 1473 { 1474 Device *pDevice = GPU_RES_GET_DEVICE(pSubdevice); 1475 MIG_INSTANCE_REF ref; 1476 1477 NV_CHECK_OK_OR_RETURN( 1478 LEVEL_ERROR, 1479 kmigmgrGetInstanceRefFromDevice(pGpu, pKernelMIGManager, pDevice, &ref)); 1480 1481 NV_CHECK_OK_OR_RETURN( 1482 LEVEL_ERROR, 1483 kmigmgrGetLocalToGlobalEngineType(pGpu, pKernelMIGManager, ref, 1484 rmEngineType, 1485 &rmEngineType)); 1486 1487 pPartnerListParams->engineType = gpuGetNv2080EngineType(rmEngineType); 1488 } 1489 1490 // See if the hal wants to handle this 1491 KernelFifo *pKernelFifo = GPU_GET_KERNEL_FIFO(pGpu); 1492 status = kfifoGetEnginePartnerList_HAL(pGpu, pKernelFifo, pPartnerListParams); 1493 1494 // Restore the client's passed engineType 1495 pPartnerListParams->engineType = localNv2080EngineType; 1496 1497 if (NV_OK == status) 1498 { 1499 goto subdeviceCtrlCmdGpuGetEnginePartnerList_filter; 1500 } 1501 1502 // 1503 // For channels that the hal didn't handle, we should just return 1504 // all of the supported engines except for the target engine. 1505 // 1506 1507 // Update the engine Database 1508 NV_ASSERT_OK_OR_RETURN(gpuUpdateEngineTable(pGpu)); 1509 1510 // Make sure it all will fit 1511 if (pGpu->engineDB.size > NV2080_CTRL_GPU_MAX_ENGINE_PARTNERS) 1512 { 1513 NV_PRINTF(LEVEL_ERROR, 1514 "partnerList space is too small, time to increase. This is fatal\n"); 1515 DBG_BREAKPOINT(); 1516 return status; 1517 } 1518 1519 // Copy over all of the engines except the target 1520 for (i = 0; i < pGpu->engineDB.size; i++) 1521 { 1522 localNv2080EngineType = gpuGetNv2080EngineType(pGpu->engineDB.pType[i]); 1523 1524 // Skip the engine handed in 1525 if (localNv2080EngineType != pPartnerListParams->engineType ) 1526 { 1527 pPartnerListParams->partnerList[pPartnerListParams->numPartners++] = localNv2080EngineType; 1528 } 1529 } 1530 1531 subdeviceCtrlCmdGpuGetEnginePartnerList_filter: 1532 if (IS_MIG_IN_USE(pGpu)) 1533 { 1534 // Remove entries which don't exist in this client's GPU instance 1535 status = kmigmgrFilterEnginePartnerList(pGpu, pKernelMIGManager, 1536 pSubdevice, 1537 pPartnerListParams); 1538 } 1539 1540 return status; 1541 } 1542 1543 // 1544 // subdeviceCtrlCmdGpuGetEngineFaultInfo 1545 // 1546 // Lock Requirements: 1547 // Assert that API lock held on entry 1548 // 1549 NV_STATUS 1550 subdeviceCtrlCmdGpuGetEngineFaultInfo_IMPL 1551 ( 1552 Subdevice *pSubdevice, 1553 NV2080_CTRL_GPU_GET_ENGINE_FAULT_INFO_PARAMS *pParams 1554 ) 1555 { 1556 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 1557 KernelFifo *pKernelFifo = GPU_GET_KERNEL_FIFO(pGpu); 1558 NV_STATUS status = NV_OK; 1559 RM_ENGINE_TYPE rmEngineType = gpuGetRmEngineType(pParams->engineType); 1560 1561 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner()); 1562 1563 // 1564 // When MIG is enabled, clients pass in their instance-specific engineId 1565 // rather than physical engineId since each client only sees engines available in 1566 // its own instance. So we need to convert this local engineId to physical engineId 1567 // 1568 if (IS_MIG_IN_USE(pGpu)) 1569 { 1570 KernelMIGManager *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu); 1571 Device *pDevice = GPU_RES_GET_DEVICE(pSubdevice); 1572 MIG_INSTANCE_REF ref; 1573 1574 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, 1575 kmigmgrGetInstanceRefFromDevice(pGpu, pKernelMIGManager, pDevice, &ref)); 1576 1577 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, 1578 kmigmgrGetLocalToGlobalEngineType(pGpu, pKernelMIGManager, ref, 1579 rmEngineType, 1580 &rmEngineType)); 1581 } 1582 1583 // Populate HW info for SW engine entry 1584 status = kfifoEngineInfoXlate_HAL(pGpu, pKernelFifo, ENGINE_INFO_TYPE_RM_ENGINE_TYPE, 1585 (NvU32)rmEngineType, ENGINE_INFO_TYPE_MMU_FAULT_ID, 1586 &pParams->mmuFaultId); 1587 if (status != NV_OK) 1588 { 1589 NV_PRINTF(LEVEL_ERROR, 1590 "NV2080_CTRL_CMD_GPU_GET_ENGINE_INFO failed\n"); 1591 return status; 1592 } 1593 1594 // Only GR engine supports subcontext faulting on Volta+ chips 1595 pParams->bSubcontextSupported = (RM_ENGINE_TYPE_IS_GR(rmEngineType) && 1596 kfifoIsSubcontextSupported(pKernelFifo)); 1597 1598 return status; 1599 } 1600 1601 ct_assert(NV2080_CTRL_INTERNAL_MAX_TPC_PER_GPC_COUNT == 1602 NV2080_CTRL_CMD_GPU_GET_PES_INFO_MAX_TPC_PER_GPC_COUNT); 1603 1604 // 1605 // subdeviceCtrlCmdGpuGetFermiGpcInfo 1606 // 1607 // Lock Requirements: 1608 // Assert that API lock and GPUs lock held on entry 1609 // 1610 NV_STATUS 1611 subdeviceCtrlCmdGpuGetFermiGpcInfo_IMPL 1612 ( 1613 Subdevice *pSubdevice, 1614 NV2080_CTRL_GPU_GET_FERMI_GPC_INFO_PARAMS *pParams 1615 ) 1616 { 1617 NV2080_CTRL_GR_GET_GPC_MASK_PARAMS gpcMaskParams; 1618 RM_API *pRmApi = rmapiGetInterface(RMAPI_GPU_LOCK_INTERNAL); 1619 NvHandle hClient = RES_GET_CLIENT_HANDLE(pSubdevice); 1620 NvHandle hSubdevice = RES_GET_HANDLE(pSubdevice); 1621 1622 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmDeviceGpuLockIsOwner(GPU_RES_GET_GPU(pSubdevice)->gpuInstance)); 1623 1624 portMemSet(&gpcMaskParams, 0, sizeof(gpcMaskParams)); 1625 1626 NV_CHECK_OK_OR_RETURN( 1627 LEVEL_ERROR, 1628 pRmApi->Control(pRmApi, 1629 hClient, 1630 hSubdevice, 1631 NV2080_CTRL_CMD_GR_GET_GPC_MASK, 1632 &gpcMaskParams, 1633 sizeof(gpcMaskParams))); 1634 1635 pParams->gpcMask = gpcMaskParams.gpcMask; 1636 return NV_OK; 1637 } 1638 1639 // 1640 // subdeviceCtrlCmdGpuGetFermiTpcInfo 1641 // 1642 // Lock Requirements: 1643 // Assert that API lock and GPUs lock held on entry 1644 // 1645 NV_STATUS 1646 subdeviceCtrlCmdGpuGetFermiTpcInfo_IMPL 1647 ( 1648 Subdevice *pSubdevice, 1649 NV2080_CTRL_GPU_GET_FERMI_TPC_INFO_PARAMS *pParams 1650 ) 1651 { 1652 NV2080_CTRL_GR_GET_TPC_MASK_PARAMS tpcMaskParams; 1653 RM_API *pRmApi = rmapiGetInterface(RMAPI_GPU_LOCK_INTERNAL); 1654 NvHandle hClient = RES_GET_CLIENT_HANDLE(pSubdevice); 1655 NvHandle hSubdevice = RES_GET_HANDLE(pSubdevice); 1656 1657 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmDeviceGpuLockIsOwner(GPU_RES_GET_GPU(pSubdevice)->gpuInstance)); 1658 1659 portMemSet(&tpcMaskParams, 0, sizeof(tpcMaskParams)); 1660 tpcMaskParams.gpcId = pParams->gpcId; 1661 1662 NV_CHECK_OK_OR_RETURN( 1663 LEVEL_ERROR, 1664 pRmApi->Control(pRmApi, 1665 hClient, 1666 hSubdevice, 1667 NV2080_CTRL_CMD_GR_GET_TPC_MASK, 1668 &tpcMaskParams, 1669 sizeof(tpcMaskParams))); 1670 1671 pParams->tpcMask = tpcMaskParams.tpcMask; 1672 return NV_OK; 1673 } 1674 1675 // 1676 // subdeviceCtrlCmdGpuGetFermiZcullInfo 1677 // 1678 // Lock Requirements: 1679 // Assert that API lock and GPUs lock held on entry 1680 // 1681 // WARNING: This control call is deprecated. 1682 // 1683 NV_STATUS 1684 subdeviceCtrlCmdGpuGetFermiZcullInfo_IMPL 1685 ( 1686 Subdevice *pSubdevice, 1687 NV2080_CTRL_GPU_GET_FERMI_ZCULL_INFO_PARAMS *pParams 1688 ) 1689 { 1690 NV2080_CTRL_GR_GET_ZCULL_MASK_PARAMS zcullMaskParams; 1691 RM_API *pRmApi = rmapiGetInterface(RMAPI_GPU_LOCK_INTERNAL); 1692 NvHandle hClient = RES_GET_CLIENT_HANDLE(pSubdevice); 1693 NvHandle hSubdevice = RES_GET_HANDLE(pSubdevice); 1694 1695 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmDeviceGpuLockIsOwner(GPU_RES_GET_GPU(pSubdevice)->gpuInstance)); 1696 1697 portMemSet(&zcullMaskParams, 0, sizeof(zcullMaskParams)); 1698 zcullMaskParams.gpcId = pParams->gpcId; 1699 1700 NV_CHECK_OK_OR_RETURN( 1701 LEVEL_ERROR, 1702 pRmApi->Control(pRmApi, 1703 hClient, 1704 hSubdevice, 1705 NV2080_CTRL_CMD_GR_GET_ZCULL_MASK, 1706 &zcullMaskParams, 1707 sizeof(zcullMaskParams))); 1708 1709 pParams->zcullMask = zcullMaskParams.zcullMask; 1710 1711 return NV_OK; 1712 } 1713 1714 /*! 1715 * @brief Get graphics engine PES configuration 1716 * 1717 * This can be called before floor sweeping is determined, so we cannot use cached 1718 * values. 1719 */ 1720 NV_STATUS 1721 subdeviceCtrlCmdGpuGetPesInfo_IMPL 1722 ( 1723 Subdevice *pSubdevice, 1724 NV2080_CTRL_GPU_GET_PES_INFO_PARAMS *pParams 1725 ) 1726 { 1727 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 1728 NvHandle hClient = RES_GET_CLIENT_HANDLE(pSubdevice); 1729 KernelGraphics *pKernelGraphics; 1730 const KGRAPHICS_STATIC_INFO *pKernelGraphicsStaticInfo; 1731 RsClient *pRsClient; 1732 NvU32 gpcId = pParams->gpcId; 1733 NvU32 maxGpcCount; 1734 1735 // 1736 // XXX Bug 2681931 - GET_PES_INFO overloads interpretation of gpcId parameter 1737 // This ctrl call is due for deprecation and should not be used. 1738 // 1739 1740 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner()); 1741 1742 NV_ASSERT_OK_OR_RETURN( 1743 serverGetClientUnderLock(&g_resServ, hClient, &pRsClient)); 1744 1745 NV_CHECK_OR_RETURN(LEVEL_INFO, !IS_MIG_IN_USE(pGpu), NV_ERR_NOT_SUPPORTED); 1746 pKernelGraphics = GPU_GET_KERNEL_GRAPHICS(pGpu, 0); 1747 pKernelGraphicsStaticInfo = kgraphicsGetStaticInfo(pGpu, pKernelGraphics); 1748 NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo != NULL, NV_ERR_INVALID_STATE); 1749 1750 maxGpcCount = gpuGetLitterValues_HAL(pGpu, NV2080_CTRL_GR_INFO_INDEX_LITTER_NUM_GPCS); 1751 if (gpcId >= maxGpcCount) 1752 { 1753 return NV_ERR_INVALID_ARGUMENT; 1754 } 1755 1756 pParams->numPesInGpc = pKernelGraphicsStaticInfo->floorsweepingMasks.numPesPerGpc[gpcId]; 1757 1758 NV_CHECK_OR_RETURN(LEVEL_SILENT, pKernelGraphicsStaticInfo->pPpcMasks != NULL, NV_ERR_NOT_SUPPORTED); 1759 pParams->activePesMask = pKernelGraphicsStaticInfo->pPpcMasks->mask[gpcId]; 1760 1761 pParams->maxTpcPerGpcCount = pKernelGraphicsStaticInfo->pGrInfo->infoList[NV2080_CTRL_GR_INFO_INDEX_LITTER_NUM_TPC_PER_GPC].data; 1762 portMemCopy(pParams->tpcToPesMap, sizeof(pParams->tpcToPesMap), 1763 pKernelGraphicsStaticInfo->floorsweepingMasks.tpcToPesMap, sizeof(pKernelGraphicsStaticInfo->floorsweepingMasks.tpcToPesMap)); 1764 1765 return NV_OK; 1766 } 1767 1768 // 1769 // subdeviceCtrlCmdGpuQueryMode_IMPL 1770 // 1771 // Lock Requirements: 1772 // Assert that API and GPUs lock held on entry 1773 // 1774 NV_STATUS 1775 subdeviceCtrlCmdGpuQueryMode_IMPL 1776 ( 1777 Subdevice *pSubdevice, 1778 NV2080_CTRL_GPU_QUERY_MODE_PARAMS *pQueryMode 1779 ) 1780 { 1781 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 1782 1783 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner()); 1784 1785 switch (gpuGetMode(pGpu)) 1786 { 1787 case NV_GPU_MODE_GRAPHICS_MODE: 1788 { 1789 pQueryMode->mode = NV2080_CTRL_GPU_QUERY_MODE_GRAPHICS_MODE; 1790 break; 1791 } 1792 case NV_GPU_MODE_COMPUTE_MODE: 1793 { 1794 pQueryMode->mode = NV2080_CTRL_GPU_QUERY_MODE_COMPUTE_MODE; 1795 break; 1796 } 1797 default: 1798 { 1799 pQueryMode->mode = NV2080_CTRL_GPU_QUERY_MODE_UNKNOWN_MODE; 1800 break; 1801 } 1802 } 1803 1804 return NV_OK; 1805 } 1806 1807 // 1808 // subdeviceCtrlCmdGpuHandleGpuSR 1809 // 1810 // Lock Requirements: 1811 // Assert that API lock held on entry 1812 // 1813 NV_STATUS 1814 subdeviceCtrlCmdGpuHandleGpuSR_IMPL 1815 ( 1816 Subdevice *pSubdevice 1817 ) 1818 { 1819 return NV_OK; 1820 } 1821 1822 // 1823 // subdeviceCtrlCmdGpuSetComputeModeRules 1824 // 1825 // Lock Requirements: 1826 // Assert that API lock held on entry 1827 // 1828 NV_STATUS 1829 subdeviceCtrlCmdGpuSetComputeModeRules_IMPL 1830 ( 1831 Subdevice *pSubdevice, 1832 NV2080_CTRL_GPU_SET_COMPUTE_MODE_RULES_PARAMS *pSetRulesParams 1833 ) 1834 { 1835 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 1836 1837 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner()); 1838 1839 if (IS_GSP_CLIENT(pGpu)) 1840 { 1841 CALL_CONTEXT *pCallContext = resservGetTlsCallContext(); 1842 RmCtrlParams *pRmCtrlParams = pCallContext->pControlParams; 1843 RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu); 1844 1845 // 1846 // Client RM still needs to set its value and update the registry, 1847 // so don't return unless there was an error. 1848 // 1849 NV_ASSERT_OK_OR_RETURN(pRmApi->Control(pRmApi, 1850 pRmCtrlParams->hClient, 1851 pRmCtrlParams->hObject, 1852 pRmCtrlParams->cmd, 1853 pRmCtrlParams->pParams, 1854 pRmCtrlParams->paramsSize)); 1855 } 1856 1857 //TODO Bug 2718406 will extend compute mode support for MIG 1858 if (IS_MIG_ENABLED(pGpu)) 1859 { 1860 return NV_ERR_NOT_SUPPORTED; 1861 } 1862 1863 // Setting compute mode for cuda non supported vGPU profiles 1864 // is not supported. 1865 // Exclude GSP environment for that rule. 1866 VGPU_STATIC_INFO *pVSI = GPU_GET_STATIC_INFO(pGpu); 1867 if (pVSI && !IS_GSP_CLIENT(pGpu) && pVSI->vgpuConfig.cudaEnabled == 0) 1868 { 1869 return NV_ERR_NOT_SUPPORTED; 1870 } 1871 1872 switch(pSetRulesParams->rules) 1873 { 1874 case NV2080_CTRL_GPU_COMPUTE_MODE_RULES_NONE: 1875 case NV2080_CTRL_GPU_COMPUTE_MODE_RULES_EXCLUSIVE_COMPUTE: 1876 case NV2080_CTRL_GPU_COMPUTE_MODE_RULES_COMPUTE_PROHIBITED: 1877 case NV2080_CTRL_GPU_COMPUTE_MODE_RULES_EXCLUSIVE_COMPUTE_PROCESS: 1878 pGpu->computeModeRules = pSetRulesParams->rules; 1879 1880 // 1881 // Store this setting in the registry so that it persists even 1882 // after the last client disconnects. 1883 // Client RM handles this so skip on GSP. 1884 // 1885 if (NV_OK != 1886 osWriteRegistryDword(pGpu, 1887 NV_REG_STR_RM_COMPUTE_MODE_RULES, 1888 pGpu->computeModeRules)) 1889 { 1890 // Non-fatal but worth reporting 1891 NV_PRINTF(LEVEL_ERROR, 1892 "Could not store compute mode rule in the registry, current setting may not persist if all clients disconnect!\n"); 1893 } 1894 break; 1895 1896 default: 1897 return NV_ERR_INVALID_ARGUMENT; 1898 } 1899 1900 return NV_OK; 1901 } 1902 1903 // 1904 // subdeviceCtrlCmdGpuQueryComputeModeRules 1905 // 1906 // Lock Requirements: 1907 // Assert that API lock held on entry 1908 // 1909 // TODO Bug 2718406 will extend compute mode support for MIG 1910 // 1911 NV_STATUS 1912 subdeviceCtrlCmdGpuQueryComputeModeRules_IMPL 1913 ( 1914 Subdevice *pSubdevice, 1915 NV2080_CTRL_GPU_QUERY_COMPUTE_MODE_RULES_PARAMS *pQueryRulesParams 1916 ) 1917 { 1918 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 1919 1920 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner()); 1921 1922 // 1923 // vGPU specific check to assign compute mode as 'Prohibited' 1924 // for cuda non supported vGPU profiles. 1925 // Exclude GSP environment for that rule. 1926 // 1927 VGPU_STATIC_INFO *pVSI = GPU_GET_STATIC_INFO(pGpu); 1928 if ((pVSI != NULL) && !IS_GSP_CLIENT(pGpu) && (pVSI->vgpuConfig.cudaEnabled == 0)) 1929 { 1930 pQueryRulesParams->rules = NV2080_CTRL_GPU_COMPUTE_MODE_RULES_COMPUTE_PROHIBITED; 1931 } 1932 else 1933 { 1934 pQueryRulesParams->rules = pGpu->computeModeRules; 1935 } 1936 1937 return NV_OK; 1938 } 1939 1940 NV_STATUS 1941 subdeviceCtrlCmdGpuAcquireComputeModeReservation_IMPL 1942 ( 1943 Subdevice *pSubdevice 1944 ) 1945 { 1946 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 1947 NvHandle hClient = RES_GET_CLIENT_HANDLE(pSubdevice); 1948 1949 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner()); 1950 1951 //TODO Bug 2718406 will extend compute mode support for MIG 1952 if (IS_MIG_ENABLED(pGpu)) 1953 { 1954 return NV_ERR_NOT_SUPPORTED; 1955 } 1956 1957 switch (pGpu->computeModeRules) 1958 { 1959 case NV2080_CTRL_GPU_COMPUTE_MODE_RULES_NONE: 1960 { 1961 // If a GPU is in "normal" mode, then the caller can always get the reservation: 1962 pGpu->hComputeModeReservation = hClient; 1963 } 1964 return NV_OK; 1965 break; // For the Coverity code checker. 1966 1967 case NV2080_CTRL_GPU_COMPUTE_MODE_RULES_EXCLUSIVE_COMPUTE: 1968 case NV2080_CTRL_GPU_COMPUTE_MODE_RULES_EXCLUSIVE_COMPUTE_PROCESS: 1969 { 1970 // 1971 // If a GPU is in "cuda exclusive" mode, then the caller can only get the 1972 // reservation if no other client holds the reservation: 1973 // 1974 if (NV01_NULL_OBJECT == pGpu->hComputeModeReservation) 1975 { 1976 pGpu->hComputeModeReservation = hClient; 1977 return NV_OK; 1978 } 1979 else 1980 { 1981 // Someone else holds the reservation: 1982 return NV_ERR_STATE_IN_USE; 1983 } 1984 } 1985 break; 1986 1987 case NV2080_CTRL_GPU_COMPUTE_MODE_RULES_COMPUTE_PROHIBITED: 1988 // 1989 // If a GPU is in "cuda prohibited" mode, then the caller can never get the 1990 // reservation: 1991 // 1992 return NV_ERR_STATE_IN_USE; 1993 break; 1994 1995 default: 1996 NV_ASSERT(0); // This *should* be unreachable code. 1997 break; 1998 } 1999 2000 return NV_OK; 2001 } 2002 2003 NV_STATUS 2004 subdeviceCtrlCmdGpuReleaseComputeModeReservation_IMPL 2005 ( 2006 Subdevice *pSubdevice 2007 ) 2008 { 2009 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 2010 NvHandle hClient = RES_GET_CLIENT_HANDLE(pSubdevice); 2011 2012 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner()); 2013 2014 //TODO Bug 2718406 will extend compute mode support for MIG 2015 if (IS_MIG_ENABLED(pGpu)) 2016 { 2017 return NV_ERR_NOT_SUPPORTED; 2018 } 2019 2020 // Release the reservation ONLY IF we had the reservation to begin with. Otherwise, 2021 // leave it alone, because someone else has acquired it: 2022 if (pGpu->hComputeModeReservation == hClient) 2023 { 2024 pGpu->hComputeModeReservation = NV01_NULL_OBJECT; 2025 } 2026 else 2027 { 2028 return NV_ERR_STATE_IN_USE; 2029 } 2030 2031 return NV_OK; 2032 } 2033 2034 // 2035 // subdeviceCtrlCmdGpuGetId 2036 // 2037 // Lock Requirements: 2038 // Assert that API lock held on entry 2039 // 2040 NV_STATUS 2041 subdeviceCtrlCmdGpuGetId_IMPL 2042 ( 2043 Subdevice *pSubdevice, 2044 NV2080_CTRL_GPU_GET_ID_PARAMS *pIdParams 2045 ) 2046 { 2047 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 2048 2049 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner()); 2050 2051 pIdParams->gpuId = pGpu->gpuId; 2052 2053 return NV_OK; 2054 } 2055 2056 // 2057 // nv2080CtrlCmdGpuGetPids 2058 // 2059 // Lock Requirements: 2060 // Assert that API and GPUs lock held on entry 2061 // 2062 NV_STATUS 2063 subdeviceCtrlCmdGpuGetPids_IMPL 2064 ( 2065 Subdevice *pSubdevice, 2066 NV2080_CTRL_GPU_GET_PIDS_PARAMS *pGetPidsParams 2067 ) 2068 { 2069 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 2070 NvU32 internalClassId; 2071 NV_STATUS status; 2072 MIG_INSTANCE_REF *pRef = NULL; 2073 2074 NV_ASSERT_OR_RETURN(RMCFG_FEATURE_KERNEL_RM, NV_ERR_NOT_SUPPORTED); 2075 2076 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner()); 2077 2078 switch (pGetPidsParams->idType) 2079 { 2080 case (NV2080_CTRL_GPU_GET_PIDS_ID_TYPE_CLASS): 2081 { 2082 if (pGetPidsParams->id == NV20_SUBDEVICE_0) 2083 { 2084 internalClassId = classId(Subdevice); 2085 } 2086 else if (pGetPidsParams->id == MPS_COMPUTE) 2087 { 2088 internalClassId = classId(MpsApi); 2089 } 2090 else 2091 { 2092 internalClassId = classId(ChannelDescendant); 2093 } 2094 break; 2095 } 2096 case (NV2080_CTRL_GPU_GET_PIDS_ID_TYPE_VGPU_GUEST): 2097 { 2098 internalClassId = classId(KernelHostVgpuDeviceApi); 2099 break; 2100 } 2101 2102 default: 2103 return NV_ERR_INVALID_ARGUMENT; 2104 } 2105 2106 // 2107 // With MIG GPU instancing enabled, get associated instance ref 2108 // Clients with MIG_MONITOR capability are allowed to get full device 2109 // info 2110 // 2111 KernelMIGManager *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu); 2112 NvHandle hClient = RES_GET_CLIENT_HANDLE(pSubdevice); 2113 MIG_INSTANCE_REF partitionRef = kmigmgrMakeNoMIGReference(); 2114 pRef = &partitionRef; 2115 if (IS_MIG_IN_USE(pGpu) && 2116 !rmclientIsCapableByHandle(hClient, NV_RM_CAP_SYS_SMC_MONITOR)) 2117 { 2118 Device *pDevice = GPU_RES_GET_DEVICE(pSubdevice); 2119 // 2120 // Check instanceSubscription to limit the scope of the call 2121 // Clients with mig-monitor capability are allowed to get full device 2122 // info 2123 // 2124 NV_CHECK_OR_RETURN(LEVEL_INFO, (kmigmgrGetInstanceRefFromDevice(pGpu, pKernelMIGManager, 2125 pDevice, pRef) == NV_OK), 2126 NV_ERR_INSUFFICIENT_PERMISSIONS); 2127 } 2128 2129 // 2130 // Search over all clients to see if any contain objects of type = id. 2131 // If they do, then add their PID to the PIDArray param and also 2132 // return the amount of valid entries in the Array through pidTblCount. 2133 // 2134 status = gpuGetProcWithObject(pGpu, pGetPidsParams->id, internalClassId, 2135 pGetPidsParams->pidTbl, &pGetPidsParams->pidTblCount, 2136 pRef); 2137 return status; 2138 } 2139 2140 // 2141 // subdeviceCtrlCmdGpuGetPidInfo 2142 // 2143 // Lock Requirements: 2144 // Assert that API and GPUs lock held on entry 2145 // 2146 NV_STATUS 2147 subdeviceCtrlCmdGpuGetPidInfo_IMPL 2148 ( 2149 Subdevice *pSubdevice, 2150 NV2080_CTRL_GPU_GET_PID_INFO_PARAMS *pGetPidInfoParams 2151 ) 2152 { 2153 NV2080_CTRL_GPU_PID_INFO_DATA *pPidInfoData; 2154 NV2080_CTRL_SMC_SUBSCRIPTION_INFO *pSmcInfo; 2155 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 2156 NV2080_CTRL_GPU_PID_INFO *pPidInfo; 2157 NvU32 internalClassId; 2158 NvU32 i; 2159 MIG_INSTANCE_REF *pRef = NULL; 2160 NvBool bGlobalInfo = NV_TRUE; 2161 2162 NV_ASSERT_OR_RETURN(RMCFG_FEATURE_KERNEL_RM, NV_ERR_NOT_SUPPORTED); 2163 2164 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner()); 2165 2166 if ((pGetPidInfoParams->pidInfoListCount <= 0) || 2167 (pGetPidInfoParams->pidInfoListCount > 2168 NV2080_CTRL_GPU_GET_PID_INFO_MAX_COUNT)) 2169 { 2170 return NV_ERR_INVALID_ARGUMENT; 2171 } 2172 2173 // 2174 // With MIG GPU instancing enabled, get associated instance ref 2175 // Clients with MIG_MONITOR capability are allowed to get full device 2176 // info 2177 // 2178 KernelMIGManager *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu); 2179 NvHandle hClient = RES_GET_CLIENT_HANDLE(pSubdevice); 2180 MIG_INSTANCE_REF ref = kmigmgrMakeNoMIGReference(); 2181 pRef = &ref; 2182 if (IS_MIG_IN_USE(pGpu) && 2183 !rmclientIsCapableByHandle(hClient, NV_RM_CAP_SYS_SMC_MONITOR)) 2184 { 2185 Device *pDevice = GPU_RES_GET_DEVICE(pSubdevice); 2186 // 2187 // Check instanceSubscription to limit the scope of the call 2188 // Clients with mig-monitor capability are allowed to get full device 2189 // info 2190 // 2191 NV_CHECK_OR_RETURN(LEVEL_INFO, (kmigmgrGetInstanceRefFromDevice(pGpu, pKernelMIGManager, 2192 pDevice, pRef) == NV_OK), 2193 NV_ERR_INSUFFICIENT_PERMISSIONS); 2194 bGlobalInfo = NV_FALSE; 2195 } 2196 2197 for (i = 0; i < pGetPidInfoParams->pidInfoListCount; ++i) 2198 { 2199 pPidInfo = &pGetPidInfoParams->pidInfoList[i]; 2200 2201 pSmcInfo = &pPidInfo->smcSubscription; 2202 pSmcInfo->computeInstanceId = PARTITIONID_INVALID; 2203 pSmcInfo->gpuInstanceId = PARTITIONID_INVALID; 2204 2205 switch (pPidInfo->index) 2206 { 2207 case (NV2080_CTRL_GPU_PID_INFO_INDEX_VIDEO_MEMORY_USAGE): 2208 { 2209 internalClassId = classId(Memory); 2210 2211 pPidInfoData = &pPidInfo->data; 2212 portMemSet(pPidInfoData, 0, sizeof(NV2080_CTRL_GPU_PID_INFO_DATA)); 2213 pPidInfo->result = gpuFindClientInfoWithPidIterator(pGpu, pPidInfo->pid, 0, 2214 internalClassId, 2215 pPidInfoData, 2216 pSmcInfo, 2217 pRef, 2218 bGlobalInfo); 2219 break; 2220 } 2221 default: 2222 { 2223 pPidInfo->result = NV_ERR_INVALID_ARGUMENT; 2224 break; 2225 } 2226 } 2227 } 2228 2229 return NV_OK; 2230 } 2231 2232 // Control call to fetch the Runlist pri base for the engine(s) specified 2233 NV_STATUS 2234 subdeviceCtrlCmdGpuGetEngineRunlistPriBase_IMPL 2235 ( 2236 Subdevice *pSubdevice, 2237 NV2080_CTRL_GPU_GET_ENGINE_RUNLIST_PRI_BASE_PARAMS *pParams 2238 ) 2239 { 2240 NV_STATUS status = NV_OK; 2241 NV_STATUS tmpStatus = NV_OK; 2242 NvU32 i; 2243 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 2244 KernelFifo *pKernelFifo = GPU_GET_KERNEL_FIFO(pGpu); 2245 2246 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner()); 2247 2248 if (!kfifoIsHostEngineExpansionSupported(pKernelFifo)) 2249 { 2250 status = NV_ERR_NOT_SUPPORTED; 2251 return status; 2252 } 2253 2254 for (i = 0; i < NV2080_GPU_MAX_ENGINES_LIST_SIZE; i++) 2255 { 2256 RM_ENGINE_TYPE rmEngineType; 2257 2258 // Check if input is NULL or a SW engine; return a NULL value since SW engine does not have a runlist pri base 2259 // and this should not be returned as an error 2260 if ((pParams->engineList[i] == NV2080_ENGINE_TYPE_NULL) || (pParams->engineList[i] == NV2080_ENGINE_TYPE_SW)) 2261 { 2262 pParams->runlistPriBase[i] = NV2080_CTRL_GPU_GET_ENGINE_RUNLIST_PRI_BASE_NULL; 2263 continue; 2264 } 2265 2266 rmEngineType = gpuGetRmEngineType(pParams->engineList[i]); 2267 2268 // 2269 // See if MIG is enabled. If yes, then we have to convert instanceLocal 2270 // engine to global engine before moving ahead 2271 // 2272 if (IS_MIG_IN_USE(pGpu)) 2273 { 2274 KernelMIGManager *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu); 2275 Device *pDevice = GPU_RES_GET_DEVICE(pSubdevice); 2276 MIG_INSTANCE_REF ref; 2277 2278 NV_CHECK_OK_OR_RETURN( 2279 LEVEL_ERROR, 2280 kmigmgrGetInstanceRefFromDevice(pGpu, pKernelMIGManager, 2281 pDevice, &ref)); 2282 2283 NV_CHECK_OK_OR_RETURN( 2284 LEVEL_ERROR, 2285 kmigmgrGetLocalToGlobalEngineType(pGpu, pKernelMIGManager, ref, 2286 rmEngineType, 2287 &rmEngineType)); 2288 } 2289 2290 tmpStatus = kfifoEngineInfoXlate_HAL(pGpu, pKernelFifo, ENGINE_INFO_TYPE_RM_ENGINE_TYPE, 2291 rmEngineType, ENGINE_INFO_TYPE_RUNLIST_PRI_BASE, 2292 &pParams->runlistPriBase[i]); 2293 2294 if (tmpStatus != NV_OK) 2295 { 2296 pParams->runlistPriBase[i] = NV2080_CTRL_GPU_GET_ENGINE_RUNLIST_PRI_BASE_ERROR; 2297 status = tmpStatus; 2298 } 2299 } 2300 return status; 2301 } 2302 2303 // Control call to fetch the HW engine ID for the engine(s) specified 2304 NV_STATUS 2305 subdeviceCtrlCmdGpuGetHwEngineId_IMPL 2306 ( 2307 Subdevice *pSubdevice, 2308 NV2080_CTRL_GPU_GET_HW_ENGINE_ID_PARAMS *pParams 2309 ) 2310 { 2311 NV_STATUS status = NV_OK; 2312 NV_STATUS tmpStatus = NV_OK; 2313 NvU32 i; 2314 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 2315 KernelFifo *pKernelFifo = GPU_GET_KERNEL_FIFO(pGpu); 2316 2317 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner()); 2318 2319 if (!kfifoIsHostEngineExpansionSupported(pKernelFifo)) 2320 { 2321 status = NV_ERR_NOT_SUPPORTED; 2322 return status; 2323 } 2324 2325 for (i = 0; i < NV2080_GPU_MAX_ENGINES_LIST_SIZE; i++) 2326 { 2327 RM_ENGINE_TYPE rmEngineType; 2328 2329 // Check if input is NULL or a SW engine; return a NULL value since SW engine does not have a runlist pri base 2330 // and this should not be returned as an error 2331 if (pParams->engineList[i] == NV2080_ENGINE_TYPE_NULL || (pParams->engineList[i] == NV2080_ENGINE_TYPE_SW)) 2332 { 2333 pParams->hwEngineID[i] = NV2080_CTRL_GPU_GET_HW_ENGINE_ID_NULL; 2334 continue; 2335 } 2336 2337 rmEngineType = gpuGetRmEngineType(pParams->engineList[i]); 2338 2339 // 2340 // See if MIG is enabled. If yes, then we have to convert instanceLocal 2341 // engine to global engine before moving ahead 2342 // 2343 if (IS_MIG_IN_USE(pGpu)) 2344 { 2345 KernelMIGManager *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu); 2346 Device *pDevice = GPU_RES_GET_DEVICE(pSubdevice); 2347 MIG_INSTANCE_REF ref; 2348 2349 NV_CHECK_OK_OR_RETURN( 2350 LEVEL_ERROR, 2351 kmigmgrGetInstanceRefFromDevice(pGpu, pKernelMIGManager, 2352 pDevice, &ref)); 2353 2354 NV_CHECK_OK_OR_RETURN( 2355 LEVEL_ERROR, 2356 kmigmgrGetLocalToGlobalEngineType(pGpu, pKernelMIGManager, ref, 2357 rmEngineType, 2358 &rmEngineType)); 2359 } 2360 2361 tmpStatus = kfifoEngineInfoXlate_HAL(pGpu, pKernelFifo, ENGINE_INFO_TYPE_RM_ENGINE_TYPE, 2362 (NvU32)rmEngineType, 2363 ENGINE_INFO_TYPE_FIFO_TAG, 2364 &pParams->hwEngineID[i]); 2365 2366 if (tmpStatus != NV_OK) 2367 { 2368 pParams->hwEngineID[i] = NV2080_CTRL_GPU_GET_HW_ENGINE_ID_ERROR; 2369 status = tmpStatus; 2370 } 2371 } 2372 return status; 2373 } 2374 2375 NV_STATUS 2376 subdeviceCtrlCmdGpuGetMaxSupportedPageSize_IMPL 2377 ( 2378 Subdevice *pSubdevice, 2379 NV2080_CTRL_GPU_GET_MAX_SUPPORTED_PAGE_SIZE_PARAMS *pParams 2380 ) 2381 { 2382 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 2383 NV_STATUS status = NV_OK; 2384 2385 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmDeviceGpuLockIsOwner(pGpu->gpuInstance)); 2386 2387 // Default to minimal page size (4k) 2388 pParams->maxSupportedPageSize = RM_PAGE_SIZE; 2389 2390 if (IS_VIRTUAL(pGpu)) 2391 { 2392 VGPU_STATIC_INFO *pVSI = GPU_GET_STATIC_INFO(pGpu); 2393 2394 pParams->maxSupportedPageSize = pVSI->maxSupportedPageSize; 2395 2396 return status; 2397 } 2398 2399 KernelGmmu *pKernelGmmu = GPU_GET_KERNEL_GMMU(pGpu); 2400 2401 if (kgmmuIsPageSize512mbSupported(pKernelGmmu)) 2402 { 2403 pParams->maxSupportedPageSize = RM_PAGE_SIZE_512M; 2404 } 2405 else if (kgmmuIsHugePageSupported(pKernelGmmu)) 2406 { 2407 pParams->maxSupportedPageSize = RM_PAGE_SIZE_HUGE; 2408 } 2409 else 2410 { 2411 pParams->maxSupportedPageSize = (NvU32)kgmmuGetMaxBigPageSize_HAL(pKernelGmmu); 2412 } 2413 2414 if (gpuIsSriovEnabled(pGpu) 2415 || gpuIsCCFeatureEnabled(pGpu) 2416 ) 2417 { 2418 NvU64 vmmuSegmentSize = gpuGetVmmuSegmentSize(pGpu); 2419 if (vmmuSegmentSize > 0 && 2420 vmmuSegmentSize < NV2080_CTRL_GPU_VMMU_SEGMENT_SIZE_512MB) 2421 { 2422 pParams->maxSupportedPageSize = RM_PAGE_SIZE_HUGE; 2423 } 2424 } 2425 2426 return status; 2427 } 2428 2429 #if (defined(DEBUG) || defined(DEVELOP) || RMCFG_FEATURE_MODS_FEATURES) && RMCFG_MODULE_KERNEL_GRAPHICS 2430 NV_STATUS 2431 subdeviceCtrlCmdGpuGetNumMmusPerGpc_IMPL 2432 ( 2433 Subdevice *pSubdevice, 2434 NV2080_CTRL_GPU_GET_NUM_MMUS_PER_GPC_PARAMS *pParams 2435 ) 2436 { 2437 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 2438 KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu); 2439 KernelGraphics *pKernelGraphics; 2440 const KGRAPHICS_STATIC_INFO *pKernelGraphicsStaticInfo; 2441 NvU32 count; 2442 NvU32 maxGpcCount; 2443 2444 // Ensure that the gpcId is within range 2445 maxGpcCount = gpuGetLitterValues_HAL(pGpu, NV2080_CTRL_GR_INFO_INDEX_LITTER_NUM_GPCS); 2446 if (pParams->gpcId >= maxGpcCount) 2447 { 2448 return NV_ERR_INVALID_ARGUMENT; 2449 } 2450 2451 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, 2452 kgrmgrCtrlRouteKGRWithDevice(pGpu, pKernelGraphicsManager, 2453 GPU_RES_GET_DEVICE(pSubdevice), 2454 &pParams->grRouteInfo, &pKernelGraphics)); 2455 2456 pKernelGraphicsStaticInfo = kgraphicsGetStaticInfo(pGpu, pKernelGraphics); 2457 NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo != NULL, NV_ERR_INVALID_STATE); 2458 2459 count = pKernelGraphicsStaticInfo->floorsweepingMasks.mmuPerGpc[pParams->gpcId]; 2460 2461 // If the litter value doesn't exist (pre Ampere) than default to 1 gpcmmu 2462 pParams->count = ((count != 0) ? count : 1); 2463 2464 return NV_OK; 2465 } 2466 #endif 2467 2468 // Stubbed for Orin 2469 2470 /* 2471 * @brief Update/Set the compute policy config for a GPU 2472 * 2473 * @param[in] pSubdevice 2474 * @param[in] pParams pointer to control parameters 2475 * 2476 * @return 2477 * NV_OK Success 2478 * NV_ERR_NOT_SUPPORTED Setting policy is not supported on requested GPU 2479 * NV_ERR_INVALID_ARGUMENT Invalid config type/value specified 2480 * else appropriate error code. 2481 */ 2482 NV_STATUS 2483 subdeviceCtrlCmdGpuSetComputePolicyConfig_IMPL 2484 ( 2485 Subdevice *pSubdevice, 2486 NV2080_CTRL_GPU_SET_COMPUTE_POLICY_CONFIG_PARAMS *pParams 2487 ) 2488 { 2489 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 2490 GPU_COMPUTE_POLICY_INFO policyInfo; 2491 NvU32 gidFlags; 2492 NV_STATUS status = NV_OK; 2493 2494 switch(pParams->config.type) 2495 { 2496 case NV2080_CTRL_GPU_COMPUTE_POLICY_TIMESLICE: 2497 if (!gpuIsComputePolicyTimesliceSupported(pGpu)) 2498 { 2499 NV_PRINTF(LEVEL_ERROR, "Setting the timeslice policy is not supported for gpu with pci id 0x%llx\n", 2500 gpuGetDBDF(pGpu)); 2501 return NV_ERR_NOT_SUPPORTED; 2502 2503 } 2504 2505 if (pParams->config.data.timeslice >= NV2080_CTRL_CMD_GPU_COMPUTE_TIMESLICE_MAX) 2506 { 2507 NV_PRINTF(LEVEL_ERROR, "Unsupported timeslice value %u specified for gpu with pci id 0x%llx\n", 2508 pParams->config.data.timeslice, gpuGetDBDF(pGpu)); 2509 return NV_ERR_INVALID_ARGUMENT; 2510 } 2511 2512 policyInfo.timeslice = pParams->config.data.timeslice; 2513 break; 2514 default: 2515 NV_PRINTF(LEVEL_ERROR, "Unsupported compute policy %u specified for gpu id 0x%llx\n", 2516 pParams->config.type, gpuGetDBDF(pGpu)); 2517 return NV_ERR_INVALID_ARGUMENT; 2518 } 2519 2520 gidFlags = DRF_DEF(2080_GPU_CMD, _GPU_GET_GID_FLAGS, _TYPE, _SHA1) | 2521 DRF_DEF(2080_GPU_CMD, _GPU_GET_GID_FLAGS, _FORMAT, _BINARY); 2522 status = gpuGetGidInfo(pGpu, NULL, NULL, gidFlags); 2523 if (status != NV_OK) 2524 { 2525 return status; 2526 } 2527 2528 NV_ASSERT(pGpu->gpuUuid.isInitialized); 2529 status = gpudbSetGpuComputePolicyConfig(pGpu->gpuUuid.uuid, pParams->config.type, 2530 &policyInfo); 2531 2532 return status; 2533 } 2534 2535 // 2536 // Make sure number of compute policies per GPU is always less than or equal 2537 // to the number of policy configs that can be handled by the 2538 // NV2080_CTRL_CMD_GPU_GET_COMPUTE_POLICY_CONFIG command. 2539 // 2540 ct_assert(NV2080_CTRL_GPU_COMPUTE_POLICY_MAX <= NV2080_CTRL_GPU_COMPUTE_POLICY_CONFIG_LIST_MAX); 2541 2542 /* 2543 * @brief Get all compute policy configs for a GPU 2544 * 2545 * @param[in] pSubdevice 2546 * @param[in] pParams pointer to control parameters 2547 * 2548 * @return 2549 * NV_OK on success 2550 * else appropriate error code. 2551 */ 2552 NV_STATUS 2553 subdeviceCtrlCmdGpuGetComputePolicyConfig_IMPL 2554 ( 2555 Subdevice *pSubdevice, 2556 NV2080_CTRL_GPU_GET_COMPUTE_POLICY_CONFIG_PARAMS *pParams 2557 ) 2558 { 2559 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 2560 GPU_COMPUTE_POLICY_INFO policyInfo; 2561 NvU32 policyId; 2562 NvU32 gidFlags; 2563 NV_STATUS status = NV_OK; 2564 2565 gidFlags = DRF_DEF(2080_GPU_CMD, _GPU_GET_GID_FLAGS, _TYPE, _SHA1) | 2566 DRF_DEF(2080_GPU_CMD, _GPU_GET_GID_FLAGS, _FORMAT, _BINARY); 2567 status = gpuGetGidInfo(pGpu, NULL, NULL, gidFlags); 2568 if (status != NV_OK) 2569 { 2570 return status; 2571 } 2572 2573 NV_ASSERT(pGpu->gpuUuid.isInitialized); 2574 status = gpudbGetGpuComputePolicyConfigs(pGpu->gpuUuid.uuid, &policyInfo); 2575 if (status != NV_OK) 2576 { 2577 return status; 2578 } 2579 2580 pParams->numConfigs = 0; 2581 // Loop through all compute policies and retrieve the configured settings 2582 for (policyId = NV2080_CTRL_GPU_COMPUTE_POLICY_TIMESLICE; 2583 policyId < NV2080_CTRL_GPU_COMPUTE_POLICY_MAX; 2584 policyId++) 2585 { 2586 switch (policyId) 2587 { 2588 case NV2080_CTRL_GPU_COMPUTE_POLICY_TIMESLICE: 2589 pParams->configList[policyId].type = NV2080_CTRL_GPU_COMPUTE_POLICY_TIMESLICE; 2590 pParams->configList[policyId].data.timeslice = policyInfo.timeslice; 2591 pParams->numConfigs++; 2592 break; 2593 default: 2594 NV_ASSERT(0); 2595 break; 2596 } 2597 } 2598 2599 return status; 2600 } 2601 2602 /*! 2603 * @brief Check if address range is within the provided limits 2604 * 2605 * @param[in] addrStart Staring address of address range 2606 * @param[in] addrLength Size of address range 2607 * @param[in] limitStart Staring address of limit 2608 * @param[in] limitLength Size of limit 2609 * 2610 * @return 2611 * NV_TRUE, if address range is within the provided limits 2612 * NV_FALSE, if address range is outside the provided limits 2613 * 2614 */ 2615 static NvBool isAddressWithinLimits 2616 ( 2617 NvU64 addrStart, 2618 NvU64 addrLength, 2619 NvU64 limitStart, 2620 NvU64 limitLength 2621 ) 2622 { 2623 NvU64 addrEnd = 0; 2624 NvU64 limitEnd = 0; 2625 2626 // 2627 // Calculate End address of address range and limit, 2628 // Return NV_FALSE in case of 64-bit addition overflow 2629 // 2630 if (!portSafeAddU64(addrStart, addrLength - 1, &addrEnd) || 2631 !portSafeAddU64(limitStart, limitLength - 1, &limitEnd)) 2632 { 2633 return NV_FALSE; 2634 } 2635 2636 return ((addrStart >= limitStart) && (addrEnd <= limitEnd)); 2637 } 2638 2639 /*! 2640 * @brief Validate the address range for Memory Map request by comparing the 2641 * user supplied address range with GPU BAR0/BAR1 range. 2642 * 2643 * Lock Requirements: 2644 * Assert that API and GPUs lock held on entry 2645 * 2646 * @param[in] pSubdevice 2647 * @param[in] pParams pointer to control parameters 2648 * 2649 * Possible status values returned are: 2650 * NV_OK 2651 * NV_ERR_PROTECTION_FAULT 2652 * 2653 */ 2654 NV_STATUS subdeviceCtrlCmdValidateMemMapRequest_IMPL 2655 ( 2656 Subdevice *pSubdevice, 2657 NV2080_CTRL_GPU_VALIDATE_MEM_MAP_REQUEST_PARAMS *pParams 2658 ) 2659 { 2660 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 2661 NvU64 start = pParams->addressStart; 2662 NvU64 length = pParams->addressLength; 2663 NV_STATUS rmStatus; 2664 NvU32 bar0MapSize; 2665 NvU64 bar0MapOffset; 2666 2667 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmDeviceGpuLockIsOwner(GPU_RES_GET_GPU(pSubdevice)->gpuInstance)); 2668 2669 pParams->protection = NV_PROTECT_READ_WRITE; 2670 2671 if (isAddressWithinLimits(start, length, pGpu->busInfo.gpuPhysAddr, 2672 pGpu->deviceMappings[0].gpuNvLength)) 2673 { 2674 start -= pGpu->busInfo.gpuPhysAddr; 2675 2676 OBJTMR *pTmr = GPU_GET_TIMER(pGpu); 2677 rmStatus = tmrGetTimerBar0MapInfo_HAL(pGpu, pTmr, 2678 &bar0MapOffset, &bar0MapSize); 2679 if ((rmStatus == NV_OK) && 2680 isAddressWithinLimits(start, length, bar0MapOffset, bar0MapSize)) 2681 { 2682 pParams->protection = NV_PROTECT_READABLE; 2683 return NV_OK; 2684 } 2685 2686 KernelFifo *pKernelFifo = GPU_GET_KERNEL_FIFO(pGpu); 2687 rmStatus = kfifoGetUsermodeMapInfo_HAL(pGpu, pKernelFifo, 2688 &bar0MapOffset, &bar0MapSize); 2689 if ((rmStatus == NV_OK) && 2690 isAddressWithinLimits(start, length, bar0MapOffset, bar0MapSize)) 2691 { 2692 return NV_OK; 2693 } 2694 2695 KernelMc *pKernelMc = GPU_GET_KERNEL_MC(pGpu); 2696 rmStatus = kmcGetMcBar0MapInfo_HAL(pGpu, pKernelMc, 2697 &bar0MapOffset, &bar0MapSize); 2698 if ((rmStatus == NV_OK) && 2699 isAddressWithinLimits(start, length, bar0MapOffset, bar0MapSize)) 2700 { 2701 pParams->protection = NV_PROTECT_READABLE; 2702 return NV_OK; 2703 } 2704 2705 // 2706 // If the kernel side does not know about the object being mapped, 2707 // fall-through to GSP and see if it knows anything. 2708 // 2709 if (IS_GSP_CLIENT(pGpu)) 2710 { 2711 RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu); 2712 2713 return pRmApi->Control(pRmApi, 2714 pGpu->hInternalClient, 2715 pGpu->hInternalSubdevice, 2716 NV2080_CTRL_CMD_GPU_VALIDATE_MEM_MAP_REQUEST, 2717 pParams, sizeof(*pParams)); 2718 } 2719 2720 return NV_ERR_PROTECTION_FAULT; 2721 } 2722 // See bug 1784955 2723 else if (isAddressWithinLimits(start, length, pGpu->busInfo.gpuPhysFbAddr, pGpu->fbLength) 2724 || GPU_GET_KERNEL_MEMORY_SYSTEM(pGpu)->coherentCpuFbBase) 2725 { 2726 return NV_OK; 2727 } 2728 2729 return NV_ERR_PROTECTION_FAULT; 2730 } 2731 2732 /*! 2733 * @brief Computes the GFID (GPU Function ID) for a given SR-IOV 2734 * Virtual Function (VF) of the physical GPU based on the 2735 * BDF parameters provided by the caller. 2736 * 2737 * Lock Requirements: 2738 * Assert that API and GPUs lock held on entry 2739 * 2740 * @param[in] pSubdevice 2741 * @param[in] pParams pointer to control parameters 2742 * 2743 * Possible status values returned are: 2744 * NV_OK on successful computation of a valid GFID 2745 * NV_ERR_NOT_SUPPORTED if ctrl call is made when 2746 * SRIOV is not enabled OR 2747 * caller is not FM from Host RM 2748 * NV_ERR_INVALID_STATE if computed GFID is greater than 2749 * max GFID that is expected/allowed 2750 */ 2751 NV_STATUS 2752 subdeviceCtrlCmdGpuGetGfid_IMPL 2753 ( 2754 Subdevice *pSubdevice, 2755 NV2080_CTRL_GPU_GET_GFID_PARAMS *pParams 2756 ) 2757 { 2758 OBJSYS *pSys = SYS_GET_INSTANCE(); 2759 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 2760 NvU32 pciFunction, gfid; 2761 2762 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner()); 2763 2764 if (!gpuIsSriovEnabled(pGpu)) 2765 return NV_ERR_NOT_SUPPORTED; 2766 2767 // Host RM && FM 2768 if ((!IS_VIRTUAL(pGpu)) && 2769 (pSys->getProperty(pSys, PDB_PROP_SYS_FABRIC_IS_EXTERNALLY_MANAGED))) 2770 { 2771 // 2772 // In unix based systems, OS uses lspci format which is "ssss:bb:dd.f", 2773 // so device is 5 bits and function 3 bits. 2774 // for SR-IOV when ARI is enabled, device and function gets combined and 2775 // we need to consider 8 bits function. 2776 // 2777 pciFunction = (pParams->device << 3) | pParams->func; 2778 gfid = (pciFunction - pGpu->sriovState.firstVFOffset) + 1; 2779 2780 if (gfid > pGpu->sriovState.maxGfid) 2781 { 2782 NV_PRINTF(LEVEL_ERROR, "Computed GFID %d greater than max supported GFID\n", gfid); 2783 return NV_ERR_INVALID_STATE; 2784 } 2785 2786 pParams->gfid = gfid; 2787 // Also set the mask for max gfid supported currently in the driver 2788 pParams->gfidMask = (pGpu->sriovState.maxGfid - 1); 2789 } 2790 else 2791 { 2792 return NV_ERR_NOT_SUPPORTED; 2793 } 2794 2795 return NV_OK; 2796 } 2797 2798 /*! 2799 * @brief Sets or unsets the SW state to inform the GPU driver that the GPU instance 2800 * associated with input GFID has been activated or de-activated respectively. 2801 * 2802 * Lock Requirements: 2803 * Assert that API and GPUs lock held on entry 2804 * 2805 * @param[in] pSubdevice 2806 * @param[in] pParams pointer to control parameters 2807 * 2808 * Possible status values returned are: 2809 * NV_OK on success 2810 * NV_ERR_INVALID_STATE if SRIOV state for P2P in driver is not setup 2811 * NV_ERR_INVALID_ARGUMENT if input GFID is greater than the max GFID allowed 2812 * NV_ERR_NOT_SUPPORTED if ctrl call is made when 2813 * SRIOV is not enabled OR 2814 * caller is not FM from Host RM 2815 * NV_ERR_IN_USE If MAX_NUM_P2P_GFIDS have already been enabled for P2P 2816 */ 2817 NV_STATUS 2818 gpuUpdateGfidP2pCapability 2819 ( 2820 OBJGPU *pGpu, 2821 NV2080_CTRL_CMD_GPU_UPDATE_GFID_P2P_CAPABILITY_PARAMS *pParams 2822 ) 2823 { 2824 OBJSYS *pSys = SYS_GET_INSTANCE(); 2825 PSRIOV_P2P_INFO pP2PInfo = pGpu->sriovState.pP2PInfo; 2826 NvBool bSetP2PAccess = NV_FALSE; 2827 NvU32 idx; 2828 2829 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner()); 2830 2831 if (!gpuIsSriovEnabled(pGpu)) 2832 return NV_ERR_NOT_SUPPORTED; 2833 2834 NV_ASSERT_OR_RETURN(pP2PInfo != NULL, NV_ERR_INVALID_STATE); 2835 2836 // Ctrl call should only be called by the FM from Host RM 2837 if ((!IS_VIRTUAL(pGpu)) && 2838 (pSys->getProperty(pSys, PDB_PROP_SYS_FABRIC_IS_EXTERNALLY_MANAGED))) 2839 { 2840 if (pParams->gfid > pGpu->sriovState.maxGfid) 2841 { 2842 NV_PRINTF(LEVEL_ERROR, "Input GFID %d greater than max allowed GFID\n", pParams->gfid); 2843 return NV_ERR_INVALID_ARGUMENT; 2844 } 2845 2846 for (idx = 0; idx < pGpu->sriovState.maxP2pGfid; idx++) 2847 { 2848 // 2849 // Check if Host RM is already using a GFID for P2P, 2850 // Since only "MAX_NUM_P2P_GFIDS" GFID(s) is(are) allowed to do P2P at any time, 2851 // we should fail here if a GFID greater than supported number is being enabled 2852 // 2853 if (pParams->bEnable) 2854 { 2855 if (pP2PInfo[idx].gfid == INVALID_P2P_GFID) 2856 { 2857 pP2PInfo[idx].gfid = pParams->gfid; 2858 pGpu->sriovState.p2pFabricPartitionId = pParams->fabricPartitionId; 2859 bSetP2PAccess = NV_TRUE; 2860 break; 2861 } 2862 } 2863 else 2864 { 2865 if (pP2PInfo[idx].gfid == pParams->gfid) 2866 { 2867 pP2PInfo[idx].gfid = INVALID_P2P_GFID; 2868 pGpu->sriovState.p2pFabricPartitionId = INVALID_FABRIC_PARTITION_ID; 2869 bSetP2PAccess = NV_TRUE; 2870 break; 2871 } 2872 } 2873 } 2874 2875 if (bSetP2PAccess == NV_TRUE) 2876 { 2877 pP2PInfo[idx].bAllowP2pAccess = pParams->bEnable; 2878 } 2879 else 2880 { 2881 // Some other GFID(s) has already been enabled to do P2P 2882 // Fail the call 2883 return NV_ERR_IN_USE; 2884 } 2885 } 2886 else 2887 { 2888 return NV_ERR_NOT_SUPPORTED; 2889 } 2890 2891 return NV_OK; 2892 } 2893 2894 NV_STATUS 2895 subdeviceCtrlCmdUpdateGfidP2pCapability_IMPL 2896 ( 2897 Subdevice *pSubdevice, 2898 NV2080_CTRL_CMD_GPU_UPDATE_GFID_P2P_CAPABILITY_PARAMS *pParams 2899 ) 2900 { 2901 return gpuUpdateGfidP2pCapability(GPU_RES_GET_GPU(pSubdevice), pParams); 2902 } 2903 /* 2904 * Set the EGM fabric base address 2905 */ 2906 NV_STATUS 2907 subdeviceCtrlCmdGpuSetEgmGpaFabricAddr_IMPL 2908 ( 2909 Subdevice *pSubdevice, 2910 NV2080_CTRL_GPU_SET_EGM_GPA_FABRIC_BASE_ADDR_PARAMS *pParams 2911 ) 2912 { 2913 return NV_OK; 2914 } 2915 2916 /*! 2917 * @brief: This command returns the load time (latency) of each engine, 2918 * implementing NV2080_CTRL_CMD_GPU_GET_ENGINE_LOAD_TIMES control call. 2919 * 2920 * @param[in] pSubdevice 2921 * @param[in] pParams 2922 * 2923 * @return 2924 * NV_OK Success 2925 */ 2926 NV_STATUS 2927 subdeviceCtrlCmdGpuGetEngineLoadTimes_IMPL 2928 ( 2929 Subdevice *pSubdevice, 2930 NV2080_CTRL_GPU_GET_ENGINE_LOAD_TIMES_PARAMS *pParams 2931 ) 2932 { 2933 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 2934 PENGDESCRIPTOR engDescriptorList = gpuGetInitEngineDescriptors(pGpu); 2935 NvU32 numEngDescriptors = gpuGetNumEngDescriptors(pGpu); 2936 NvU32 curEngDescIdx; 2937 2938 NV_ASSERT_OR_RETURN(numEngDescriptors < NV2080_CTRL_GPU_MAX_ENGINE_OBJECTS, NV_ERR_BUFFER_TOO_SMALL); 2939 2940 pParams->engineCount = numEngDescriptors; 2941 for (curEngDescIdx = 0; curEngDescIdx < numEngDescriptors; curEngDescIdx++) 2942 { 2943 ENGDESCRIPTOR curEngDescriptor = engDescriptorList[curEngDescIdx]; 2944 OBJENGSTATE *pEngstate = gpuGetEngstate(pGpu, curEngDescriptor); 2945 2946 if (pEngstate == NULL) 2947 { 2948 pParams->engineIsInit[curEngDescIdx] = NV_FALSE; 2949 continue; 2950 } 2951 2952 pParams->engineList[curEngDescIdx] = pEngstate->engDesc; 2953 pParams->engineStateLoadTime[curEngDescIdx] = pEngstate->stats[ENGSTATE_STATE_LOAD].transitionTimeUs * 1000; 2954 pParams->engineIsInit[curEngDescIdx] = NV_TRUE; 2955 } 2956 2957 return NV_OK; 2958 } 2959 2960 // 2961 // subdeviceCtrlCmdGpuSetFabricAddr 2962 // 2963 // Lock Requirements: 2964 // Assert that API lock and GPUs lock held on entry 2965 // 2966 NV_STATUS 2967 subdeviceCtrlCmdGpuSetFabricAddr_IMPL 2968 ( 2969 Subdevice *pSubdevice, 2970 NV2080_CTRL_GPU_SET_FABRIC_BASE_ADDR_PARAMS *pParams 2971 ) 2972 { 2973 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 2974 NvHandle hClient = RES_GET_CLIENT_HANDLE(pSubdevice); 2975 CALL_CONTEXT *pCallContext = resservGetTlsCallContext(); 2976 2977 NV_ASSERT_OR_RETURN(RMCFG_FEATURE_KERNEL_RM, NV_ERR_NOT_SUPPORTED); 2978 NV_ASSERT_OR_RETURN(pCallContext != NULL, NV_ERR_INVALID_STATE); 2979 2980 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner()); 2981 2982 if (!rmclientIsCapableOrAdminByHandle(hClient, 2983 NV_RM_CAP_EXT_FABRIC_MGMT, 2984 pCallContext->secInfo.privLevel)) 2985 { 2986 NV_PRINTF(LEVEL_ERROR, "Non-privileged context issued privileged cmd\n"); 2987 return NV_ERR_INSUFFICIENT_PERMISSIONS; 2988 } 2989 2990 KernelNvlink *pKernelNvlink = GPU_GET_KERNEL_NVLINK(pGpu); 2991 2992 if (pKernelNvlink == NULL) 2993 return NV_ERR_NOT_SUPPORTED; 2994 2995 return knvlinkSetUniqueFabricBaseAddress(pGpu, pKernelNvlink, pParams->fabricBaseAddr); 2996 } 2997 2998 static NvU64 2999 _convertGpuFabricProbeInfoCaps 3000 ( 3001 NvU64 fmCaps 3002 ) 3003 { 3004 NvU64 fabricCaps = 0; 3005 NvU32 i = 0; 3006 3007 FOR_EACH_INDEX_IN_MASK(64, i, fmCaps) 3008 { 3009 switch (NVBIT64(i)) 3010 { 3011 case NVLINK_INBAND_FM_CAPS_MC_TEAM_SETUP_V1: 3012 case NVLINK_INBAND_FM_CAPS_MC_TEAM_RELEASE_V1: 3013 { 3014 fabricCaps |= NV2080_CTRL_GPU_FABRIC_PROBE_CAP_MC_SUPPORTED; 3015 break; 3016 } 3017 case NVLINK_INBAND_FM_CAPS_MC_TEAM_SETUP_V2: 3018 { 3019 fabricCaps |= NV2080_CTRL_GPU_FABRIC_PROBE_CAP_MC_SUPPORTED; 3020 #ifdef NV2080_CTRL_GPU_FABRIC_PROBE_CAP_MC_MUTLINODE_SUPPORTED 3021 fabricCaps |= 3022 NV2080_CTRL_GPU_FABRIC_PROBE_CAP_MC_MUTLINODE_SUPPORTED; 3023 #endif 3024 break; 3025 } 3026 default: 3027 { 3028 break; 3029 } 3030 } 3031 } 3032 FOR_EACH_INDEX_IN_MASK_END; 3033 3034 return fabricCaps; 3035 } 3036 3037 NV_STATUS 3038 subdeviceCtrlCmdGetGpuFabricProbeInfo_IMPL 3039 ( 3040 Subdevice *pSubdevice, 3041 NV2080_CTRL_CMD_GET_GPU_FABRIC_PROBE_INFO_PARAMS *pParams 3042 ) 3043 { 3044 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 3045 NV_STATUS status; 3046 NvU64 numProbeReqs = 0; 3047 NvU64 fmCaps = 0; 3048 NvUuid *pClusterUuid = (NvUuid*) pParams->clusterUuid; 3049 NvU32 mask = 0, healthMask = 0; 3050 3051 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && 3052 rmDeviceGpuLockIsOwner(gpuGetInstance(pGpu))); 3053 3054 // Probe is not supported - Ex - Direct connected etc. 3055 if (!gpuFabricProbeIsSupported(pGpu)) 3056 { 3057 pParams->state = NV2080_CTRL_GPU_FABRIC_PROBE_STATE_UNSUPPORTED; 3058 return NV_OK; 3059 } 3060 3061 // Probe is not supported - Ex - GPU is degraded etc. 3062 if (pGpu->pGpuFabricProbeInfoKernel == NULL) 3063 { 3064 pParams->state = NV2080_CTRL_GPU_FABRIC_PROBE_STATE_COMPLETE; 3065 pParams->status = NV_ERR_NOT_SUPPORTED; // Due to degradation etc. 3066 return NV_OK; 3067 } 3068 3069 status = gpuFabricProbeGetNumProbeReqs(pGpu->pGpuFabricProbeInfoKernel, 3070 &numProbeReqs); 3071 if (status != NV_OK) 3072 { 3073 NV_PRINTF(LEVEL_ERROR, "Error while retrieving numProbeReqs\n"); 3074 return status; 3075 } 3076 3077 pParams->state = (numProbeReqs == 0) ? 3078 NV2080_CTRL_GPU_FABRIC_PROBE_STATE_NOT_STARTED : 3079 NV2080_CTRL_GPU_FABRIC_PROBE_STATE_IN_PROGRESS; 3080 3081 if (!gpuFabricProbeIsReceived(pGpu->pGpuFabricProbeInfoKernel)) 3082 { 3083 return NV_OK; 3084 } 3085 3086 pParams->state = NV2080_CTRL_GPU_FABRIC_PROBE_STATE_COMPLETE; 3087 pParams->status = gpuFabricProbeGetFmStatus(pGpu->pGpuFabricProbeInfoKernel); 3088 if (pParams->status != NV_OK) 3089 { 3090 // Nothing needs to be done as probe response status is not success 3091 return NV_OK; 3092 } 3093 3094 ct_assert(NV2080_GPU_FABRIC_CLUSTER_UUID_LEN == NV_UUID_LEN); 3095 3096 status = gpuFabricProbeGetClusterUuid(pGpu->pGpuFabricProbeInfoKernel, pClusterUuid); 3097 NV_ASSERT_OK_OR_RETURN(status); 3098 3099 status = gpuFabricProbeGetFabricPartitionId(pGpu->pGpuFabricProbeInfoKernel, 3100 &pParams->fabricPartitionId); 3101 NV_ASSERT_OK_OR_RETURN(status); 3102 3103 status = gpuFabricProbeGetfmCaps(pGpu->pGpuFabricProbeInfoKernel, &fmCaps); 3104 NV_ASSERT_OK_OR_RETURN(status); 3105 3106 pParams->fabricCaps = _convertGpuFabricProbeInfoCaps(fmCaps); 3107 3108 status = gpuFabricProbeGetFabricCliqueId(pGpu->pGpuFabricProbeInfoKernel, 3109 &pParams->fabricCliqueId); 3110 NV_ASSERT_OK_OR_RETURN(status); 3111 3112 status = gpuFabricProbeGetFabricHealthStatus(pGpu->pGpuFabricProbeInfoKernel, 3113 &mask); 3114 NV_ASSERT_OK_OR_RETURN(status); 3115 3116 if (FLD_TEST_DRF(LINK, _INBAND_FABRIC_HEALTH_MASK, _DEGRADED_BW, _TRUE, mask)) 3117 { 3118 healthMask |= FLD_SET_DRF(2080, _CTRL_GPU_FABRIC_HEALTH_MASK, 3119 _DEGRADED_BW, _TRUE, healthMask); 3120 } 3121 else if (FLD_TEST_DRF(LINK, _INBAND_FABRIC_HEALTH_MASK, _DEGRADED_BW, 3122 _FALSE, mask)) 3123 { 3124 healthMask |= FLD_SET_DRF(2080, _CTRL_GPU_FABRIC_HEALTH_MASK, 3125 _DEGRADED_BW, _FALSE, healthMask); 3126 } 3127 else if (FLD_TEST_DRF(LINK, _INBAND_FABRIC_HEALTH_MASK, _DEGRADED_BW, 3128 _NOT_SUPPORTED, mask)) 3129 { 3130 healthMask |= FLD_SET_DRF(2080, _CTRL_GPU_FABRIC_HEALTH_MASK, 3131 _DEGRADED_BW, _NOT_SUPPORTED, healthMask); 3132 } 3133 3134 pParams->fabricHealthMask = healthMask; 3135 3136 return NV_OK; 3137 } 3138 3139 /*! 3140 * @brief This command is used to determine which GSP features are 3141 * supported on this GPU. 3142 * 3143 * @param[in] pSubdevice 3144 * @param[in,out] pGspFeaturesParams 3145 * 3146 * @return Returns NV_STATUS 3147 * NV_OK Success 3148 */ 3149 NV_STATUS 3150 subdeviceCtrlCmdGspGetFeatures_KERNEL 3151 ( 3152 Subdevice *pSubdevice, 3153 NV2080_CTRL_GSP_GET_FEATURES_PARAMS *pGspFeaturesParams 3154 ) 3155 { 3156 pGspFeaturesParams->bValid = NV_FALSE; 3157 return NV_OK; 3158 } 3159 3160 // 3161 // Lock Requirements: 3162 // Assert that API lock and GPUs lock held on entry 3163 // 3164 NV_STATUS 3165 subdeviceCtrlCmdGpuGetNameString_IMPL 3166 ( 3167 Subdevice *pSubdevice, 3168 NV2080_CTRL_GPU_GET_NAME_STRING_PARAMS *pNameStringParams 3169 ) 3170 { 3171 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 3172 3173 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner()); 3174 3175 return gpuGetNameString(pGpu, 3176 pNameStringParams->gpuNameStringFlags, 3177 (void *)&pNameStringParams->gpuNameString); 3178 } 3179 3180 // 3181 // subdeviceCtrlCmdGpuGetShortNameString 3182 // 3183 // Lock Requirements: 3184 // Assert that API lock and GPUs lock held on entry 3185 // 3186 NV_STATUS 3187 subdeviceCtrlCmdGpuGetShortNameString_IMPL 3188 ( 3189 Subdevice *pSubdevice, 3190 NV2080_CTRL_GPU_GET_SHORT_NAME_STRING_PARAMS *pShortNameStringParams 3191 ) 3192 { 3193 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 3194 3195 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner()); 3196 3197 return gpuGetShortNameString(pGpu, (void *)&pShortNameStringParams->gpuShortNameString); 3198 } 3199 3200 // 3201 // subdeviceCtrlCmdGpuGetGidInfo 3202 // 3203 // Lock Requirements: 3204 // Assert that API lock held on entry 3205 // 3206 NV_STATUS 3207 subdeviceCtrlCmdGpuGetGidInfo_IMPL 3208 ( 3209 Subdevice *pSubdevice, 3210 NV2080_CTRL_GPU_GET_GID_INFO_PARAMS *pGidInfoParams 3211 ) 3212 { 3213 NV_STATUS rmStatus = NV_OK; 3214 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 3215 NvU8 *pGidString; 3216 NvU32 flags = pGidInfoParams->flags; 3217 NvU32 gidStrlen; 3218 3219 rmStatus = gpuGetGidInfo(pGpu, &pGidString, &gidStrlen, flags); 3220 if (rmStatus == NV_OK) 3221 { 3222 if (sizeof(pGidInfoParams->data) >= gidStrlen) 3223 { 3224 portMemCopy(pGidInfoParams->data, gidStrlen, pGidString, gidStrlen); 3225 pGidInfoParams->length = gidStrlen; 3226 } 3227 else 3228 { 3229 rmStatus = NV_ERR_INSUFFICIENT_RESOURCES; 3230 } 3231 3232 portMemFree(pGidString); 3233 } 3234 3235 return rmStatus; 3236 } 3237 3238 // Control call to report a nonreplayable fault from UVM 3239 NV_STATUS 3240 subdeviceCtrlCmdGpuReportNonReplayableFault_IMPL 3241 ( 3242 Subdevice *pSubdevice, 3243 NV2080_CTRL_GPU_REPORT_NON_REPLAYABLE_FAULT_PARAMS *pParams 3244 ) 3245 { 3246 NV_STATUS status = NV_OK; 3247 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 3248 KernelGmmu *pKernelGmmu = GPU_GET_KERNEL_GMMU(pGpu); 3249 GMMU_FAULT_PACKET *pFaultPacket = (GMMU_FAULT_PACKET *)(NvUPtr)&pParams->faultPacket.data; 3250 3251 ct_assert(sizeof(GMMU_FAULT_PACKET) == NV2080_CTRL_GPU_FAULT_PACKET_SIZE); 3252 3253 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner()); 3254 3255 status = kgmmuHandleNonReplayableFaultPacket_HAL(pGpu, pKernelGmmu, pFaultPacket); 3256 3257 return status; 3258 } 3259 3260 NV_STATUS 3261 subdeviceCtrlCmdGpuGetChipDetails_IMPL 3262 ( 3263 Subdevice *pSubdevice, 3264 NV2080_CTRL_GPU_GET_CHIP_DETAILS_PARAMS *pParams 3265 ) 3266 { 3267 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 3268 3269 return gpuGetChipDetails(pGpu, pParams); 3270 } 3271 3272 /*! 3273 * @brief This Command is used to report if the specified logo illumination attribute 3274 * is supported 3275 * 3276 * @param[in,out] pConfigParams 3277 * attribute: The attribute whose support is to be determined. 3278 * bSupported: indicator if the specified attribute is supported. 3279 * 3280 * @return Returns NV_STATUS 3281 * NV_OK Success 3282 * 3283 */ 3284 NV_STATUS 3285 subdeviceCtrlCmdGpuQueryIllumSupport_VF 3286 ( 3287 Subdevice *pSubdevice, 3288 NV2080_CTRL_CMD_GPU_QUERY_ILLUM_SUPPORT_PARAMS *pConfigParams 3289 ) 3290 { 3291 pConfigParams->bSupported = NV_FALSE; 3292 3293 return NV_OK; 3294 } 3295