1 /* 2 * SPDX-FileCopyrightText: Copyright (c) 2015-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 * SPDX-License-Identifier: MIT 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24 /*! 25 * @file 26 * @brief Implementation of the Sync Gpu Boost Manager methods. 27 */ 28 29 /*------------------------------Includes--------------------------------------*/ 30 #include "power/gpu_boost_mgr.h" 31 #include "os/os.h" 32 #include "core/locks.h" 33 #include "gpu/gpu_access.h" 34 #include "gpu/gpu.h" 35 #include "syncgpuboost.h" 36 #include "nvlimits.h" 37 #include "gpu_mgr/gpu_mgr.h" 38 #include "gpu/gsp/gsp_static_config.h" 39 #include "vgpu/vgpu_events.h" 40 #include "gpu/perf/kern_perf_gpuboostsync.h" 41 #include "nvdevid.h" 42 43 /*-----------------------Static Private Method Prototypes---------------------*/ 44 static NV_STATUS _gpuboostmgrApplyPolicyFilters(NV0000_SYNC_GPU_BOOST_GROUP_CONFIG *); 45 46 /*----------------------------Object Methods----------------------------------*/ 47 48 /*! 49 * @brief OBJGPUBOOSTMGR object method to create a Sync Gpu Boost Group (SGBG) 50 * 51 * This method will create a new SGBG if none of the GPUs specified in the input 52 * params is already a part of another SGBG. 53 * 54 * @param [in] pBoostConfig @ref NV0000_SYNC_GPU_BOOST_GROUP_CONFIG 55 * @param [out] pBoostConfig::boostGroupId If SGBG creation succeeds, this field 56 * has the assigned group ID. This ID is 57 * unique across RM. 58 * @returns NV_OK Success 59 * @returns NV_ERR_INSUFFICIENT_RESOURCES No new groups possible. 60 * @returns NV_ERR_INVALID_STATE Internal state messed up. 61 * and a few more returned from second level functions. 62 */ 63 NV_STATUS 64 gpuboostmgrCreateGroup_IMPL 65 ( 66 OBJGPUBOOSTMGR *pBoostMgr, 67 NV0000_SYNC_GPU_BOOST_GROUP_CONFIG *pBoostConfig 68 ) 69 { 70 NV_STATUS status = NV_OK; 71 NODE *pGpuIdNode = NULL; 72 NvBool bCleanup = NV_FALSE; 73 NvU32 i; 74 75 // See if we can accomodate one more SGBG 76 NV_ASSERT_OR_RETURN(pBoostMgr->groupCount < NV0000_SYNC_GPU_BOOST_MAX_GROUPS, 77 NV_ERR_INSUFFICIENT_RESOURCES); 78 79 // Check if requested config is valid. 80 status = gpuboostmgrCheckConfig(pBoostMgr, pBoostConfig); 81 if (NV_OK != status) 82 { 83 NV_PRINTF(LEVEL_ERROR, 84 "Invalid Boost Config. Failing Boost Group creation.\n"); 85 NV_ASSERT_OR_GOTO(NV_OK == status, gpuboostmgrCreateGroup_exit); 86 } 87 88 // 89 // Allocate a @ref SYNC_GPU_BOOST_GROUP for the requested group at the first 90 // available index. 91 // 92 // Note: A linear search is sufficient for practical purposes currently. 93 // 94 for (i = 0; i < NV0000_SYNC_GPU_BOOST_MAX_GROUPS; i++) 95 { 96 // Found an unused index. 97 if (0 == pBoostMgr->pBoostGroups[i].gpuCount) 98 { 99 NvU32 j; 100 101 // Setup the internal state for the new group 102 for(j = 0; j < pBoostConfig->gpuCount; j++) 103 { 104 // Allocate GPU ID node. 105 pGpuIdNode = portMemAllocNonPaged(sizeof(*pGpuIdNode)); 106 if (NULL == pGpuIdNode) 107 { 108 bCleanup = NV_TRUE; 109 NV_ASSERT_OR_GOTO((pGpuIdNode != NULL), gpuboostmgrCreateGroup_exit); 110 } 111 112 // Add each unique GPU ID in the GPU ID tree 113 portMemSet(pGpuIdNode, 0, sizeof(*pGpuIdNode)); 114 pGpuIdNode->keyStart = pBoostConfig->gpuIds[j]; 115 pGpuIdNode->keyEnd = pBoostConfig->gpuIds[j]; 116 status = btreeInsert(pGpuIdNode, &pBoostMgr->pGpuIdTree); 117 if (NV_OK != status) 118 { 119 bCleanup = NV_TRUE; 120 NV_ASSERT_OR_GOTO(NV_OK == status, gpuboostmgrCreateGroup_exit); 121 } 122 123 pBoostMgr->pBoostGroups[i].gpuIds[j] = pBoostConfig->gpuIds[j]; 124 } 125 126 pBoostMgr->groupCount++; 127 pBoostMgr->pBoostGroups[i].gpuCount = pBoostConfig->gpuCount; 128 pBoostMgr->pBoostGroups[i].bBridgeless = pBoostConfig->bBridgeless; 129 130 // Set the out param 131 pBoostConfig->boostGroupId = i; 132 133 // We are done. 134 break; 135 } 136 } 137 138 // Since we've come so far, there can't be 0 unused entries 139 if (i == NV0000_SYNC_GPU_BOOST_MAX_GROUPS) 140 { 141 NV_PRINTF(LEVEL_ERROR, "Inconsistency in pBoostGroups state.\n"); 142 status = NV_ERR_INVALID_STATE; 143 NV_ASSERT_OR_GOTO(0, gpuboostmgrCreateGroup_exit); 144 } 145 146 gpuboostmgrCreateGroup_exit: 147 if (bCleanup) 148 { 149 NvU32 k; 150 151 // Clean up stray state in case of failure 152 for(k = 0; k < pBoostConfig->gpuCount; k++) 153 { 154 btreeSearch(pBoostConfig->gpuIds[k], 155 &pGpuIdNode, 156 pBoostMgr->pGpuIdTree); 157 if (NULL != pGpuIdNode) 158 { 159 btreeUnlink(pGpuIdNode, &pBoostMgr->pGpuIdTree); 160 portMemFree(pGpuIdNode); 161 } 162 } 163 164 // Destroy @ref SYNC_GPU_BOOST_GROUP object 165 portMemSet(&(pBoostMgr->pBoostGroups[i]), 0, sizeof(SYNC_GPU_BOOST_GROUP)); 166 } 167 168 return status; 169 } 170 171 /*! 172 * @brief OBJGPUBOOSTMGR object method to destroy a Sync Gpu Boost Group (SGBG) 173 * 174 * This method will destroy an existing SGBG 175 * 176 * @param [in] boostGroupId Unique ID of the SGBG to be destroyed 177 178 * @returns NV_OK Success 179 * @returns NV_ERR_ILLEGAL_ACTION No SGBGs to destroy in the first place 180 * Or the requested SGBG is already destroyed. 181 * and a few more returned from second level functions. 182 */ 183 NV_STATUS 184 gpuboostmgrDestroyGroup_IMPL 185 ( 186 OBJGPUBOOSTMGR *pBoostMgr, 187 NvU32 boostGroupId 188 ) 189 { 190 NV_STATUS status = NV_OK; 191 NODE *pGpuIdNode = NULL; 192 NvU32 i; 193 194 // Can't try to destroy a non-existing group 195 NV_ASSERT_OR_RETURN(pBoostMgr->groupCount > 0, NV_ERR_ILLEGAL_ACTION); 196 NV_ASSERT_OR_RETURN(NV0000_SYNC_GPU_BOOST_MAX_GROUPS > boostGroupId, NV_ERR_OUT_OF_RANGE); 197 NV_ASSERT_OR_RETURN(0 != pBoostMgr->pBoostGroups[boostGroupId].gpuCount, NV_ERR_ILLEGAL_ACTION); 198 199 // Remove each GPU ID from the ID tree before destorying the group. 200 for(i = 0; i < pBoostMgr->pBoostGroups[boostGroupId].gpuCount; i++) 201 { 202 status = btreeSearch(pBoostMgr->pBoostGroups[boostGroupId].gpuIds[i], 203 &pGpuIdNode, 204 pBoostMgr->pGpuIdTree); 205 NV_ASSERT_OR_RETURN(((NV_OK == status) && (NULL != pGpuIdNode)), status); 206 btreeUnlink(pGpuIdNode, &pBoostMgr->pGpuIdTree); 207 portMemFree(pGpuIdNode); 208 } 209 210 // Destroy @ref SYNC_GPU_BOOST_GROUP object 211 portMemSet(&(pBoostMgr->pBoostGroups[boostGroupId]), 0, sizeof(SYNC_GPU_BOOST_GROUP)); 212 213 // Decrement groupCount 214 pBoostMgr->groupCount--; 215 216 return NV_OK; 217 } 218 219 /*! 220 * @brief Returns information about each Sync Gpu Boost Group defined in the system 221 */ 222 NV_STATUS 223 gpuboostmgrQueryGroups_IMPL 224 ( 225 OBJGPUBOOSTMGR *pBoostMgr, 226 NV0000_SYNC_GPU_BOOST_GROUP_INFO_PARAMS *pParams 227 ) 228 { 229 NvU32 i; 230 NvU32 j; 231 232 j = 0; 233 for (i = 0; i < NV0000_SYNC_GPU_BOOST_MAX_GROUPS; i++) 234 { 235 if (NV_OK == gpuboostmgrValidateGroupId(pBoostMgr, i)) 236 { 237 pParams->pBoostGroups[j].gpuCount = pBoostMgr->pBoostGroups[i].gpuCount; 238 pParams->pBoostGroups[j].boostGroupId = i; 239 portMemCopy(pParams->pBoostGroups[j].gpuIds, 240 sizeof(pParams->pBoostGroups[j].gpuIds), 241 pBoostMgr->pBoostGroups[i].gpuIds, 242 sizeof(pParams->pBoostGroups[j].gpuIds)); 243 j++; 244 } 245 } 246 247 pParams->groupCount = j; 248 249 return NV_OK; 250 } 251 252 /*! 253 * @brief OBJGPUBOOSTMGR object method to validate a config for a Sync Gpu Boost Group (SGBG) 254 * @ref NV0000_SYNC_GPU_BOOST_GROUP_CONFIG 255 * 256 * The following checks needs to be met for a config to be converted to an SGBG 257 * 1. There is room for a new SGBG to be tracked in RM. 258 * 2. Valid GPU IDs are specified 259 * 3. None of the GPUs specified is already a part of an existing SGBG 260 * 261 * @param [in] boostConfig @ref NV0000_SYNC_GPU_BOOST_GROUP_CONFIG 262 * 263 * @returns NV_OK Success 264 * @returns other values Config specified cannot be accepted. 265 */ 266 NV_STATUS 267 gpuboostmgrCheckConfig_IMPL 268 ( 269 OBJGPUBOOSTMGR *pBoostMgr, 270 NV0000_SYNC_GPU_BOOST_GROUP_CONFIG *pBoostConfig 271 ) 272 { 273 NV_STATUS status = NV_OK; 274 OBJGPU *pGpu = NULL; 275 NODE *pNode = NULL; 276 NvU32 i; 277 278 NV_ASSERT_OR_RETURN(NULL != pBoostConfig, NV_ERR_INVALID_ARGUMENT); 279 280 if (0 == pBoostConfig->gpuCount || 281 NV_MAX_DEVICES < pBoostConfig->gpuCount) 282 { 283 status = NV_ERR_OUT_OF_RANGE; 284 NV_PRINTF(LEVEL_ERROR, "Invalid Gpu Count 0x%x\n", pBoostConfig->gpuCount); 285 DBG_BREAKPOINT(); 286 goto gpuboostmgrCheckConfig_exit; 287 } 288 289 // Policy filters will specify if we can support a given config. 290 status = _gpuboostmgrApplyPolicyFilters(pBoostConfig); 291 NV_ASSERT_OR_GOTO(NV_OK == status, gpuboostmgrCheckConfig_exit); 292 293 for (i = 0; i < pBoostConfig->gpuCount; i++) 294 { 295 // Check for invalid GPU ID 296 if (NV0000_CTRL_GPU_INVALID_ID == pBoostConfig->gpuIds[i]) 297 { 298 status = NV_ERR_INVALID_ARGUMENT; 299 NV_PRINTF(LEVEL_ERROR, 300 "Invalid GPU ID 0x%x at index 0x%x\n", 301 pBoostConfig->gpuIds[i], i); 302 DBG_BREAKPOINT(); 303 goto gpuboostmgrCheckConfig_exit; 304 } 305 306 // 307 // Check for OBJGPU being available. 308 // 309 // We do not need to take a GPU lock here, as currently, the API lock 310 // guarantees that OBJ* will not be destroyed while the API 311 // lock is being held. If at all the check needs to read/write OBJGPU state, 312 // we will need the GPU lock. 313 // 314 // We expect that going ahead, client locks will provide similar guarantees 315 // on the GPU state. 316 // 317 pGpu = gpumgrGetGpuFromId(pBoostConfig->gpuIds[i]); 318 if (NULL == pGpu) 319 { 320 status = NV_ERR_INVALID_ARGUMENT; 321 NV_PRINTF(LEVEL_ERROR, 322 "OBJGPU not constructed yet for ID 0x%x at index 0x%x\n", 323 pBoostConfig->gpuIds[i], i); 324 DBG_BREAKPOINT(); 325 goto gpuboostmgrCheckConfig_exit; 326 } 327 328 // A GPU cannot be in more than one Boost Group 329 if (NV_OK == btreeSearch(pBoostConfig->gpuIds[i], &pNode, pBoostMgr->pGpuIdTree)) 330 { 331 status = NV_ERR_INVALID_ARGUMENT; 332 NV_PRINTF(LEVEL_ERROR, 333 "GPU with ID 0x%x already in use in another group\n", 334 pBoostConfig->gpuIds[i]); 335 DBG_BREAKPOINT(); 336 goto gpuboostmgrCheckConfig_exit; 337 } 338 } 339 340 gpuboostmgrCheckConfig_exit: 341 return status; 342 } 343 344 /*! 345 * @brief Constructor 346 */ 347 NV_STATUS 348 gpuboostmgrConstruct_IMPL(OBJGPUBOOSTMGR *pBoostMgr) 349 { 350 return NV_OK; 351 } 352 353 /*! 354 * @brief Destructor 355 */ 356 void 357 gpuboostmgrDestruct_IMPL(OBJGPUBOOSTMGR *pBoostMgr) 358 { 359 btreeDestroyNodes(pBoostMgr->pGpuIdTree); 360 portMemSet(pBoostMgr->pBoostGroups, 0, NV0000_SYNC_GPU_BOOST_MAX_GROUPS * sizeof(SYNC_GPU_BOOST_GROUP)); 361 pBoostMgr->groupCount = 0; 362 } 363 364 365 /*! 366 * @brief Checks if the boost group ID belongs to a valid Sync Gpu Boost Group 367 * 368 * @param [in] boostGroupId ID to be checked 369 * 370 * @returns NV_OK group ID belongs to a valid Group. 371 * @returns NV_ERR_INVALID_INDEX group ID is not used by any SGBG 372 */ 373 NV_STATUS 374 gpuboostmgrValidateGroupId_IMPL 375 ( 376 OBJGPUBOOSTMGR *pBoostMgr, 377 NvU32 boostGroupId 378 ) 379 { 380 if (NV0000_SYNC_GPU_BOOST_MAX_GROUPS <= boostGroupId) 381 return NV_ERR_INVALID_INDEX; 382 383 // If group count is 0, the group index points to an invalid/empty boost group 384 if (0 == pBoostMgr->pBoostGroups[boostGroupId].gpuCount) 385 return NV_ERR_INVALID_INDEX; 386 387 return NV_OK; 388 } 389 390 /*! 391 * @brief Increments the ref count for a Sync Gpu Boost Group 392 * 393 * @param [in] boostGroupId ID of the SGBG whose ref count needs incrementing. 394 * 395 * @returns NV_OK Ref count incremented successfully 396 * 397 */ 398 NV_STATUS 399 gpuboostmgrIncrementRefCount_IMPL 400 ( 401 OBJGPUBOOSTMGR *pBoostMgr, 402 NvU32 boostGroupId 403 ) 404 { 405 NV_STATUS status = NV_OK; 406 407 status = gpuboostmgrValidateGroupId(pBoostMgr, boostGroupId); 408 if (NV_OK != status) 409 { 410 NV_PRINTF(LEVEL_ERROR, "Invalid group ID 0x%x\n", boostGroupId); 411 NV_ASSERT_OR_RETURN(0, status); 412 } 413 414 if (NV_U32_MAX == pBoostMgr->pBoostGroups[boostGroupId].refCount) 415 { 416 NV_PRINTF(LEVEL_ERROR, 417 "Max limit reached for ref count on group 0x%x\n", 418 boostGroupId); 419 NV_ASSERT_OR_RETURN(0, NV_ERR_INSUFFICIENT_RESOURCES); 420 } 421 422 // 423 // Increment the ref count on the SGBG in @ref OJGPUBOOSTMGR 424 // Trigger state change for the SGB Algorithm if this is the first client 425 // referencing the group 426 // 427 pBoostMgr->pBoostGroups[boostGroupId].refCount++; 428 if (1 == pBoostMgr->pBoostGroups[boostGroupId].refCount) 429 { 430 status = kperfGpuBoostSyncStateUpdate(pBoostMgr, boostGroupId, NV_TRUE); 431 if (NV_OK != status) 432 { 433 NV_PRINTF(LEVEL_ERROR, 434 "Could not activate Sync GPU Boost on group 0x%x. Status: 0x%08x\n", 435 boostGroupId, status); 436 pBoostMgr->pBoostGroups[boostGroupId].refCount--; 437 NV_ASSERT(0); 438 } 439 } 440 441 return status; 442 } 443 444 /*! 445 * @brief Decrements the ref count for a Sync Gpu Boost 446 * Group 447 * 448 * @param [in] boostGroupId ID of the SGBG whose ref count needs decrementing. 449 * 450 * @returns NV_OK Ref count decremented successfully 451 * 452 */ 453 NV_STATUS 454 gpuboostmgrDecrementRefCount_IMPL 455 ( 456 OBJGPUBOOSTMGR *pBoostMgr, 457 NvU32 boostGroupId 458 ) 459 { 460 NV_STATUS status = NV_OK; 461 462 status = gpuboostmgrValidateGroupId(pBoostMgr, boostGroupId); 463 if (NV_OK != status) 464 { 465 NV_PRINTF(LEVEL_ERROR, "Invalid group ID 0x%x\n", boostGroupId); 466 NV_ASSERT_OR_RETURN(0, status); 467 } 468 469 if (0 == pBoostMgr->pBoostGroups[boostGroupId].refCount) 470 { 471 NV_PRINTF(LEVEL_ERROR, "Ref count on group 0x%x is already 0\n", 472 boostGroupId); 473 NV_ASSERT_OR_RETURN(0, NV_ERR_INVALID_REQUEST); 474 } 475 476 // 477 // Decrement the ref count on the SGBG in @ref OJGPUBOOSTMGR 478 // Trigger state change for the SGB Algorithm if this was the last client 479 // referencing the group 480 // 481 pBoostMgr->pBoostGroups[boostGroupId].refCount--; 482 if (0 == pBoostMgr->pBoostGroups[boostGroupId].refCount) 483 { 484 status = kperfGpuBoostSyncStateUpdate(pBoostMgr, boostGroupId, NV_FALSE); 485 if (NV_OK != status) 486 { 487 NV_PRINTF(LEVEL_ERROR, 488 "Could not deactivate Sync GPU Boost on group 0x%x. Status: 0x%08x\n", 489 boostGroupId, status); 490 NV_ASSERT(0); 491 } 492 } 493 494 return status; 495 } 496 497 /*! 498 * This iterator function return the GPU at given index from the given SGBG 499 * 500 * @params [in] pBoostGrp Pointer to the SGBG to iterate over 501 * @params [in] grpId ID of the Boost Group over which to iterate. 502 * ID corresponds to index in @ref OBJGPUBOOSTMGR::pBoostGroups 503 * @params [in] pIndex 0 based index into the pBoostGrp, at which the 504 * iteration commences. 505 * 506 * @returns OBJGPU* if a GPU object is found. 507 * NULL otherwise 508 * 509 * Note: Always pass in an initial index of 0, when beginning the iteration. This 510 * method lends itself to a while() construct like so - 511 * while (NULL != (pGpu = ItrMethod(pBoostGrp, &index)){ //foo }; 512 */ 513 POBJGPU 514 gpuboostmgrGpuItr_IMPL 515 ( 516 OBJGPUBOOSTMGR *pBoostMgr, 517 NvU32 grpId, 518 NvU32 *pIndex 519 ) 520 { 521 NV_ASSERT_OR_RETURN(NULL != pIndex, NULL); 522 523 if (0 == pBoostMgr->pBoostGroups[grpId].gpuCount) 524 { 525 NV_PRINTF(LEVEL_ERROR, "Gpu Count is 0 for group ID: 0x%x\n", grpId); 526 return NULL; 527 } 528 if (*pIndex == pBoostMgr->pBoostGroups[grpId].gpuCount) 529 { 530 return NULL; 531 } 532 533 return gpumgrGetGpuFromId(pBoostMgr->pBoostGroups[grpId].gpuIds[(*pIndex)++]); 534 } 535 536 /*! 537 * @brief Retrieves the ID of the SGBG to which a GPU belongs 538 * 539 * @param [in] pBoostMgr 540 * @param [in] pGpu 541 * @param [out] pBoostGrpId ID of the @ref SYNC_GPU_BOOST_GROUP to which the 542 * given GPU belongs. 543 * NV0000_SYNC_GPU_BOOST_INVALID_GROUP_ID value if 544 * group is not found 545 * 546 * @return NV_OK if SGBG is found 547 * @return NV_ERR_OBJECT_NOT_FOUND if SGBG is not found 548 * @return NV_ERR_INVALID_ARGUMENT Null or incorrect arguments passed in. 549 */ 550 NV_STATUS 551 gpuboostmgrGetBoostGrpIdFromGpu_IMPL 552 ( 553 OBJGPUBOOSTMGR *pBoostMgr, 554 OBJGPU *pGpu, 555 NvU32 *pBoostGrpId 556 ) 557 { 558 NvU32 i; 559 NvU32 index = 0; 560 OBJGPU *pGpuTemp = NULL; 561 562 *pBoostGrpId = NV0000_SYNC_GPU_BOOST_INVALID_GROUP_ID; 563 564 NV_ASSERT_OR_RETURN(NULL != pGpu, NV_ERR_INVALID_ARGUMENT); 565 NV_ASSERT_OR_RETURN(NULL != pBoostGrpId, NV_ERR_INVALID_ARGUMENT); 566 567 for (i = 0; i < pBoostMgr->groupCount; i++) 568 { 569 while (NULL != (pGpuTemp = gpuboostmgrGpuItr(pBoostMgr, i, &index))) 570 { 571 if (pGpuTemp->gpuId == pGpu->gpuId) 572 { 573 *pBoostGrpId = i; 574 return NV_OK; 575 } 576 } 577 } 578 579 NV_PRINTF(LEVEL_INFO, 580 "No Boost Group found for the gpu with ID: 0x%08x\n", 581 pGpu->gpuId); 582 583 return NV_ERR_OBJECT_NOT_FOUND; 584 } 585 586 /*! 587 * @return NV_TRUE If the Sync GPU Boost Group at the given ID has the algorithm 588 * active. 589 * NV_FALSE If the group ID is invalid or the algorithm is inactive. 590 */ 591 NvBool 592 gpuboostmgrIsBoostGrpActive_IMPL 593 ( 594 OBJGPUBOOSTMGR *pBoostMgr, 595 NvU32 grpId 596 ) 597 { 598 if (grpId == NV0000_SYNC_GPU_BOOST_INVALID_GROUP_ID) 599 { 600 return NV_FALSE; 601 } 602 603 return ((0 != pBoostMgr->pBoostGroups[grpId].gpuCount) && 604 (0 != pBoostMgr->pBoostGroups[grpId].refCount)); 605 } 606 607 /*------------------------------Static Private Methods------------------------*/ 608 609 /*! 610 * Applies filter policies which determine whether or not to allow the given GPUs 611 * to be in the same SGBG. 612 */ 613 static NV_STATUS 614 _gpuboostmgrApplyPolicyFilters(NV0000_SYNC_GPU_BOOST_GROUP_CONFIG *pBoostConfig) 615 { 616 NV_STATUS status = NV_ERR_NOT_COMPATIBLE; 617 OBJGPU *pGpu = NULL; 618 OBJGPU *pGpuItr = NULL; 619 OBJGPUGRP *pGpuGrp = NULL; 620 NvBool bIsSli = NV_TRUE; 621 NvBool bIsUnlinkedSli = NV_TRUE; 622 NvBool bMatchingDevId = NV_TRUE; 623 NvU32 i; 624 625 NV_ASSERT_OR_RETURN(NULL != pBoostConfig, NV_ERR_INVALID_ARGUMENT); 626 627 pGpu = gpumgrGetGpuFromId(pBoostConfig->gpuIds[0]); 628 NV_ASSERT_OR_RETURN(NULL != pGpu, NV_ERR_OBJECT_NOT_FOUND); 629 pGpuGrp = gpumgrGetGpuGrpFromGpu(pGpu); 630 631 // 632 // Group Filter Policy: 633 // If GPUs are in same SLI device - Allow 634 // else if GPUs have the same (devid, subsystem id, subvendor id, board proj id, board sku id) - Allow 635 // else - Disallow 636 // 637 638 // 639 // Check if all GPUs are in same SLI Device. 640 // We compare @ref OBJGPUGRP for each GPU as opposed to PBJGPU:deviceInstance 641 // because in the future we may move away from the SLI Device Model. 642 // 643 for (i = 1; i < pBoostConfig->gpuCount; i++) 644 { 645 pGpuItr = gpumgrGetGpuFromId(pBoostConfig->gpuIds[i]); 646 NV_ASSERT_OR_RETURN(NULL != pGpuItr, NV_ERR_OBJECT_NOT_FOUND); 647 648 if (pGpuGrp == gpumgrGetGpuGrpFromGpu(pGpuItr)) 649 { 650 continue; 651 } 652 else 653 { 654 bIsSli = NV_FALSE; 655 break; 656 } 657 } 658 if (bIsSli) 659 { 660 status = NV_OK; 661 goto _gpuboostmgrApplyPolicyFilters_exit; 662 } 663 664 // 665 // Check if Unlinked SLI is enabled for all GPUs within the group 666 // 667 for (i = 0; i < pBoostConfig->gpuCount; i++) 668 { 669 pGpuItr = gpumgrGetGpuFromId(pBoostConfig->gpuIds[i]); 670 NV_ASSERT_OR_RETURN(NULL != pGpuItr, NV_ERR_OBJECT_NOT_FOUND); 671 672 if (IsUnlinkedSLIEnabled(pGpuItr)) 673 { 674 continue; 675 } 676 else 677 { 678 bIsUnlinkedSli = NV_FALSE; 679 break; 680 } 681 } 682 if (bIsUnlinkedSli) 683 { 684 status = NV_OK; 685 goto _gpuboostmgrApplyPolicyFilters_exit; 686 } 687 688 // 689 // Check if all the GPUs have same dev id. This needs to be ensured for the Sync 690 // Boost algorithm to provide the expected benefits, unless otherwise specified. 691 // 692 NvU32 pciDevId = 0; 693 NvU64 boardProjNum = 0; 694 NvU64 boardSkuNum = 0; 695 NvU16 subVendor = 0; 696 NvU16 subDevice = 0; 697 GspStaticConfigInfo *pGSCI = NULL; 698 699 pciDevId = DRF_VAL(_PCI, _DEVID, _DEVICE, pGpu->idInfo.PCIDeviceID); 700 701 // Cache all necessary values for one of the GPUs 702 { 703 if ( IS_GSP_CLIENT(pGpu) ) 704 { 705 pGSCI = GPU_GET_GSP_STATIC_INFO(pGpu); 706 } 707 708 if ( !IS_GSP_CLIENT(pGpu) || !pGSCI->bVbiosValid ) 709 { 710 status = NV_ERR_NOT_SUPPORTED; 711 NV_ASSERT_OR_GOTO(NV_FALSE, _gpuboostmgrApplyPolicyFilters_exit); 712 } 713 714 portMemCopy(&boardSkuNum, sizeof(boardSkuNum), pGSCI->SKUInfo.projectSKU, sizeof(pGSCI->SKUInfo.projectSKU)); 715 portMemCopy(&boardProjNum, sizeof(boardProjNum), pGSCI->SKUInfo.project, sizeof(pGSCI->SKUInfo.project)); 716 subVendor = pGSCI->vbiosSubVendor; 717 subDevice = pGSCI->vbiosSubDevice; 718 } 719 720 // Compare each GPU's values with the cached values. 721 for (i = 1; i < pBoostConfig->gpuCount; i++) 722 { 723 NvU64 boardProjNumItr = 0; 724 NvU64 boardSkuNumItr = 0; 725 NvU16 subVendorItr = 0; 726 NvU16 subDeviceItr = 0; 727 728 pGpuItr = gpumgrGetGpuFromId(pBoostConfig->gpuIds[i]); 729 NV_ASSERT_OR_RETURN(NULL != pGpuItr, NV_ERR_OBJECT_NOT_FOUND); 730 731 // Extract values for the GPU in the iteration. 732 { 733 if ( IS_GSP_CLIENT(pGpuItr) ) 734 { 735 pGSCI = GPU_GET_GSP_STATIC_INFO(pGpuItr); 736 } 737 738 if ( !IS_GSP_CLIENT(pGpuItr) || !pGSCI->bVbiosValid ) 739 { 740 status = NV_ERR_OBJECT_NOT_FOUND; 741 bMatchingDevId = NV_FALSE; 742 NV_ASSERT_OR_GOTO(NV_FALSE, _gpuboostmgrApplyPolicyFilters_exit); 743 } 744 portMemCopy(&boardSkuNumItr, sizeof(boardSkuNumItr), pGSCI->SKUInfo.projectSKU, sizeof(pGSCI->SKUInfo.projectSKU)); 745 portMemCopy(&boardProjNumItr, sizeof(boardProjNumItr), pGSCI->SKUInfo.project, sizeof(pGSCI->SKUInfo.project)); 746 subVendorItr = pGSCI->vbiosSubVendor; 747 subDeviceItr = pGSCI->vbiosSubDevice; 748 } 749 750 // Go to the next GPU if all values match 751 if ((pciDevId == DRF_VAL(_PCI, _DEVID, _DEVICE, pGpuItr->idInfo.PCIDeviceID)) && 752 (boardSkuNum == boardSkuNumItr) && 753 (boardProjNum == boardProjNumItr) && 754 (subVendor == subVendorItr) && 755 (subDevice == subDeviceItr)) 756 { 757 continue; 758 } 759 else 760 { 761 // At least one mismatch. 762 bMatchingDevId = NV_FALSE; 763 break; 764 } 765 } 766 if (bMatchingDevId) 767 { 768 status = NV_OK; 769 goto _gpuboostmgrApplyPolicyFilters_exit; 770 } 771 772 _gpuboostmgrApplyPolicyFilters_exit: 773 if (status != NV_OK) 774 { 775 NV_PRINTF(LEVEL_ERROR, 776 "GPUs not compatible to be put in the same group\n"); 777 DBG_BREAKPOINT(); 778 } 779 780 return status; 781 } 782 783 NV_STATUS 784 syncgpuboostConstruct_IMPL 785 ( 786 SyncGpuBoost *pSyncGpuBoost, 787 CALL_CONTEXT *pCallContext, 788 RS_RES_ALLOC_PARAMS_INTERNAL *pParams 789 ) 790 { 791 OBJSYS *pSys = SYS_GET_INSTANCE(); 792 OBJGPUBOOSTMGR *pBoostMgr = SYS_GET_GPUBOOSTMGR(pSys); 793 NV_STATUS rmStatus = NV_OK; 794 NV0060_ALLOC_PARAMETERS *p0060Params = pParams->pAllocParams; 795 796 NV_ASSERT_OR_RETURN(NULL != p0060Params, NV_ERR_INVALID_ARGUMENT); 797 NV_ASSERT_OK_OR_RETURN(gpuboostmgrIncrementRefCount(pBoostMgr, p0060Params->gpuBoostGroupId)); 798 799 pSyncGpuBoost->gpuBoostGroupId = p0060Params->gpuBoostGroupId; 800 801 return rmStatus; 802 } 803 804 void 805 syncgpuboostDestruct_IMPL 806 ( 807 SyncGpuBoost *pSyncGpuBoost 808 ) 809 { 810 RS_RES_FREE_PARAMS_INTERNAL *pParams = NULL; 811 OBJSYS *pSys = SYS_GET_INSTANCE(); 812 OBJGPUBOOSTMGR *pBoostMgr = SYS_GET_GPUBOOSTMGR(pSys); 813 NV_STATUS rmStatus = NV_OK; 814 815 resGetFreeParams(staticCast(pSyncGpuBoost, RsResource), NULL, &pParams); 816 817 // Can't do much if ref count decrement failed. Assert and continue deletion. 818 rmStatus = gpuboostmgrDecrementRefCount(pBoostMgr, pSyncGpuBoost->gpuBoostGroupId); 819 NV_ASSERT(NV_OK == rmStatus); 820 821 pParams->status = rmStatus; 822 823 return; 824 } 825