1 /* 2 * SPDX-FileCopyrightText: Copyright (c) 1993-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 * SPDX-License-Identifier: MIT 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 #include "core/core.h" 24 #include "os/os.h" 25 #include "rmapi/event.h" 26 #include "rmapi/resource_fwd_decls.h" 27 #include "vgpu/rpc.h" 28 #include "gpu/device/device.h" 29 #include "core/locks.h" 30 #include "rmapi/rs_utils.h" 31 32 #include "virtualization/kernel_hostvgpudeviceapi.h" 33 34 #include "gpu/external_device/gsync_api.h" 35 36 #include "resserv/rs_client.h" 37 #include "class/cl0005.h" 38 39 #include "ctrl/ctrl0000/ctrl0000event.h" // NV0000_CTRL_EVENT_SET_NOTIFICATION_ACTION_* 40 41 #if (!NV_RM_STUB_RPC) 42 static NV_STATUS _eventRpcForType(NvHandle hClient, NvHandle hObject); 43 #endif 44 45 NV_STATUS 46 eventConstruct_IMPL 47 ( 48 Event *pEvent, 49 CALL_CONTEXT *pCallContext, 50 RS_RES_ALLOC_PARAMS_INTERNAL *pParams 51 ) 52 { 53 NV0005_ALLOC_PARAMETERS *pNv0050AllocParams = pParams->pAllocParams; 54 RsClient *pRsClient = pCallContext->pClient; 55 RsResourceRef *pClientRef; 56 RsResourceRef *pResourceRef = pCallContext->pResourceRef; 57 NV_STATUS rmStatus = NV_OK; 58 PEVENTNOTIFICATION *ppEventNotification; 59 NvHandle hChannel = 0x0; 60 OBJGPU *pGpu = NULL; 61 RS_PRIV_LEVEL privLevel = pParams->pSecInfo->privLevel; 62 NvBool bUserOsEventHandle = NV_FALSE; 63 NvHandle hParentClient = pNv0050AllocParams->hParentClient; 64 65 // 66 // Allow hParentClient being zero to imply the allocating client should be 67 // the parent client of this event. 68 // 69 if (hParentClient == NV01_NULL_OBJECT) 70 { 71 hParentClient = pRsClient->hClient; 72 } 73 74 // never allow user mode/non-root clients to create ring0 callbacks as 75 // we can not trust the function pointer (encoded in data). 76 if ((NV01_EVENT_KERNEL_CALLBACK == pResourceRef->externalClassId) || 77 (NV01_EVENT_KERNEL_CALLBACK_EX == pResourceRef->externalClassId)) 78 { 79 if (privLevel < RS_PRIV_LEVEL_KERNEL) 80 { 81 // sometimes it is nice to hook up callbacks for debug purposes 82 // -- but disable the override for release builds! 83 #if defined(DEBUG) || defined(DEVELOP) 84 if (!(pNv0050AllocParams->notifyIndex & NV01_EVENT_PERMIT_NON_ROOT_EVENT_KERNEL_CALLBACK_CREATION)) 85 #endif 86 { 87 return NV_ERR_ILLEGAL_ACTION; 88 } 89 } 90 } 91 92 #if (!NV_RM_STUB_RPC) 93 if (_eventRpcForType(hParentClient, pNv0050AllocParams->hSrcResource)) 94 { 95 RsResourceRef *pSrcRef; 96 NV_STATUS tmpStatus; 97 98 tmpStatus = serverutilGetResourceRef(hParentClient, 99 pNv0050AllocParams->hSrcResource, 100 &pSrcRef); 101 102 if (tmpStatus == NV_OK) 103 { 104 hChannel = pSrcRef->pParentRef ? pSrcRef->pParentRef->hResource : 0; 105 pGpu = CliGetGpuFromContext(pSrcRef, NULL); 106 107 if (pGpu == NULL) 108 { 109 NV_PRINTF(LEVEL_ERROR, 110 "RmAllocEvent could not set pGpu. hClient=0x%x, hObject=0x%x\n", 111 pRsClient->hClient, pResourceRef->hResource); 112 } 113 } 114 } 115 #endif 116 117 NV_ASSERT_OK_OR_RETURN(clientGetResourceRef(pRsClient, pRsClient->hClient, &pClientRef)); 118 119 // add event to client and parent object 120 rmStatus = eventInit(pEvent, 121 pCallContext, 122 hParentClient, 123 pNv0050AllocParams->hSrcResource, 124 &ppEventNotification); 125 if (rmStatus == NV_OK) 126 { 127 // 128 // vGPU: 129 // 130 // Since vGPU does all real hardware management in the 131 // host, if we are in guest OS (where IS_VIRTUAL(pGpu) is true), 132 // do an RPC to the host to do the hardware update. 133 // 134 // In RM-offload, we don't allocate ContextDma in GSP-RM unless there 135 // is any necessity to use it (e.g. display channel binding time). So 136 // GSP-RM will find no valid object if the event is associated with 137 // ContextDma object. So we are ignoring the event allocation here if 138 // the event is associated with ContextDma object. 139 // 140 if (pGpu != NULL) 141 { 142 RsResourceRef *pSourceRef; 143 144 if (IS_GSP_CLIENT(pGpu)) 145 { 146 NV_ASSERT_OK_OR_RETURN( 147 serverutilGetResourceRef(hParentClient, 148 pNv0050AllocParams->hSrcResource, 149 &pSourceRef)); 150 } 151 152 if ( 153 !(IS_GSP_CLIENT(pGpu) && (pSourceRef->internalClassId == classId(KernelHostVgpuDeviceApi))) && 154 (IS_VIRTUAL_WITHOUT_SRIOV(pGpu) || 155 (IS_GSP_CLIENT(pGpu) && pSourceRef->internalClassId != classId(ContextDma)) || 156 (IS_VIRTUAL_WITH_SRIOV(pGpu) && !(pNv0050AllocParams->notifyIndex & NV01_EVENT_NONSTALL_INTR)))) 157 { 158 // 159 // In SR-IOV enabled systems, nonstall events can be registered 160 // directly with guest RM since guest RM is capable of 161 // receiving and handling nonstall interrupts itself. In 162 // paravirtualized systems, we always need to use the RPC to 163 // host RM. 164 // 165 NV_RM_RPC_ALLOC_EVENT(pGpu, 166 pRsClient->hClient, 167 pEvent->hNotifierClient, 168 hChannel, 169 pEvent->hNotifierResource, 170 pResourceRef->hResource, 171 pResourceRef->externalClassId, 172 pNv0050AllocParams->notifyIndex, 173 rmStatus); 174 } 175 } 176 177 if (NV01_EVENT_OS_EVENT == pResourceRef->externalClassId) 178 { 179 // convert a user event handle to its kernel equivalent. 180 if (privLevel <= RS_PRIV_LEVEL_USER_ROOT) 181 { 182 rmStatus = osUserHandleToKernelPtr(pRsClient->hClient, 183 pNv0050AllocParams->data, 184 &pNv0050AllocParams->data); 185 bUserOsEventHandle = NV_TRUE; 186 } 187 } 188 189 if (rmStatus == NV_OK) 190 rmStatus = registerEventNotification(ppEventNotification, 191 pRsClient, 192 pEvent->hNotifierResource, 193 pResourceRef->hResource, 194 pNv0050AllocParams->notifyIndex, 195 pResourceRef->externalClassId, 196 pNv0050AllocParams->data, 197 bUserOsEventHandle); 198 } 199 200 if (rmStatus != NV_OK) 201 goto cleanup; 202 203 return NV_OK; 204 205 cleanup: 206 eventDestruct_IMPL(pEvent); 207 return rmStatus; 208 } 209 210 void eventDestruct_IMPL 211 ( 212 Event *pEvent 213 ) 214 { 215 CALL_CONTEXT *pCallContext; 216 RS_RES_FREE_PARAMS_INTERNAL *pParams; 217 218 RsClient* pRsClient; 219 NvHandle hEventClient; 220 NV_STATUS status = NV_OK; 221 NvHandle hEvent; 222 NotifShare *pNotifierShare; 223 224 resGetFreeParams(staticCast(pEvent, RsResource), &pCallContext, &pParams); 225 pRsClient = pCallContext->pClient; 226 hEventClient = pRsClient->hClient; 227 hEvent = pCallContext->pResourceRef->hResource; 228 229 LOCK_METER_DATA(FREE_EVENT, 0, 0, 0); 230 231 pNotifierShare = pEvent->pNotifierShare; 232 if (pNotifierShare != NULL) 233 { 234 if (pNotifierShare->pNotifier != NULL) 235 { 236 status = inotifyUnregisterEvent(pNotifierShare->pNotifier, 237 pNotifierShare->hNotifierClient, 238 pNotifierShare->hNotifierResource, 239 hEventClient, 240 hEvent); 241 } 242 serverFreeShare(&g_resServ, staticCast(pEvent->pNotifierShare, RsShared)); 243 } 244 245 if (pParams != NULL) 246 pParams->status = status; 247 } 248 249 NV_STATUS notifyUnregisterEvent_IMPL 250 ( 251 Notifier *pNotifier, 252 NvHandle hNotifierClient, 253 NvHandle hNotifierResource, 254 NvHandle hEventClient, 255 NvHandle hEvent 256 ) 257 { 258 NV_STATUS status = NV_OK; 259 PEVENTNOTIFICATION *ppEventNotification; 260 261 ppEventNotification = inotifyGetNotificationListPtr(staticCast(pNotifier, INotifier)); 262 263 // delete the event from the parent object and client 264 if (*ppEventNotification != NULL) 265 { 266 267 #if (!NV_RM_STUB_RPC) 268 if (_eventRpcForType(hNotifierClient, hNotifierResource)) 269 { 270 OBJGPU *pGpu = CliGetGpuFromHandle(hNotifierClient, hNotifierResource, NULL); 271 272 if (pGpu != NULL) 273 { 274 RsResourceRef *pNotifierRef = NULL; 275 276 if (IS_GSP_CLIENT(pGpu)) 277 { 278 NV_ASSERT_OK_OR_RETURN(serverutilGetResourceRef(hNotifierClient, hNotifierResource, &pNotifierRef)); 279 } 280 281 // 282 // vGPU: 283 // 284 // Since vGPU does all real hardware management in the 285 // host, if we are in guest OS (where IS_VIRTUAL(pGpu) is true), 286 // do an RPC to the host to do the hardware update. 287 // 288 if ( 289 !(IS_GSP_CLIENT(pGpu) && (pNotifierRef->internalClassId == classId(KernelHostVgpuDeviceApi))) && 290 (IS_VIRTUAL_WITHOUT_SRIOV(pGpu) || 291 (IS_GSP_CLIENT(pGpu) && pNotifierRef->internalClassId != classId(ContextDma)) || 292 (IS_VIRTUAL_WITH_SRIOV(pGpu) && !((*ppEventNotification)->bNonStallIntrEvent)))) 293 { 294 // 295 // In SR-IOV enabled systems, nonstall events are registered 296 // directly with guest RM since guest RM is capable of 297 // receiving and handling nonstall interrupts itself. We skip 298 // the allocation, so here, we skip the free too. In 299 // paravirtualized systems, we always need to use the RPC to 300 // host RM. 301 // 302 NV_RM_RPC_FREE(pGpu, hEventClient, hEventClient, hEvent, status); 303 } 304 } 305 else 306 { 307 NV_PRINTF(LEVEL_ERROR, 308 "RmFreeEvent could not set pGpu. hClient=0x%x, hObject=0x%x\n", 309 hNotifierClient, hNotifierResource); 310 } 311 } 312 #endif 313 314 unregisterEventNotification(ppEventNotification, 315 hEventClient, 316 hNotifierResource, 317 hEvent); 318 319 } 320 321 // Gsync needs special event handling (ugh). 322 // 323 GSyncApi *pGSyncApi = dynamicCast(pNotifier, GSyncApi); 324 if (pGSyncApi != NULL) 325 { 326 NvU32 eventNum; 327 328 // check all events bound to this gsync object 329 for (eventNum = 0; eventNum < NV30F1_CTRL_GSYNC_EVENT_TYPES; eventNum++) 330 { 331 if ((pGSyncApi->pEventByType[eventNum]) && 332 (pGSyncApi->pEventByType[eventNum]->hEventClient == hEventClient) && 333 (pGSyncApi->pEventByType[eventNum]->hEvent == hEvent)) 334 { 335 unregisterEventNotification(&pGSyncApi->pEventByType[eventNum], 336 hEventClient, 337 hNotifierResource, 338 hEvent); 339 } 340 } 341 } 342 343 return status; 344 } 345 346 NV_STATUS 347 eventInit_IMPL 348 ( 349 Event *pEvent, 350 CALL_CONTEXT *pCallContext, 351 NvHandle hNotifierClient, 352 NvHandle hNotifierResource, 353 PEVENTNOTIFICATION **pppEventNotification 354 ) 355 { 356 NV_STATUS rmStatus = NV_OK; 357 RsClient *pRsClient = pCallContext->pClient; 358 RsClient *pNotifierClient; 359 RsResourceRef *pResourceRef = pCallContext->pResourceRef; 360 NotifShare *pNotifierShare = NULL; 361 362 // validate event class 363 switch (pResourceRef->externalClassId) 364 { 365 case NV01_EVENT_KERNEL_CALLBACK: 366 case NV01_EVENT_KERNEL_CALLBACK_EX: 367 case NV01_EVENT_OS_EVENT: 368 break; 369 370 default: 371 return NV_ERR_INVALID_CLASS; 372 } 373 374 // RS-TODO remove support for this after per-client locking is enabled 375 if (pRsClient->hClient != hNotifierClient) 376 { 377 rmStatus = serverGetClientUnderLock(&g_resServ, hNotifierClient, &pNotifierClient); 378 if (rmStatus != NV_OK) 379 return rmStatus; 380 } 381 else 382 { 383 pNotifierClient = pRsClient; 384 } 385 386 if (pNotifierClient != NULL) 387 { 388 RsResourceRef *pNotifierRef; 389 INotifier *pNotifier; 390 if (clientGetResourceRef(pNotifierClient, hNotifierResource, &pNotifierRef) != NV_OK) 391 return NV_ERR_INVALID_OBJECT; 392 393 pNotifier = dynamicCast(pNotifierRef->pResource, INotifier); 394 if (pNotifier == NULL) 395 return NV_ERR_INVALID_OBJECT; 396 397 rmStatus = inotifyGetOrAllocNotifShare(pNotifier, hNotifierClient, hNotifierResource, &pNotifierShare); 398 if (rmStatus != NV_OK) 399 return rmStatus; 400 401 *pppEventNotification = inotifyGetNotificationListPtr(pNotifierShare->pNotifier); 402 } 403 404 serverRefShare(&g_resServ, staticCast(pNotifierShare, RsShared)); 405 pEvent->pNotifierShare = pNotifierShare; 406 407 // RS-TODO these can be looked up from share 408 pEvent->hNotifierClient = hNotifierClient; 409 pEvent->hNotifierResource = hNotifierResource; 410 pEvent->hEvent = pCallContext->pResourceRef->hResource; 411 412 return rmStatus; 413 } 414 415 NV_STATUS 416 notifyGetOrAllocNotifShare_IMPL 417 ( 418 Notifier *pNotifier, 419 NvHandle hNotifierClient, 420 NvHandle hNotifierResource, 421 NotifShare **ppNotifierShare 422 ) 423 { 424 NV_STATUS status; 425 NotifShare *pNotifierShare; 426 427 // 428 // Most objects that are notifiers will never have any events to notify so 429 // notifier shares are allocated as needed (i.e., when an event 430 // registers itself with the notifier.) 431 // 432 pNotifierShare = inotifyGetNotificationShare(staticCast(pNotifier, INotifier)); 433 if (pNotifierShare == NULL) 434 { 435 RsShared *pShare; 436 status = serverAllocShare(&g_resServ, classInfo(NotifShare), &pShare); 437 if (status != NV_OK) 438 return status; 439 440 pNotifierShare = dynamicCast(pShare, NotifShare); 441 pNotifierShare->pNotifier = staticCast(pNotifier, INotifier); 442 pNotifierShare->hNotifierClient = hNotifierClient; 443 pNotifierShare->hNotifierResource = hNotifierResource; 444 inotifySetNotificationShare(staticCast(pNotifier, INotifier), pNotifierShare); 445 } 446 447 if (ppNotifierShare) 448 *ppNotifierShare = pNotifierShare; 449 450 return NV_OK; 451 } 452 453 NV_STATUS 454 CliGetEventNotificationList 455 ( 456 NvHandle hClient, 457 NvHandle hObject, 458 INotifier **ppNotifier, 459 PEVENTNOTIFICATION **pppEventNotification 460 ) 461 { 462 NV_STATUS status = NV_OK; 463 RsResourceRef *pResourceRef; 464 RsClient *pRsClient; 465 INotifier *pNotifier; 466 467 *pppEventNotification = NULL; 468 469 // Populate Resource Server information 470 status = serverGetClientUnderLock(&g_resServ, hClient, &pRsClient); 471 if (status != NV_OK) 472 return status; 473 474 status = clientGetResourceRef(pRsClient, hObject, &pResourceRef); 475 if (status != NV_OK) 476 return status; 477 478 pNotifier = dynamicCast(pResourceRef->pResource, INotifier); 479 if (pNotifier != NULL) 480 *pppEventNotification = inotifyGetNotificationListPtr(pNotifier); 481 482 if (*pppEventNotification == NULL) 483 return NV_ERR_INVALID_OBJECT; 484 485 if (ppNotifier != NULL) 486 *ppNotifier = pNotifier; 487 488 return NV_OK; 489 } 490 491 NvBool 492 CliGetEventInfo 493 ( 494 NvHandle hClient, 495 NvHandle hEvent, 496 Event **ppEvent 497 ) 498 { 499 RsClient *pRsClient; 500 RsResourceRef *pResourceRef; 501 RmClient *pClient = serverutilGetClientUnderLock(hClient); 502 503 if (pClient == NULL) 504 return NV_FALSE; 505 506 pRsClient = staticCast(pClient, RsClient); 507 if (clientGetResourceRefByType(pRsClient, hEvent, classId(Event), &pResourceRef) != NV_OK) 508 return NV_FALSE; 509 510 if (pResourceRef->pResource != NULL) 511 { 512 *ppEvent = dynamicCast(pResourceRef->pResource, Event); 513 return NV_TRUE; 514 } 515 516 return NV_FALSE; 517 518 } 519 520 NvBool 521 CliDelObjectEvents 522 ( 523 NvHandle hClient, 524 NvHandle hResource 525 ) 526 { 527 NotifShare *pNotifierShare; 528 INotifier *pNotifier; 529 RsClient *pRsClient; 530 NV_STATUS status = NV_OK; 531 RsResourceRef *pResourceRef; 532 533 status = serverGetClientUnderLock(&g_resServ, hClient, &pRsClient); 534 if (status != NV_OK) 535 return NV_FALSE; 536 537 status = clientGetResourceRef(pRsClient, hResource, &pResourceRef); 538 if (status != NV_OK) 539 return NV_FALSE; 540 541 // If not a notifier object, there aren't any events to free 542 pNotifier = dynamicCast(pResourceRef->pResource, INotifier); 543 544 if (pNotifier == NULL) 545 return NV_TRUE; 546 547 pNotifierShare = inotifyGetNotificationShare(pNotifier); 548 if (pNotifierShare != NULL) 549 { 550 while(pNotifierShare->pEventList != NULL) 551 { 552 PEVENTNOTIFICATION pEventNotif = pNotifierShare->pEventList; 553 status = inotifyUnregisterEvent(pNotifier, 554 pNotifierShare->hNotifierClient, 555 pNotifierShare->hNotifierResource, 556 pEventNotif->hEventClient, 557 pEventNotif->hEvent); 558 } 559 pNotifierShare->pNotifier = NULL; 560 } 561 562 return NV_TRUE; 563 564 } // end of CliDelObjectEvents() 565 566 // **************************************************************************** 567 // System events 568 // **************************************************************************** 569 570 void CliAddSystemEvent( 571 NvU32 event, 572 NvU32 status 573 ) 574 { 575 NvU32 temp; 576 PEVENTNOTIFICATION pEventNotification = NULL; 577 RmClient **ppClient; 578 RmClient *pClient; 579 RsClient *pRsClient; 580 RsResourceRef *pCliResRef; 581 NV_STATUS rmStatus = NV_OK; 582 Notifier *pNotifier; 583 584 for (ppClient = serverutilGetFirstClientUnderLock(); 585 ppClient; 586 ppClient = serverutilGetNextClientUnderLock(ppClient)) 587 { 588 pClient = *ppClient; 589 pRsClient = staticCast(pClient, RsClient); 590 591 if (pClient->CliSysEventInfo.notifyActions[event] == NV2080_CTRL_EVENT_SET_NOTIFICATION_ACTION_DISABLE) 592 { 593 continue; 594 } 595 596 temp = (pClient->CliSysEventInfo.systemEventsQueue.Head + 1) % NV_SYSTEM_EVENT_QUEUE_SIZE; 597 598 if (temp == pClient->CliSysEventInfo.systemEventsQueue.Tail) 599 { 600 NV_PRINTF(LEVEL_ERROR, "system event queue is full"); 601 return; 602 } 603 604 pClient->CliSysEventInfo.systemEventsQueue.EventQueue[pClient->CliSysEventInfo.systemEventsQueue.Head].event = event; 605 pClient->CliSysEventInfo.systemEventsQueue.EventQueue[pClient->CliSysEventInfo.systemEventsQueue.Head].status = status; 606 pClient->CliSysEventInfo.systemEventsQueue.Head = temp; 607 608 rmStatus = clientGetResourceRef(staticCast(pClient, RsClient), pRsClient->hClient, &pCliResRef); 609 if (rmStatus != NV_OK) 610 { 611 NV_PRINTF(LEVEL_ERROR, 612 "Failed to look up resource reference handle: 0x%x\n", 613 pRsClient->hClient); 614 return; 615 } 616 617 pNotifier = dynamicCast(pCliResRef->pResource, Notifier); 618 if (pNotifier != NULL) 619 pEventNotification = inotifyGetNotificationList(staticCast(pNotifier, INotifier)); 620 621 if (pEventNotification != NULL) 622 { 623 while (pEventNotification) 624 { 625 if (pEventNotification->NotifyIndex == event) 626 { 627 if (osNotifyEvent(NULL, pEventNotification, 0, 0, 0) != NV_OK) 628 { 629 NV_PRINTF(LEVEL_ERROR, "failed to deliver event 0x%x", 630 event); 631 } 632 } 633 pEventNotification = pEventNotification->Next; 634 } 635 636 if (pClient->CliSysEventInfo.notifyActions[event] == NV0000_CTRL_EVENT_SET_NOTIFICATION_ACTION_SINGLE) 637 { 638 pClient->CliSysEventInfo.notifyActions[event] = NV0000_CTRL_EVENT_SET_NOTIFICATION_ACTION_DISABLE; 639 } 640 } 641 } 642 643 return; 644 } 645 646 #if (!NV_RM_STUB_RPC) 647 static NV_STATUS 648 _eventRpcForType(NvHandle hClient, NvHandle hObject) 649 { 650 NV_STATUS status; 651 RsResourceRef *pResourceRef; 652 653 status = serverutilGetResourceRef(hClient, hObject, &pResourceRef); 654 655 if (status != NV_OK) 656 { 657 return NV_FALSE; 658 } 659 660 if (objDynamicCastById(pResourceRef->pResource, classId(Subdevice)) || 661 objDynamicCastById(pResourceRef->pResource, classId(KernelHostVgpuDeviceApi)) || 662 objDynamicCastById(pResourceRef->pResource, classId(ChannelDescendant)) || 663 objDynamicCastById(pResourceRef->pResource, classId(ContextDma)) || 664 objDynamicCastById(pResourceRef->pResource, classId(DispChannel)) || 665 objDynamicCastById(pResourceRef->pResource, classId(TimerApi)) || 666 objDynamicCastById(pResourceRef->pResource, classId(KernelSMDebuggerSession))) 667 { 668 return NV_TRUE; 669 } 670 671 return NV_FALSE; 672 } 673 #endif 674