1 /* 2 * SPDX-FileCopyrightText: Copyright (c) 2021-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 #define NVOC_KERNEL_GRAPHICS_MANAGER_H_PRIVATE_ACCESS_ALLOWED 25 26 #include "kernel/gpu/gr/kernel_graphics_manager.h" 27 #include "kernel/gpu/gr/kernel_graphics.h" 28 29 #include "kernel/gpu/device/device.h" 30 #include "kernel/gpu/fifo/kernel_channel_group_api.h" 31 #include "kernel/gpu/fifo/kernel_channel_group.h" 32 33 #include "kernel/rmapi/client.h" 34 #include "kernel/rmapi/client_resource.h" 35 #include "nvRmReg.h" 36 37 // COMPUTE 38 #include "class/clb0c0.h" 39 #include "class/clb1c0.h" 40 #include "class/clc0c0.h" 41 #include "class/clc1c0.h" 42 #include "class/clc3c0.h" 43 #include "class/clc5c0.h" 44 #include "class/clc6c0.h" 45 #include "class/clc7c0.h" 46 #include "class/clc9c0.h" 47 #include "class/clcbc0.h" 48 // GFX 49 #include "class/clb097.h" 50 #include "class/clb197.h" 51 #include "class/clc097.h" 52 #include "class/clc197.h" 53 #include "class/clc397.h" 54 #include "class/clc597.h" 55 #include "class/clc697.h" 56 #include "class/clc797.h" 57 #include "class/clc997.h" 58 #include "class/clcb97.h" 59 // TWOD 60 #include "class/cl902d.h" 61 62 // MEM2MEM 63 #include "class/cla140.h" 64 65 static NvBool 66 _kgrmgrGPUInstanceHasComputeInstances 67 ( 68 OBJGPU *pGpu, 69 KernelGraphicsManager *pKernelGraphicsManager, 70 KERNEL_MIG_GPU_INSTANCE *pKernelMIGGpuInstance 71 ) 72 { 73 NV_ASSERT_OR_RETURN(pKernelMIGGpuInstance != NULL, NV_FALSE); 74 NvU32 computeInstanceIdx; 75 76 for (computeInstanceIdx = 0; 77 computeInstanceIdx < NV_ARRAY_ELEMENTS(pKernelMIGGpuInstance->MIGComputeInstance); 78 ++computeInstanceIdx) 79 { 80 if (pKernelMIGGpuInstance->MIGComputeInstance[computeInstanceIdx].bValid) 81 return NV_TRUE; 82 } 83 84 return NV_FALSE; 85 } 86 87 /*! 88 * @brief Get GR object type from the class number 89 * 90 * @param[IN] classNum external class number 91 * @param[OUT] pObjectType GR class subtype 92 */ 93 void 94 kgrmgrGetGrObjectType_IMPL 95 ( 96 NvU32 classNum, 97 NvU32 *pObjectType 98 ) 99 { 100 switch (classNum) 101 { 102 case MAXWELL_COMPUTE_A: 103 case MAXWELL_COMPUTE_B: 104 case PASCAL_COMPUTE_A: 105 case PASCAL_COMPUTE_B: 106 case VOLTA_COMPUTE_A: 107 case TURING_COMPUTE_A: 108 case AMPERE_COMPUTE_A: 109 case AMPERE_COMPUTE_B: 110 case ADA_COMPUTE_A: 111 case HOPPER_COMPUTE_A: 112 *pObjectType = GR_OBJECT_TYPE_COMPUTE; 113 break; 114 case MAXWELL_A: 115 case MAXWELL_B: 116 case PASCAL_A: 117 case PASCAL_B: 118 case VOLTA_A: 119 case TURING_A: 120 case AMPERE_A: 121 case AMPERE_B: 122 case ADA_A: 123 case HOPPER_A: 124 *pObjectType = GR_OBJECT_TYPE_3D; 125 break; 126 case FERMI_TWOD_A: 127 *pObjectType = GR_OBJECT_TYPE_2D; 128 break; 129 case KEPLER_INLINE_TO_MEMORY_B: 130 *pObjectType = GR_OBJECT_TYPE_MEM; 131 break; 132 default: 133 *pObjectType = GR_OBJECT_TYPE_INVALID; 134 break; 135 } 136 } 137 138 /*! 139 * @brief Is local ctx buffer supported 140 * 141 * @param[IN] bufId buffer Id 142 * @param[IN] bClassSupported2D Is 2D class supported 143 */ 144 NvBool 145 kgrmgrIsCtxBufSupported_IMPL 146 ( 147 GR_CTX_BUFFER bufId, 148 NvBool bClassSupported2D 149 ) 150 { 151 NvBool bSupported = NV_FALSE; 152 153 NV_ASSERT_OR_RETURN(NV_ENUM_IS(GR_CTX_BUFFER, bufId), NV_FALSE); 154 155 // All buffers are supported when 2D class is supported 156 if (bClassSupported2D) 157 { 158 return NV_TRUE; 159 } 160 161 switch (bufId) 162 { 163 case GR_CTX_BUFFER_ZCULL: 164 // fall-through 165 case GR_CTX_BUFFER_PREEMPT: 166 // fall-through 167 case GR_CTX_BUFFER_SPILL: 168 // fall-through 169 case GR_CTX_BUFFER_BETA_CB: 170 // fall-through 171 case GR_CTX_BUFFER_PAGEPOOL: 172 // fall-through 173 case GR_CTX_BUFFER_RTV_CB: 174 bSupported = NV_FALSE; 175 break; 176 177 case GR_CTX_BUFFER_PM: 178 // fall-through 179 case GR_CTX_BUFFER_MAIN: 180 // fall-through 181 case GR_CTX_BUFFER_PATCH: 182 bSupported = NV_TRUE; 183 break; 184 185 // No default case - compiler enforces update if enum changes 186 } 187 return bSupported; 188 } 189 190 /*! 191 * @brief Is globalctx buffer supported 192 * 193 * @param[IN] bufId buffer Id 194 * @param[IN] bClassSupported2D Is 2D class supported 195 */ 196 NvBool 197 kgrmgrIsGlobalCtxBufSupported_IMPL 198 ( 199 GR_GLOBALCTX_BUFFER bufId, 200 NvBool bClassSupported2D 201 ) 202 { 203 NvBool bSupported = NV_FALSE; 204 205 NV_ASSERT_OR_RETURN(NV_ENUM_IS(GR_GLOBALCTX_BUFFER, bufId), NV_FALSE); 206 207 // All buffers are supported when 2D class is supported 208 if (bClassSupported2D) 209 { 210 return NV_TRUE; 211 } 212 213 switch (bufId) 214 { 215 case GR_GLOBALCTX_BUFFER_BUNDLE_CB: 216 // fall-through 217 case GR_GLOBALCTX_BUFFER_PAGEPOOL: 218 // fall-through 219 case GR_GLOBALCTX_BUFFER_ATTRIBUTE_CB: 220 // fall-through 221 case GR_GLOBALCTX_BUFFER_RTV_CB: 222 // fall-through 223 case GR_GLOBALCTX_BUFFER_GFXP_POOL: 224 // fall-through 225 case GR_GLOBALCTX_BUFFER_GFXP_CTRL_BLK: 226 bSupported = NV_FALSE; 227 break; 228 229 case GR_GLOBALCTX_BUFFER_PRIV_ACCESS_MAP: 230 // fall-through 231 case GR_GLOBALCTX_BUFFER_UNRESTRICTED_PRIV_ACCESS_MAP: 232 // fall-through 233 case GR_GLOBALCTX_BUFFER_FECS_EVENT: 234 // fall-through 235 case GR_GLOBAL_BUFFER_GLOBAL_PRIV_ACCESS_MAP: 236 bSupported = NV_TRUE; 237 break; 238 239 // No default case - compiler enforces update if enum changes 240 } 241 242 return bSupported; 243 } 244 245 /*! 246 * @brief Sets swizzID and engineID on routing info if they don't already exist. 247 * 248 * @param[in] engID GR engine ID 249 * @param[in, out] pRouteInfo Client provided routing info 250 */ 251 void 252 kgrmgrCtrlSetEngineID_IMPL 253 ( 254 NvU32 engID, 255 NV2080_CTRL_GR_ROUTE_INFO *pRouteInfo 256 ) 257 { 258 if (NULL == pRouteInfo) 259 { 260 return; 261 } 262 else if (NV2080_CTRL_GR_ROUTE_INFO_FLAGS_TYPE_NONE == 263 DRF_VAL(2080_CTRL_GR, _ROUTE_INFO_FLAGS, _TYPE, pRouteInfo->flags)) 264 { 265 pRouteInfo->flags = DRF_DEF(2080_CTRL_GR, _ROUTE_INFO_FLAGS, _TYPE, _ENGID); 266 pRouteInfo->route = DRF_NUM64(2080_CTRL_GR, _ROUTE_INFO_DATA, _ENGID, engID); 267 } 268 } 269 270 /*! 271 * @brief Sets channel handle on routing info if it doesn't already exist. 272 * 273 * @param[in] hChannel Channel handle 274 * @param[in, out] pRouteInfo Client provided routing info 275 */ 276 void 277 kgrmgrCtrlSetChannelHandle_IMPL 278 ( 279 NvHandle hChannel, 280 NV2080_CTRL_GR_ROUTE_INFO *pRouteInfo 281 ) 282 { 283 if (NULL == pRouteInfo) 284 { 285 return; 286 } 287 else if (NV2080_CTRL_GR_ROUTE_INFO_FLAGS_TYPE_NONE == 288 DRF_VAL(2080_CTRL_GR, _ROUTE_INFO_FLAGS, _TYPE, pRouteInfo->flags)) 289 { 290 pRouteInfo->flags = DRF_DEF(2080_CTRL_GR, _ROUTE_INFO_FLAGS, _TYPE, _CHANNEL); 291 pRouteInfo->route = DRF_NUM64(2080_CTRL_GR, _ROUTE_INFO_DATA, _CHANNEL_HANDLE, hChannel); 292 } 293 } 294 295 static void 296 _kgrmgrInitRegistryOverrides 297 ( 298 OBJGPU *pGpu, 299 KernelGraphicsManager *pKernelGraphicsManager 300 ) 301 { 302 } 303 304 NV_STATUS 305 kgrmgrConstructEngine_IMPL 306 ( 307 OBJGPU *pGpu, 308 KernelGraphicsManager *pKernelGraphicsManager, 309 ENGDESCRIPTOR engDesc 310 ) 311 { 312 _kgrmgrInitRegistryOverrides(pGpu, pKernelGraphicsManager); 313 314 return NV_OK; 315 } 316 317 void 318 kgrmgrDestruct_IMPL 319 ( 320 KernelGraphicsManager *pKernelGraphicsManager 321 ) 322 { 323 portMemSet(&pKernelGraphicsManager->legacyKgraphicsStaticInfo.floorsweepingMasks, 0, 324 sizeof(pKernelGraphicsManager->legacyKgraphicsStaticInfo.floorsweepingMasks)); 325 portMemFree(pKernelGraphicsManager->legacyKgraphicsStaticInfo.pPpcMasks); 326 pKernelGraphicsManager->legacyKgraphicsStaticInfo.pPpcMasks = NULL; 327 portMemFree(pKernelGraphicsManager->legacyKgraphicsStaticInfo.pGrInfo); 328 pKernelGraphicsManager->legacyKgraphicsStaticInfo.pGrInfo = NULL; 329 pKernelGraphicsManager->legacyKgraphicsStaticInfo.bInitialized = NV_FALSE; 330 } 331 332 /*! 333 * @brief Set legacy Kgraphics Static Info (i.e. state of GR0) 334 */ 335 void 336 kgrmgrSetLegacyKgraphicsStaticInfo_IMPL 337 ( 338 OBJGPU *pGpu, 339 KernelGraphicsManager *pKernelGraphicsManager, 340 KernelGraphics *pKernelGraphics 341 ) 342 { 343 NV_CHECK_OR_RETURN_VOID(LEVEL_INFO, !pKernelGraphicsManager->legacyKgraphicsStaticInfo.bInitialized); 344 NV_ASSERT_OR_RETURN_VOID((pKernelGraphics != NULL) && (kgraphicsGetInstance(pGpu, pKernelGraphics) == 0)); 345 const KGRAPHICS_STATIC_INFO *pKernelGraphicsStaticInfo = kgraphicsGetStaticInfo(pGpu, pKernelGraphics); 346 NV_ASSERT_OR_RETURN_VOID(pKernelGraphicsStaticInfo != NULL); 347 348 portMemCopy(&pKernelGraphicsManager->legacyKgraphicsStaticInfo.floorsweepingMasks, sizeof(pKernelGraphicsStaticInfo->floorsweepingMasks), 349 &pKernelGraphicsStaticInfo->floorsweepingMasks, sizeof(pKernelGraphicsStaticInfo->floorsweepingMasks)); 350 351 if (pKernelGraphicsStaticInfo->pPpcMasks != NULL) 352 { 353 pKernelGraphicsManager->legacyKgraphicsStaticInfo.pPpcMasks = portMemAllocNonPaged(sizeof(*pKernelGraphicsStaticInfo->pPpcMasks)); 354 NV_ASSERT_OR_GOTO(pKernelGraphicsManager->legacyKgraphicsStaticInfo.pPpcMasks != NULL, cleanup); 355 356 portMemCopy(pKernelGraphicsManager->legacyKgraphicsStaticInfo.pPpcMasks, sizeof(*pKernelGraphicsStaticInfo->pPpcMasks), 357 pKernelGraphicsStaticInfo->pPpcMasks, sizeof(*pKernelGraphicsStaticInfo->pPpcMasks)); 358 } 359 360 if (pKernelGraphicsStaticInfo->pGrInfo != NULL) 361 { 362 pKernelGraphicsManager->legacyKgraphicsStaticInfo.pGrInfo = portMemAllocNonPaged(sizeof(*pKernelGraphicsStaticInfo->pGrInfo)); 363 NV_ASSERT_OR_GOTO(pKernelGraphicsManager->legacyKgraphicsStaticInfo.pGrInfo != NULL, cleanup); 364 365 portMemCopy(pKernelGraphicsManager->legacyKgraphicsStaticInfo.pGrInfo, sizeof(*pKernelGraphicsStaticInfo->pGrInfo), 366 pKernelGraphicsStaticInfo->pGrInfo, sizeof(*pKernelGraphicsStaticInfo->pGrInfo)); 367 } 368 369 pKernelGraphicsManager->legacyKgraphicsStaticInfo.bInitialized = NV_TRUE; 370 return; 371 372 cleanup: 373 portMemFree(pKernelGraphicsManager->legacyKgraphicsStaticInfo.pPpcMasks); 374 pKernelGraphicsManager->legacyKgraphicsStaticInfo.pPpcMasks = NULL; 375 portMemFree(pKernelGraphicsManager->legacyKgraphicsStaticInfo.pGrInfo); 376 pKernelGraphicsManager->legacyKgraphicsStaticInfo.pGrInfo = NULL; 377 } 378 379 /*! 380 * @brief Retrieves associated KernelGraphics engine for given device / route info 381 * 382 * @param[in] pGpu 383 * @param[in] pKernelGraphicsManager 384 * @param[in] pDevice 385 * @param[in] grRouteInfo Client-provided info to direct GR accesses 386 * @param[out] ppKernelGraphics (Optional) Ptr to store appropriate KernelGraphics *, if desired. 387 */ 388 NV_STATUS 389 kgrmgrCtrlRouteKGRWithDevice_IMPL 390 ( 391 OBJGPU *pGpu, 392 KernelGraphicsManager *pKernelGraphicsManager, 393 Device *pDevice, 394 const NV2080_CTRL_GR_ROUTE_INFO *pGrRouteInfo, 395 KernelGraphics **ppKernelGraphics 396 ) 397 { 398 MIG_INSTANCE_REF ref; 399 KernelGraphics *pKernelGraphics; 400 NvU32 type; 401 NV_STATUS status = NV_OK; 402 NvU32 grIdx; 403 NV2080_CTRL_GR_ROUTE_INFO grRouteInfo = *pGrRouteInfo; 404 KernelMIGManager *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu); 405 RsClient *pClient; 406 407 if (!IS_MIG_IN_USE(pGpu)) 408 { 409 grIdx = 0; 410 goto done; 411 } 412 413 pClient = RES_GET_CLIENT(pDevice); 414 415 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, 416 kmigmgrGetInstanceRefFromDevice(pGpu, pKernelMIGManager, pDevice, &ref)); 417 418 // 419 // Compute instances always have 1 GR engine, so automatically fill in 420 // the route info when subscribed to a compute instance 421 // 422 if (ref.pMIGComputeInstance != NULL) 423 { 424 portMemSet(&grRouteInfo, 0, sizeof(NV2080_CTRL_GR_ROUTE_INFO)); 425 kgrmgrCtrlSetEngineID(0, &grRouteInfo); 426 } 427 else 428 { 429 RmClient *pRmClient = dynamicCast(pClient, RmClient); 430 431 if (pRmClient == NULL) 432 return NV_ERR_INVALID_OBJECT_HANDLE; 433 434 RS_PRIV_LEVEL privLevel = rmclientGetCachedPrivilege(pRmClient); 435 if (!rmclientIsAdmin(pRmClient, privLevel) && 436 _kgrmgrGPUInstanceHasComputeInstances(pGpu, pKernelGraphicsManager, ref.pKernelMIGGpuInstance)) 437 { 438 return NV_ERR_INSUFFICIENT_PERMISSIONS; 439 } 440 } 441 442 type = DRF_VAL(2080_CTRL_GR, _ROUTE_INFO_FLAGS, _TYPE, grRouteInfo.flags); 443 switch (type) 444 { 445 case NV2080_CTRL_GR_ROUTE_INFO_FLAGS_TYPE_NONE: 446 NV_PRINTF(LEVEL_ERROR, 447 "Cannot give GR Route flag of TYPE_NONE with MIG enabled!\n"); 448 return NV_ERR_INVALID_ARGUMENT; 449 450 case NV2080_CTRL_GR_ROUTE_INFO_FLAGS_TYPE_ENGID: 451 { 452 NvU32 localGrIdx = DRF_VAL64(2080_CTRL_GR, _ROUTE_INFO_DATA, 453 _ENGID, grRouteInfo.route); 454 RM_ENGINE_TYPE globalRmEngType; 455 456 NV_CHECK_OK_OR_RETURN( 457 LEVEL_ERROR, 458 kmigmgrGetLocalToGlobalEngineType(pGpu, pKernelMIGManager, ref, 459 RM_ENGINE_TYPE_GR(localGrIdx), 460 &globalRmEngType)); 461 NV_ASSERT_OR_RETURN(RM_ENGINE_TYPE_IS_GR(globalRmEngType), NV_ERR_INVALID_STATE); 462 grIdx = RM_ENGINE_TYPE_GR_IDX(globalRmEngType); 463 464 break; 465 } 466 467 case NV2080_CTRL_GR_ROUTE_INFO_FLAGS_TYPE_CHANNEL: 468 { 469 KernelChannel *pKernelChannel; 470 RM_ENGINE_TYPE rmEngineType; 471 NvHandle hChannel = DRF_VAL64(2080_CTRL_GR, _ROUTE_INFO_DATA, 472 _CHANNEL_HANDLE, grRouteInfo.route); 473 474 status = CliGetKernelChannel(pClient, hChannel, &pKernelChannel); 475 if (status != NV_OK) 476 { 477 RsResourceRef *pChanGrpRef; 478 KernelChannelGroupApi *pKernelChannelGroupApi = NULL; 479 KernelChannelGroup *pKernelChannelGroup = NULL; 480 481 // 482 // If retrieving a channel with the given hChannel doesn't work, 483 // try interpreting it as a handle to a channel group instead. 484 // 485 status = CliGetChannelGroup(pClient->hClient, hChannel, 486 &pChanGrpRef, NULL); 487 if (NV_OK != status) 488 { 489 NV_PRINTF(LEVEL_ERROR, 490 "Failed to find a channel or TSG with given handle 0x%08x associated with hClient=0x%08x\n", 491 hChannel, pClient->hClient); 492 return NV_ERR_INVALID_ARGUMENT; 493 } 494 495 pKernelChannelGroupApi = dynamicCast(pChanGrpRef->pResource, 496 KernelChannelGroupApi); 497 NV_ASSERT_OR_RETURN( 498 (pKernelChannelGroupApi != NULL && 499 pKernelChannelGroupApi->pKernelChannelGroup != NULL), 500 NV_ERR_INVALID_STATE); 501 pKernelChannelGroup = 502 pKernelChannelGroupApi->pKernelChannelGroup; 503 504 NV_PRINTF(LEVEL_INFO, 505 "Found TSG with given handle 0x%08x, using this to determine GR engine ID\n", 506 hChannel); 507 rmEngineType = pKernelChannelGroup->engineType; 508 } 509 else 510 { 511 NV_PRINTF(LEVEL_INFO, 512 "Found channel with given handle 0x%08x, using this to determine GR engine ID\n", 513 hChannel); 514 rmEngineType = kchannelGetEngineType(pKernelChannel); 515 } 516 517 if (!RM_ENGINE_TYPE_IS_GR(rmEngineType)) 518 { 519 NV_PRINTF(LEVEL_ERROR, 520 "Failed to route GR using non-GR engine type 0x%x (0x%x)\n", 521 gpuGetNv2080EngineType(rmEngineType), rmEngineType); 522 return NV_ERR_INVALID_ARGUMENT; 523 } 524 525 grIdx = RM_ENGINE_TYPE_GR_IDX(rmEngineType); 526 break; 527 } 528 default: 529 NV_PRINTF(LEVEL_ERROR, 530 "Unrecognized GR Route flag type 0x%x!\n", type); 531 return NV_ERR_INVALID_ARGUMENT; 532 } 533 534 done: 535 pKernelGraphics = GPU_GET_KERNEL_GRAPHICS(pGpu, grIdx); 536 NV_ASSERT_OR_RETURN(pKernelGraphics != NULL, NV_ERR_INVALID_STATE); 537 538 if (ppKernelGraphics != NULL) 539 *ppKernelGraphics = pKernelGraphics; 540 541 return status; 542 } 543 544 /*! 545 * @return legacy GPC mask enumerated by this chip 546 */ 547 NvU32 548 kgrmgrGetLegacyGpcMask_IMPL 549 ( 550 OBJGPU *pGpu, 551 KernelGraphicsManager *pKernelGraphicsManager 552 ) 553 { 554 NV_ASSERT_OR_RETURN(pKernelGraphicsManager->legacyKgraphicsStaticInfo.bInitialized, 0); 555 556 return pKernelGraphicsManager->legacyKgraphicsStaticInfo.floorsweepingMasks.gpcMask; 557 } 558 559 /*! 560 * @return legacy physical GFX GPC mask enumerated by this chip 561 */ 562 NvU32 563 kgrmgrGetLegacyPhysGfxGpcMask_IMPL 564 ( 565 OBJGPU *pGpu, 566 KernelGraphicsManager *pKernelGraphicsManager 567 ) 568 { 569 NV_ASSERT_OR_RETURN(pKernelGraphicsManager->legacyKgraphicsStaticInfo.bInitialized, 0); 570 571 return pKernelGraphicsManager->legacyKgraphicsStaticInfo.floorsweepingMasks.physGfxGpcMask; 572 } 573 574 /*! 575 * @return legacy TPC mask for certain GPC 576 * 577 * @param[in] pGpu 578 * @param[in] KernelGraphicsManager 579 * @param[in] gpcId Indicates logical GPC ID when MIG enabled or physical 580 * GPC ID when MIG disabled 581 */ 582 NvU32 583 kgrmgrGetLegacyTpcMask_IMPL 584 ( 585 OBJGPU *pGpu, 586 KernelGraphicsManager *pKernelGraphicsManager, 587 NvU32 gpcId 588 ) 589 { 590 NvU32 maxNumGpcs; 591 592 NV_ASSERT_OR_RETURN(pKernelGraphicsManager->legacyKgraphicsStaticInfo.bInitialized, 0); 593 NV_ASSERT_OR_RETURN(pKernelGraphicsManager->legacyKgraphicsStaticInfo.pGrInfo != NULL, 0); 594 595 maxNumGpcs = pKernelGraphicsManager->legacyKgraphicsStaticInfo.pGrInfo->infoList[NV2080_CTRL_GR_INFO_INDEX_LITTER_NUM_GPCS].data; 596 NV_CHECK_OR_RETURN(LEVEL_ERROR, (gpcId < maxNumGpcs), 0); 597 598 return pKernelGraphicsManager->legacyKgraphicsStaticInfo.floorsweepingMasks.tpcMask[gpcId]; 599 } 600 601 /*! 602 * @brief Get legacy PPC mask for certain GPC 603 */ 604 NV_STATUS 605 kgrmgrGetLegacyPpcMask_IMPL 606 ( 607 OBJGPU *pGpu, 608 KernelGraphicsManager *pKernelGraphicsManager, 609 NvU32 physGpcId, 610 NvU32 *pPpcMask 611 ) 612 { 613 NvU32 maxNumGpcs; 614 615 NV_ASSERT_OR_RETURN(pKernelGraphicsManager->legacyKgraphicsStaticInfo.bInitialized, NV_ERR_INVALID_STATE); 616 NV_ASSERT_OR_RETURN(pKernelGraphicsManager->legacyKgraphicsStaticInfo.pGrInfo != NULL, NV_ERR_INVALID_STATE); 617 maxNumGpcs = pKernelGraphicsManager->legacyKgraphicsStaticInfo.pGrInfo->infoList[NV2080_CTRL_GR_INFO_INDEX_LITTER_NUM_GPCS].data; 618 NV_CHECK_OR_RETURN(LEVEL_ERROR, (physGpcId < maxNumGpcs), NV_ERR_INVALID_ARGUMENT); 619 NV_ASSERT_OR_RETURN((pPpcMask != NULL), NV_ERR_INVALID_ARGUMENT); 620 NV_ASSERT_OR_RETURN((pKernelGraphicsManager->legacyKgraphicsStaticInfo.pPpcMasks != NULL), NV_ERR_NOT_SUPPORTED); 621 622 *pPpcMask = pKernelGraphicsManager->legacyKgraphicsStaticInfo.pPpcMasks->mask[physGpcId]; 623 624 return NV_OK; 625 } 626 627 /*! 628 * @brief Returns legacy zcull mask for specific gpc 629 */ 630 NvU32 631 kgrmgrGetLegacyZcullMask_IMPL 632 ( 633 OBJGPU *pGpu, 634 KernelGraphicsManager *pKernelGraphicsManager, 635 NvU32 physGpcId 636 ) 637 { 638 NvU32 maxNumGpcs; 639 640 NV_ASSERT_OR_RETURN(pKernelGraphicsManager->legacyKgraphicsStaticInfo.bInitialized, 0); 641 NV_ASSERT_OR_RETURN(pKernelGraphicsManager->legacyKgraphicsStaticInfo.pGrInfo != NULL, NV_ERR_INVALID_STATE); 642 maxNumGpcs = pKernelGraphicsManager->legacyKgraphicsStaticInfo.pGrInfo->infoList[NV2080_CTRL_GR_INFO_INDEX_LITTER_NUM_GPCS].data; 643 NV_CHECK_OR_RETURN(LEVEL_ERROR, (physGpcId < maxNumGpcs), NV_ERR_INVALID_ARGUMENT); 644 645 return pKernelGraphicsManager->legacyKgraphicsStaticInfo.floorsweepingMasks.zcullMask[physGpcId]; 646 } 647 648 /*! 649 * @brief Function to Alloc VEIDs for a GR engine 650 * 651 * @param[IN] pGpu 652 * @param[IN] pKernelGraphicsManager 653 * @param[IN] grIdx phys gr idx 654 * @param[IN] veidSpanOffset Offset of spans localized to a GPU instance to make the VEID request from 655 * @param[IN] veidCount Total VEIDs connected to this GR engine 656 * @param[IN] pKernelMIGGPUInstance 657 */ 658 NV_STATUS 659 kgrmgrAllocVeidsForGrIdx_IMPL 660 ( 661 OBJGPU *pGpu, 662 KernelGraphicsManager *pKernelGraphicsManager, 663 NvU32 grIdx, 664 NvU32 veidSpanOffset, 665 NvU32 veidCount, 666 KERNEL_MIG_GPU_INSTANCE *pKernelMIGGPUInstance 667 ) 668 { 669 NvU32 veidStepSize; 670 NvU32 veidStart = 0; 671 NvU32 veidEnd = 0; 672 NvU32 GPUInstanceVeidEnd; 673 NvU64 GPUInstanceVeidMask; 674 NvU64 GPUInstanceFreeVeidMask; 675 NvU64 reqVeidMask; 676 677 // This GR should not be already configured to use any VEIDs 678 NV_ASSERT_OR_RETURN(pKernelGraphicsManager->grIdxVeidMask[grIdx] == 0, NV_ERR_INVALID_STATE); 679 680 NV_ASSERT_OK_OR_RETURN( 681 kgrmgrGetVeidStepSize(pGpu, pKernelGraphicsManager, &veidStepSize)); 682 683 // We statically assign VEIDs to a GR based on the number of GPCs connected to it 684 if (veidCount % veidStepSize != 0) 685 { 686 NV_PRINTF(LEVEL_ERROR, "veidCount %d is not aligned to veidStepSize=%d\n", veidCount, veidStepSize); 687 return NV_ERR_INVALID_ARGUMENT; 688 } 689 690 NV_ASSERT_OR_RETURN(veidSpanOffset != KMIGMGR_SPAN_OFFSET_INVALID, NV_ERR_INVALID_ARGUMENT); 691 692 veidStart = (veidSpanOffset * veidStepSize) + pKernelMIGGPUInstance->resourceAllocation.veidOffset; 693 veidEnd = veidStart + veidCount - 1; 694 695 NV_ASSERT_OR_RETURN(veidStart < veidEnd, NV_ERR_INVALID_STATE); 696 NV_ASSERT_OR_RETURN(veidStart < 64, NV_ERR_INVALID_ARGUMENT); 697 NV_ASSERT_OR_RETURN(veidEnd < 64, NV_ERR_INVALID_ARGUMENT); 698 699 reqVeidMask = DRF_SHIFTMASK64(veidEnd:veidStart); 700 701 NV_ASSERT_OR_RETURN(reqVeidMask != 0x0, NV_ERR_INVALID_STATE); 702 703 // Create a mask for VEIDs associated with this GPU instance 704 GPUInstanceVeidEnd = pKernelMIGGPUInstance->resourceAllocation.veidOffset + pKernelMIGGPUInstance->resourceAllocation.veidCount - 1; 705 GPUInstanceVeidMask = DRF_SHIFTMASK64(GPUInstanceVeidEnd:pKernelMIGGPUInstance->resourceAllocation.veidOffset); 706 707 NV_ASSERT_OR_RETURN(GPUInstanceVeidMask != 0x0, NV_ERR_INVALID_STATE); 708 709 GPUInstanceFreeVeidMask = ~(pKernelGraphicsManager->veidInUseMask) & GPUInstanceVeidMask; 710 711 // VEID range should not overlap with existing VEIDs in use 712 NV_ASSERT_OR_RETURN((pKernelGraphicsManager->veidInUseMask & reqVeidMask) == 0, NV_ERR_STATE_IN_USE); 713 714 // 715 // For swizzId 0, client can use any range of VEIDs if not used, so we don't 716 // need to do the range check 717 // 718 NV_ASSERT_OR_RETURN(((pKernelMIGGPUInstance->swizzId == 0) || 719 ((GPUInstanceFreeVeidMask & reqVeidMask) == reqVeidMask)), 720 NV_ERR_INSUFFICIENT_RESOURCES); 721 722 // mark each VEID in the range as "in use" 723 pKernelGraphicsManager->veidInUseMask |= reqVeidMask; 724 pKernelGraphicsManager->grIdxVeidMask[grIdx] |= reqVeidMask; 725 726 return NV_OK; 727 } 728 729 /*! 730 * @brief Function to Clear Gr Engine to VEIDs mapping 731 */ 732 void 733 kgrmgrClearVeidsForGrIdx_IMPL 734 ( 735 OBJGPU *pGpu, 736 KernelGraphicsManager *pKernelGraphicsManager, 737 NvU32 grIdx 738 ) 739 { 740 NvU64 veidMask = pKernelGraphicsManager->grIdxVeidMask[grIdx]; 741 742 // mark all VEIDs of this GR engine as "not in use" 743 NV_ASSERT((pKernelGraphicsManager->veidInUseMask & veidMask) == veidMask); 744 pKernelGraphicsManager->veidInUseMask &= ~veidMask; 745 pKernelGraphicsManager->grIdxVeidMask[grIdx] = 0; 746 } 747 748 /*! 749 * @brief Get VEID step size 750 */ 751 NV_STATUS 752 kgrmgrGetVeidStepSize_IMPL 753 ( 754 OBJGPU *pGpu, 755 KernelGraphicsManager *pKernelGraphicsManager, 756 NvU32 *pVeidStepSize 757 ) 758 { 759 NV_ASSERT_OR_RETURN(pVeidStepSize != NULL, NV_ERR_INVALID_ARGUMENT); 760 NV_ASSERT_OR_RETURN(pKernelGraphicsManager->legacyKgraphicsStaticInfo.bInitialized, NV_ERR_INVALID_STATE); 761 NV_ASSERT_OR_RETURN(pKernelGraphicsManager->legacyKgraphicsStaticInfo.pGrInfo != NULL, NV_ERR_INVALID_STATE); 762 763 *pVeidStepSize = pKernelGraphicsManager->legacyKgraphicsStaticInfo.pGrInfo->infoList[NV0080_CTRL_GR_INFO_INDEX_LITTER_MIN_SUBCTX_PER_SMC_ENG].data; 764 765 return NV_OK; 766 } 767 768 /*! 769 * @brief Function to get starting VEID for a Gr Engine 770 */ 771 NV_STATUS 772 kgrmgrGetVeidBaseForGrIdx_IMPL 773 ( 774 OBJGPU *pGpu, 775 KernelGraphicsManager *pKernelGraphicsManager, 776 NvU32 grIdx, 777 NvU32 *pVeidStart 778 ) 779 { 780 NvU64 veidMask; 781 NV_ASSERT_OR_RETURN(pVeidStart != NULL, NV_ERR_INVALID_ARGUMENT); 782 NV_ASSERT_OR_RETURN(grIdx != KGRMGR_MAX_GR, NV_ERR_INVALID_ARGUMENT); 783 784 *pVeidStart = 0; 785 786 veidMask = pKernelGraphicsManager->grIdxVeidMask[grIdx]; 787 788 // 789 // If a GR is not configured, VEID mask for it will be "0" and counting 790 // "0" in a zero-based mask will result in max bit-width size. 791 // 792 if (veidMask != 0x0) 793 *pVeidStart = portUtilCountTrailingZeros64(veidMask); 794 795 return NV_OK; 796 } 797 798 /*! 799 * @brief Function to get GR index for a VEID 800 */ 801 NV_STATUS 802 kgrmgrGetGrIdxForVeid_IMPL 803 ( 804 OBJGPU *pGpu, 805 KernelGraphicsManager *pKernelGraphicsManager, 806 NvU32 veid, 807 NvU32 *pGrIdx 808 ) 809 { 810 NvU32 i; 811 NvU64 veidMask = NVBIT64(veid); 812 813 NV_ASSERT_OR_RETURN(pGrIdx != NULL, NV_ERR_INVALID_ARGUMENT); 814 for (i = 0; i < KGRMGR_MAX_GR; ++i) 815 { 816 if ((pKernelGraphicsManager->grIdxVeidMask[i] & veidMask) != 0) 817 break; 818 } 819 NV_ASSERT_OR_RETURN(i != KGRMGR_MAX_GR, NV_ERR_OBJECT_NOT_FOUND); 820 *pGrIdx = i; 821 return NV_OK; 822 } 823 824 /*! 825 * @brief discovers maximum size of local ctx buffers. 826 */ 827 NV_STATUS 828 kgrmgrDiscoverMaxLocalCtxBufInfo_IMPL 829 ( 830 OBJGPU *pGpu, 831 KernelGraphicsManager *pKernelGraphicsManager, 832 KernelGraphics *pKernelGraphics, 833 NvU32 swizzId 834 ) 835 { 836 KernelMIGManager *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu); 837 838 // 839 // Most of GR is stub'd so context related things are not needed in AMODEL. 840 // But this function can be called in some MODS test, so return OK directly 841 // to avoid failing the test. 842 // 843 if (IS_MODS_AMODEL(pGpu)) 844 return NV_OK; 845 846 NV_CHECK_OR_RETURN(LEVEL_SILENT, 847 kmigmgrIsMemoryPartitioningNeeded_HAL(pGpu, pKernelMIGManager, swizzId), NV_OK); 848 849 return kgraphicsDiscoverMaxLocalCtxBufferSize(pGpu, pKernelGraphics); 850 } 851 852 /*! 853 * @brief Get ctxbufpool info for the global ctx buffer 854 */ 855 const CTX_BUF_INFO * 856 kgrmgrGetGlobalCtxBufInfo_IMPL 857 ( 858 OBJGPU *pGpu, 859 KernelGraphicsManager *pKernelGraphicsManager, 860 GR_GLOBALCTX_BUFFER buf 861 ) 862 { 863 NV_ASSERT_OR_RETURN(NV_ENUM_IS(GR_GLOBALCTX_BUFFER, buf), NULL); 864 return &pKernelGraphicsManager->globalCtxBufInfo[buf]; 865 } 866 867 /*! 868 * @brief Set ctxbufpool parameters for the global ctx buffer 869 */ 870 void 871 kgrmgrSetGlobalCtxBufInfo_IMPL 872 ( 873 OBJGPU *pGpu, 874 KernelGraphicsManager *pKernelGraphicsManager, 875 GR_GLOBALCTX_BUFFER buf, 876 NvU64 size, 877 NvU64 align, 878 RM_ATTR_PAGE_SIZE attr, 879 NvBool bContiguous 880 ) 881 { 882 CTX_BUF_INFO *pInfo; 883 NV_ASSERT_OR_RETURN_VOID(NV_ENUM_IS(GR_GLOBALCTX_BUFFER, buf)); 884 885 pInfo = &pKernelGraphicsManager->globalCtxBufInfo[buf]; 886 pInfo->size = size; 887 pInfo->align = align; 888 pInfo->attr = attr; 889 pInfo->bContig = bContiguous; 890 } 891 892 /*! 893 * @brief Gets maximum size of GR global ctx buffers. 894 * These are sizes of buffer for GR0 in legacy mode with all GPCs 895 * connected to GR0. 896 */ 897 NV_STATUS 898 kgrmgrDiscoverMaxGlobalCtxBufSizes_IMPL 899 ( 900 OBJGPU *pGpu, 901 KernelGraphicsManager *pKernelGraphicsManager, 902 KernelGraphics *pKernelGraphics, 903 NvBool bMemoryPartitioningNeeded 904 ) 905 { 906 const KGRAPHICS_STATIC_INFO *pKernelGraphicsStaticInfo; 907 GR_GLOBALCTX_BUFFER bufId; 908 909 // 910 // Most of GR is stub'd so context related things are not needed in AMODEL. 911 // But this function can be called in some MODS test, so return OK directly 912 // to avoid failing the test. 913 // 914 if (IS_MODS_AMODEL(pGpu)) 915 return NV_OK; 916 917 NV_ASSERT_OR_RETURN(!IS_MIG_IN_USE(pGpu), NV_ERR_INVALID_STATE); 918 919 // 920 // Bug 2915422: Eventually we expect this check to be replaced by ctxBufPoolIsSupported 921 // we can't use that check today because PDB_PROP_GPU_MOVE_CTX_BUFFERS_TO_PMA is not enabled 922 // when this function is called because 923 // kgraphicsInitializeDeferredStaticData below will eventually lead to 924 // global ctx buffer allocation from ctxBufPools even before these pools are 925 // populated which happens later during GPU instance creation. Once we are 926 // able to rip out global buffer alloc from 927 // kgraphicsInitializeDeferredStaticData, we can enable the above property 928 // early. 929 // 930 NV_CHECK_OR_RETURN(LEVEL_SILENT, bMemoryPartitioningNeeded, NV_OK); 931 932 // Make sure sizes of all buffers are setup 933 NV_ASSERT_OK_OR_RETURN( 934 kgraphicsInitializeDeferredStaticData(pGpu, pKernelGraphics, NV01_NULL_OBJECT, NV01_NULL_OBJECT)); 935 936 pKernelGraphicsStaticInfo = kgraphicsGetStaticInfo(pGpu, pKernelGraphics); 937 NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo != NULL, NV_ERR_INVALID_STATE); 938 NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo->pContextBuffersInfo != NULL, NV_ERR_INVALID_STATE); 939 940 // Get sizes of global ctx buffers 941 FOR_EACH_IN_ENUM(GR_GLOBALCTX_BUFFER, bufId) 942 { 943 NvU32 fifoEngineId; 944 NV_ASSERT_OK_OR_RETURN( 945 kgrctxGlobalCtxBufferToFifoEngineId(bufId, &fifoEngineId)); 946 947 // 948 // contiguity is determined later before reservation as it depends on settings 949 // that take effect after this point. 950 // 951 kgrmgrSetGlobalCtxBufInfo(pGpu, pKernelGraphicsManager, bufId, 952 pKernelGraphicsStaticInfo->pContextBuffersInfo->engine[fifoEngineId].size, 953 pKernelGraphicsStaticInfo->pContextBuffersInfo->engine[fifoEngineId].alignment, 954 RM_ATTR_PAGE_SIZE_4KB, NV_FALSE); 955 } 956 FOR_EACH_IN_ENUM_END; 957 958 return NV_OK; 959 } 960 961 /*! 962 * @return legacy TPC count for certain GPC 963 * 964 * @param[in] pGpu 965 * @param[in] KernelGraphicsManager 966 * @param[in] gpcId Indicates logical GPC ID 967 */ 968 NvU32 969 kgrmgrGetLegacyGpcTpcCount_IMPL 970 ( 971 OBJGPU *pGpu, 972 KernelGraphicsManager *pKernelGraphicsManager, 973 NvU32 gpcId 974 ) 975 { 976 NvU32 maxNumGpcs; 977 978 NV_ASSERT_OR_RETURN(pKernelGraphicsManager->legacyKgraphicsStaticInfo.bInitialized, 0); 979 NV_ASSERT_OR_RETURN(pKernelGraphicsManager->legacyKgraphicsStaticInfo.pGrInfo != NULL, 0); 980 981 maxNumGpcs = nvPopCount32(pKernelGraphicsManager->legacyKgraphicsStaticInfo.floorsweepingMasks.gpcMask); 982 NV_CHECK_OR_RETURN(LEVEL_ERROR, (gpcId < maxNumGpcs), 0); 983 984 return pKernelGraphicsManager->legacyKgraphicsStaticInfo.floorsweepingMasks.tpcCount[gpcId]; 985 } 986 987 /*! 988 * @brief Function to Alloc VEIDs with either a specific placement or first-fit placement 989 * depending upon the value passed into pSpanStart 990 * 991 * @param[IN] pGpu 992 * @param[IN] pKernelGraphicsManager 993 * @param[IN/OUT] pInUseMask Mask of VEIDs in-use, updated with newly set VEIDs 994 * @param[IN] veidCount Total VEIDs connected to this GR engine 995 * @param[IN/OUT] pSpanStart GPU Instance local span offset to begin assigning VEIDs from 996 * @param[IN] pKernelMIGGPUInstance 997 */ 998 NV_STATUS 999 kgrmgrCheckVeidsRequest_IMPL 1000 ( 1001 OBJGPU *pGpu, 1002 KernelGraphicsManager *pKernelGraphicsManager, 1003 NvU64 *pInUseMask, 1004 NvU32 veidCount, 1005 NvU32 *pSpanStart, 1006 KERNEL_MIG_GPU_INSTANCE *pKernelMIGGPUInstance 1007 ) 1008 { 1009 NvU32 veidStepSize; 1010 NvU32 veidStart = 0; 1011 NvU32 veidEnd = 0; 1012 NvU32 GPUInstanceVeidEnd; 1013 NvU64 GPUInstanceVeidMask; 1014 NvU64 GPUInstanceFreeVeidMask; 1015 NvU64 veidMask; 1016 1017 NV_ASSERT_OK_OR_RETURN( 1018 kgrmgrGetVeidStepSize(pGpu, pKernelGraphicsManager, &veidStepSize)); 1019 1020 NV_ASSERT_OR_RETURN(pSpanStart != NULL, NV_ERR_INVALID_ARGUMENT); 1021 NV_ASSERT_OR_RETURN(pInUseMask != NULL, NV_ERR_INVALID_ARGUMENT); 1022 1023 // We statically assign VEIDs to a GR based on the number of GPCs connected to it 1024 if (veidCount % veidStepSize != 0) 1025 { 1026 NV_PRINTF(LEVEL_ERROR, "veidCount %d is not aligned to veidStepSize=%d\n", veidCount, veidStepSize); 1027 return NV_ERR_INVALID_ARGUMENT; 1028 } 1029 1030 // Create a mask for VEIDs associated with this GPU instance 1031 GPUInstanceVeidEnd = pKernelMIGGPUInstance->resourceAllocation.veidOffset + pKernelMIGGPUInstance->resourceAllocation.veidCount - 1; 1032 GPUInstanceVeidMask = DRF_SHIFTMASK64(GPUInstanceVeidEnd:pKernelMIGGPUInstance->resourceAllocation.veidOffset); 1033 1034 NV_ASSERT_OR_RETURN(GPUInstanceVeidMask != 0x0, NV_ERR_INVALID_STATE); 1035 1036 GPUInstanceFreeVeidMask = ~(*pInUseMask) & GPUInstanceVeidMask; 1037 1038 if (*pSpanStart != KMIGMGR_SPAN_OFFSET_INVALID) 1039 { 1040 veidStart = (*pSpanStart * veidStepSize) + pKernelMIGGPUInstance->resourceAllocation.veidOffset; 1041 veidEnd = veidStart + veidCount - 1; 1042 1043 NV_ASSERT_OR_RETURN(veidStart < veidEnd, NV_ERR_INVALID_STATE); 1044 NV_ASSERT_OR_RETURN(veidStart < 64, NV_ERR_INVALID_ARGUMENT); 1045 NV_ASSERT_OR_RETURN(veidEnd < 64, NV_ERR_INVALID_ARGUMENT); 1046 } 1047 else 1048 { 1049 NvU64 reqVeidMask = DRF_SHIFTMASK64(veidCount - 1:0); 1050 NvU32 i; 1051 1052 for (i = pKernelMIGGPUInstance->resourceAllocation.veidOffset; i <= GPUInstanceVeidEnd; i += veidStepSize) 1053 { 1054 // See if requested slots are available within this range 1055 if (((GPUInstanceFreeVeidMask >> i) & reqVeidMask) == reqVeidMask) 1056 { 1057 veidStart = i; 1058 veidEnd = veidStart + veidCount - 1; 1059 break; 1060 } 1061 } 1062 1063 NV_CHECK_OR_RETURN(LEVEL_SILENT, i <= GPUInstanceVeidEnd, 1064 NV_ERR_INSUFFICIENT_RESOURCES); 1065 } 1066 1067 veidMask = DRF_SHIFTMASK64(veidEnd:veidStart); 1068 NV_ASSERT_OR_RETURN(veidMask != 0x0, NV_ERR_INVALID_STATE); 1069 1070 // 1071 // For swizzId 0, client can use any range of VEIDs if not used, so we don't 1072 // need to do the range check 1073 // 1074 NV_CHECK_OR_RETURN(LEVEL_ERROR, 1075 ((pKernelMIGGPUInstance->swizzId == 0) || 1076 (GPUInstanceVeidMask & veidMask) == veidMask), 1077 NV_ERR_INSUFFICIENT_RESOURCES); 1078 1079 // VEID range should not overlap with existing VEIDs in use 1080 NV_ASSERT_OR_RETURN((*pInUseMask & veidMask) == 0, NV_ERR_STATE_IN_USE); 1081 1082 NV_ASSERT(veidStart >= pKernelMIGGPUInstance->resourceAllocation.veidOffset); 1083 1084 *pSpanStart = (veidStart - pKernelMIGGPUInstance->resourceAllocation.veidOffset) / veidStepSize; 1085 *pInUseMask |= veidMask; 1086 return NV_OK; 1087 } 1088 1089 /*! 1090 * @brief Atomically set fecs callback scheduled, return NV_TRUE if wasn't scheduled 1091 */ 1092 NvBool 1093 kgrmgrSignalFecsCallbackScheduled_IMPL 1094 ( 1095 OBJGPU *pGpu, 1096 KernelGraphicsManager *pKernelGraphicsManager 1097 ) 1098 { 1099 return portAtomicCompareAndSwapU32(&pKernelGraphicsManager->fecsCallbackScheduled, 1, 0); 1100 } 1101 1102 /*! 1103 * @brief Atomically clear fecs callback scheduled 1104 */ 1105 void 1106 kgrmgrClearFecsCallbackScheduled_IMPL 1107 ( 1108 OBJGPU *pGpu, 1109 KernelGraphicsManager *pKernelGraphicsManager 1110 ) 1111 { 1112 portAtomicSetU32(&pKernelGraphicsManager->fecsCallbackScheduled, 0); 1113 } 1114