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