1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 2021-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3  * SPDX-License-Identifier: MIT
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 /****************************************************************************
25 *
26 *   Kernel Ccu Module
27 *   This file contains functions managing CCU core on CPU RM
28 *
29 ****************************************************************************/
30 
31 #include "gpu/ccu/kernel_ccu.h"
32 #include "gpu/mig_mgr/kernel_mig_manager.h"
33 #include "objtmr.h"
34 #include "ctrl/ctrl2080/ctrl2080perf_cf.h"
35 #include "utils/nvassert.h"
36 
37 /*!
38  * Constrcutor for kccu class.
39  *
40  * @param[in] pGpu          GPU object pointer.
41  * @param[in] pKernelCcu    KernelCcu object pointer
42  * @param[in] engDesc       KernelCcu Engine descriptor
43  *
44  * @return  NV_OK  If successfully constructed.
45  */
46 NV_STATUS
47 kccuConstructEngine_IMPL
48 (
49    OBJGPU        *pGpu,
50    KernelCcu     *pKernelCcu,
51    ENGDESCRIPTOR engDesc
52 )
53 {
54     NV_PRINTF(LEVEL_INFO, "KernelCcu: Constructor\n");
55 
56     return NV_OK;
57 }
58 
59 /*!
60  * Destructor
61  *
62  * @param[in]  pKernelCcu  KernelCcu object pointer
63  */
64 void
65 kccuDestruct_IMPL
66 (
67     KernelCcu *pKernelCcu
68 )
69 {
70     NV_PRINTF(LEVEL_INFO, "KernelCcu: Destructor\n");
71 
72     return;
73 }
74 
75 /*!
76  * Allocate memory for class members, create & map shared buffer and initialize counter start
77  * address and head/tail timestamp address
78  *
79  * @param[in]      pGpu       GPU object pointer
80  * @param[in]      pKernelCcu KernelCcu object pointer
81  * @param[in]      idx        MIG inst/for non-mig case idx is "0"
82  * @param[in]      shrBufSize Shared buffer size
83  * @param[in]      counterBlockSize   Counter block size
84  *
85  * @return  NV_OK on success, specific error code on failure.
86  */
87 static NV_STATUS
88 _kccuAllocMemory
89 (
90    OBJGPU     *pGpu,
91    KernelCcu  *pKernelCcu,
92    NvU32      idx,
93    NvU32      shrBufSize,
94    NvU64      counterBlockSize
95 )
96 {
97     NV_STATUS status            = NV_OK;
98     MEMORY_DESCRIPTOR *pMemDesc = NULL;
99 
100     NV_PRINTF(LEVEL_INFO, "KernelCcu: Allocate memory for class members and shared buffer\n");
101 
102     // Allocate memory & init the KernelCcu class members to store shared buffer info
103     pKernelCcu->shrBuf[idx].pCounterDstInfo = portMemAllocNonPaged(sizeof(CCU_SHRBUF_INFO));
104     pKernelCcu->shrBuf[idx].pKernelMapInfo  = portMemAllocNonPaged(sizeof(SHARED_BUFFER_MAP_INFO));
105 
106     if (pKernelCcu->shrBuf[idx].pCounterDstInfo == NULL || pKernelCcu->shrBuf[idx].pKernelMapInfo == NULL)
107     {
108         status = NV_ERR_NO_MEMORY;
109         NV_PRINTF(LEVEL_ERROR, "CCU port mem alloc failed for(%u) with status: 0x%x\n", idx, status);
110         goto free_alloc;
111     }
112     portMemSet(pKernelCcu->shrBuf[idx].pCounterDstInfo, 0, sizeof(CCU_SHRBUF_INFO));
113     portMemSet(pKernelCcu->shrBuf[idx].pKernelMapInfo, 0, sizeof(SHARED_BUFFER_MAP_INFO));
114 
115     // Create a memory descriptor data structure for the shared buffer
116     status = memdescCreate(&pKernelCcu->pMemDesc[idx], pGpu, shrBufSize, 0, NV_MEMORY_CONTIGUOUS,
117                            ADDR_SYSMEM, NV_MEMORY_CACHED,
118                            MEMDESC_FLAGS_USER_READ_ONLY);
119     if (status != NV_OK)
120     {
121         NV_PRINTF(LEVEL_ERROR, "CCU memdescCreate failed for(%u) with status: 0x%x\n", idx, status);
122         goto free_alloc;
123     }
124 
125     pMemDesc = pKernelCcu->pMemDesc[idx];
126     if (pMemDesc == NULL)
127     {
128         NV_PRINTF(LEVEL_ERROR, "CCU memdescCreate failed. memdesc for(%u) is NULL\n", idx);
129         goto free_alloc;
130     }
131 
132     // Allocate physical storage for the memory descriptor
133     status = memdescAlloc(pMemDesc);
134     if (status != NV_OK)
135     {
136         NV_PRINTF(LEVEL_ERROR, "CCU memdescAlloc failed for(%u) with status: 0x%x\n", idx, status);
137         memdescDestroy(pMemDesc);
138         goto free_alloc;
139     }
140 
141     // Map memory to kernel VA space
142     status = memdescMap(pMemDesc, 0, shrBufSize, NV_TRUE, NV_PROTECT_READ_WRITE,
143                         &pKernelCcu->shrBuf[idx].pKernelMapInfo->addr,
144                         &pKernelCcu->shrBuf[idx].pKernelMapInfo->priv);
145     if (status != NV_OK)
146     {
147         NV_PRINTF(LEVEL_ERROR, "CCU memdescMap failed for(%u)with status: 0x%x\n", idx, status);
148         memdescFree(pMemDesc);
149         memdescDestroy(pMemDesc);
150         goto free_alloc;
151     }
152     portMemSet(pKernelCcu->shrBuf[idx].pKernelMapInfo->addr, 0, shrBufSize);
153 
154     // Init the counter start address, head & tail timestamp address and counter block size
155     pKernelCcu->shrBuf[idx].pCounterDstInfo->pHeadTimeStamp =
156         (NvU64 *)pKernelCcu->shrBuf[idx].pKernelMapInfo->addr;
157     pKernelCcu->shrBuf[idx].pCounterDstInfo->pCounterBlock =
158         (NvP64)((NvUPtr)pKernelCcu->shrBuf[idx].pKernelMapInfo->addr + CCU_TIMESTAMP_SIZE);
159     pKernelCcu->shrBuf[idx].pCounterDstInfo->pTailTimeStamp =
160         (NvU64 *)((NvUPtr)pKernelCcu->shrBuf[idx].pCounterDstInfo->pCounterBlock + counterBlockSize);
161     pKernelCcu->shrBuf[idx].pCounterDstInfo->pSwizzId =
162         (NvU8 *)((NvUPtr)pKernelCcu->shrBuf[idx].pCounterDstInfo->pTailTimeStamp + CCU_TIMESTAMP_SIZE);
163     pKernelCcu->shrBuf[idx].pCounterDstInfo->pComputeId =
164         (NvU8 *)((NvUPtr)pKernelCcu->shrBuf[idx].pCounterDstInfo->pSwizzId + CCU_MIG_SWIZZID_SIZE);
165         pKernelCcu->shrBuf[idx].pCounterDstInfo->counterBlockSize = counterBlockSize;
166 
167     // Set mig swizz-id and compute-inst id to invalid
168     if (!RMCFG_FEATURE_MODS_FEATURES)
169     {
170         *pKernelCcu->shrBuf[idx].pCounterDstInfo->pSwizzId = CCU_MIG_INVALID_SWIZZID;
171         *pKernelCcu->shrBuf[idx].pCounterDstInfo->pComputeId = CCU_MIG_INVALID_COMPUTEID;
172     }
173 
174     return NV_OK;
175 
176 free_alloc:
177     portMemFree(pKernelCcu->shrBuf[idx].pCounterDstInfo);
178     portMemFree(pKernelCcu->shrBuf[idx].pKernelMapInfo);
179     return status;
180 }
181 
182 /*!
183  * Cleanup shared buffer and class member memory for given shared buffer index
184  *
185  * @param[in]      pGpu       GPU object pointer
186  * @param[in]      pKernelCcu KernelCcu object pointer
187  * @param[in]      idx        MIG inst/for non-mig case idx is "0"
188  *
189  */
190 void
191 kccuShrBufIdxCleanup_IMPL
192 (
193     OBJGPU     *pGpu,
194     KernelCcu  *pKernelCcu,
195     NvU32      idx
196 )
197 {
198     MEMORY_DESCRIPTOR *pMemDesc = pKernelCcu->pMemDesc[idx];
199 
200     NV_PRINTF(LEVEL_INFO, "Shared buffer unmap & free for idx(%u).\n", idx);
201 
202     memdescUnmap(pMemDesc, NV_TRUE, osGetCurrentProcess(),
203             pKernelCcu->shrBuf[idx].pKernelMapInfo->addr,
204             pKernelCcu->shrBuf[idx].pKernelMapInfo->priv);
205     memdescFree(pMemDesc);
206     memdescDestroy(pMemDesc);
207 
208     // Free class member memory
209     portMemFree(pKernelCcu->shrBuf[idx].pCounterDstInfo);
210     portMemFree(pKernelCcu->shrBuf[idx].pKernelMapInfo);
211     pKernelCcu->shrBuf[idx].pCounterDstInfo = NULL;
212     pKernelCcu->shrBuf[idx].pKernelMapInfo  = NULL;
213     pKernelCcu->pMemDesc[idx]               = NULL;
214 }
215 
216 /*!
217  * Unmap & free memory desc, shared buffer and class member memory
218  *
219  * @param[in]      pGpu       GPU object pointer
220  * @param[in]      pKernelCcu KernelCcu object pointer
221  *
222  */
223 static void
224 _kccuUnmapAndFreeMemory
225 (
226     OBJGPU     *pGpu,
227     KernelCcu  *pKernelCcu
228 )
229 {
230     NvU32 i = 0;
231     NV_STATUS status = NV_OK;
232     NV2080_CTRL_INTERNAL_CCU_UNMAP_INFO_PARAMS params = { 0 };
233 
234     NV_PRINTF(LEVEL_INFO, "KernelCcu: Unmap and free shared buffer\n");
235 
236     // Internal RM api ctrl call to physical RM to unmap dev & mig shared buffer memdesc
237     RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu);
238     params.bDevShrBuf = NV_TRUE;
239     params.bMigShrBuf = NV_TRUE;
240 
241     status = pRmApi->Control(pRmApi,
242                              pGpu->hInternalClient,
243                              pGpu->hInternalSubdevice,
244                              NV2080_CTRL_CMD_INTERNAL_CCU_UNMAP,
245                              &params,
246                              sizeof(params));
247     if (status != NV_OK)
248     {
249         NV_PRINTF(LEVEL_ERROR, "CCU memdesc unmap request failed with status: 0x%x\n", status);
250     }
251 
252     // Unmap & free mem desc
253     for (i = 0; i < CCU_SHRBUF_COUNT_MAX; i++)
254     {
255         if (pKernelCcu->pMemDesc[i] != NULL)
256         {
257             kccuShrBufIdxCleanup(pGpu, pKernelCcu, i);
258         }
259     }
260 }
261 
262 /*!
263  * Send shared buffer info to phy-RM/gsp
264  *
265  * @param[in]  pGpu           GPU object pointer
266  * @param[in]  pKernelCcu     KernelCcu object pointer
267  * @param[in]  shrBufStartIdx Shared buffer start idx
268  *
269  * @return  NV_OK on success, specific error code on failure.
270  */
271 NV_STATUS
272 kccuShrBufInfoToCcu_IMPL
273 (
274     OBJGPU     *pGpu,
275     KernelCcu  *pKernelCcu,
276     NvU32      shrBufStartIdx
277 )
278 {
279     NV2080_CTRL_INTERNAL_CCU_MAP_INFO_PARAMS inParams = { 0 };
280     NV_STATUS status = NV_OK;
281     NvU32     idx    = 0;
282 
283     NV_PRINTF(LEVEL_INFO, "Send shared buffer info to phyRM/gsp to map.\n");
284 
285     for (idx = shrBufStartIdx; idx < CCU_SHRBUF_COUNT_MAX; idx++)
286     {
287         if (pKernelCcu->pMemDesc[idx] != NULL)
288         {
289             inParams.phyAddr[idx] = memdescGetPhysAddr(pKernelCcu->pMemDesc[idx], AT_GPU, 0);
290         }
291     }
292 
293     // Internal RM api ctrl call to physical RM to map shared buffer memdesc
294     RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu);
295 
296     status = pRmApi->Control(pRmApi,
297                              pGpu->hInternalClient,
298                              pGpu->hInternalSubdevice,
299                              NV2080_CTRL_CMD_INTERNAL_CCU_MAP,
300                              &inParams,
301                              sizeof(inParams));
302     if (status != NV_OK)
303     {
304         NV_PRINTF(LEVEL_ERROR, "CCU memdesc map request failed with status: 0x%x\n", status);
305     }
306 
307     return status;
308 }
309 
310 /*!
311  * Create shared buffer for device counters
312  *
313  * @param[in]      pGpu       GPU object pointer
314  * @param[in]      pKernelCcu KernelCcu object pointer
315  *
316  * @return  NV_OK on success, specific error code on failure.
317  */
318 static NV_STATUS
319 _kccuInitDevSharedBuffer
320 (
321     OBJGPU     *pGpu,
322     KernelCcu  *pKernelCcu
323 )
324 {
325     NV_STATUS status = NV_OK;
326 
327     NV_PRINTF(LEVEL_INFO, "Init shared buffer for device counters.\n");
328 
329     // Allocate shared buffer for device counters
330     status = _kccuAllocMemory(pGpu, pKernelCcu, CCU_DEV_SHRBUF_ID, CCU_GPU_SHARED_BUFFER_SIZE_MAX,
331                               CCU_PER_GPU_COUNTER_Q_SIZE);
332     if (status != NV_OK)
333     {
334         NV_PRINTF(LEVEL_ERROR, "CCU memory allocation failed with status: 0x%x\n", status);
335     }
336 
337     return status;
338 }
339 
340 /*!
341  * Create shared buffer for mig counters
342  *
343  * @param[in]      pGpu       GPU object pointer
344  * @param[in]      pKernelCcu KernelCcu object pointer
345  *
346  * @return  NV_OK on success, specific error code on failure.
347  */
348 NV_STATUS
349 kccuInitMigSharedBuffer_IMPL
350 (
351     OBJGPU     *pGpu,
352     KernelCcu  *pKernelCcu
353 )
354 {
355     NV_STATUS status = NV_OK;
356     NvU32 idx;
357 
358     NV_PRINTF(LEVEL_INFO, "Init shared buffer for mig counters.\n");
359 
360     // Allocate shared buffer for each mig gpu instance
361     for (idx = CCU_MIG_SHRBUF_ID_START; idx < CCU_SHRBUF_COUNT_MAX; idx++)
362     {
363         status = _kccuAllocMemory(pGpu, pKernelCcu, idx, CCU_MIG_INST_SHARED_BUFFER_SIZE_MAX,
364                 CCU_MIG_INST_COUNTER_Q_SIZE);
365         if (status != NV_OK)
366         {
367             NV_PRINTF(LEVEL_ERROR, "CCU memory allocation failed for idx(%u) with status: 0x%x\n",
368                     idx, status);
369 
370             // Free shared buffer & mem desc, for earlier mig inst & device
371             _kccuUnmapAndFreeMemory(pGpu, pKernelCcu);
372             break;
373         }
374 
375     }
376 
377     return status;
378 }
379 
380 /*!
381  * State Load
382  *
383  * @param[in]      pGpu       GPU object pointer
384  * @param[in]      pKernelCcu KernelCcu object pointer
385  * @param[in]      flags      Type of transition
386  *
387  * @return  NV_OK
388  * @return  NV_ERR_INVALID_STATE
389  */
390 NV_STATUS kccuStateLoad_IMPL
391 (
392     OBJGPU     *pGpu,
393     KernelCcu  *pKernelCcu,
394     NvU32      flags
395 )
396 {
397     NV_STATUS status = NV_OK;
398 
399     NV_PRINTF(LEVEL_INFO, "KernelCcu: State load \n");
400 
401     if (IS_VIRTUAL(pGpu))
402     {
403         return NV_ERR_NOT_SUPPORTED;
404     }
405 
406     // Create device shared buffer
407     status = _kccuInitDevSharedBuffer(pGpu, pKernelCcu);
408     if (status != NV_OK)
409     {
410         NV_PRINTF(LEVEL_ERROR, "Failed to init device shared buffer(status: %u) \n", status);
411         return status;
412     }
413 
414     // Create mig shared buffer
415     if (IS_MIG_ENABLED(pGpu))
416     {
417         status = kccuInitMigSharedBuffer(pGpu, pKernelCcu);
418         if (status != NV_OK)
419         {
420             NV_PRINTF(LEVEL_ERROR, "Failed to init mig shared buffer(status: %u) \n", status);
421             return status;
422         }
423         pKernelCcu->bMigShrBufAllocated = NV_TRUE;
424     }
425 
426     // Send shared buffer info to gsp
427     return (kccuShrBufInfoToCcu(pGpu, pKernelCcu, CCU_DEV_SHRBUF_ID));
428 }
429 
430 /*!
431  * State Unload
432  *
433  * @param[in]      pGpu       GPU object pointer
434  * @param[in]      pKernelCcu KernelCcu object pointer
435  * @param[in]      flags      Type of transition
436  *
437  * @return  NV_OK
438  * @return  NV_ERR_INVALID_STATE
439  */
440 NV_STATUS kccuStateUnload_IMPL
441 (
442     OBJGPU     *pGpu,
443     KernelCcu  *pKernelCcu,
444     NvU32      flags
445 )
446 {
447     NV_STATUS status = NV_OK;
448     NV_PRINTF(LEVEL_INFO, "KernelCcu: State unload \n");
449 
450     // Disable ccu stream state
451     pKernelCcu->bStreamState = CCU_STREAM_STATE_DISABLE;
452 
453     // Free shared buffer & mem desc
454     _kccuUnmapAndFreeMemory(pGpu, pKernelCcu);
455 
456     pKernelCcu->bMigShrBufAllocated = NV_FALSE;
457 
458     return status;
459 }
460 
461 /*!
462  * Get the shared buffer memory descriptor for buffer index
463  *
464  * @param[in]      pGpu                GPU object pointer
465  * @param[in]      pKernelCcu          KernelCcu object pointer
466  * @param[in]      idx                 Shared buffer index
467  * @param[out]     MEMORY_DESCRIPTOR   Location of pMemDesc
468  *
469  * @return  NV_OK
470  * @return  NV_ERR_INVALID_ARGUMENT
471  */
472 NV_STATUS kccuMemDescGetForShrBufId_IMPL
473 (
474     OBJGPU     *pGpu,
475     KernelCcu  *pKernelCcu,
476     NvU32       idx,
477     MEMORY_DESCRIPTOR **ppMemDesc
478 )
479 {
480     NV_PRINTF(LEVEL_INFO, "KernelCcu: Get memdesc for idx(%u) \n", idx);
481 
482     if (IS_VIRTUAL(pGpu))
483     {
484         return NV_ERR_NOT_SUPPORTED;
485     }
486 
487     if (idx >= CCU_SHRBUF_COUNT_MAX)
488     {
489         NV_PRINTF(LEVEL_ERROR, "CCU memdesc get failed for input idx(%u). Invalid index.\n",
490                   idx);
491 
492         return NV_ERR_INVALID_ARGUMENT;
493     }
494 
495     *ppMemDesc = pKernelCcu->pMemDesc[idx];
496 
497     return NV_OK;
498 }
499 
500 /*!
501  * Get the shared buffer memory descriptor for swizz id
502  *
503  * @param[in]      pGpu                GPU object pointer
504  * @param[in]      pKernelCcu          KernelCcu object pointer
505  * @param[in]      swizzId             Mig inst swizz-id
506  * @param[out]     MEMORY_DESCRIPTOR   Location of pMemDesc
507  *
508  * @return  NV_OK
509  * @return  NV_ERR_INVALID_ARGUMENT
510  */
511 NV_STATUS kccuMemDescGetForSwizzId_IMPL
512 (
513     OBJGPU     *pGpu,
514     KernelCcu  *pKernelCcu,
515     NvU8       swizzId,
516     MEMORY_DESCRIPTOR **ppMemDesc
517 )
518 {
519     NvU32 idx = 0;
520 
521     if (IS_VIRTUAL(pGpu))
522     {
523         return NV_ERR_NOT_SUPPORTED;
524     }
525 
526     for (idx = CCU_MIG_SHRBUF_ID_START; idx < CCU_SHRBUF_COUNT_MAX; idx++)
527     {
528         if (*pKernelCcu->shrBuf[idx].pCounterDstInfo->pSwizzId == swizzId)
529         {
530             *ppMemDesc = pKernelCcu->pMemDesc[idx];
531             break;
532         }
533     }
534 
535     if (idx >= CCU_SHRBUF_COUNT_MAX)
536     {
537         NV_PRINTF(LEVEL_ERROR, "KernelCcu: memdesc get failed for input swizzId(%u)\n",
538                 swizzId);
539 
540         return NV_ERR_INVALID_ARGUMENT;
541     }
542 
543     return NV_OK;
544 }
545 
546 /*!
547  * Get counter block size
548  *
549  * @param[in]      pGpu                GPU object pointer
550  * @param[in]      pKernelCcu          KernelCcu object pointer
551  * @param[in]      bDevCounter         Device counter
552  *
553  * @return  counter block size
554  */
555 NvU32 kccuCounterBlockSizeGet_IMPL
556 (
557     OBJGPU     *pGpu,
558     KernelCcu  *pKernelCcu,
559     NvBool     bDevCounter
560 )
561 {
562     NV_PRINTF(LEVEL_INFO, "KernelCcu: Get counter block size \n");
563     // For device counter block
564     if (bDevCounter)
565     {
566         return CCU_PER_GPU_COUNTER_Q_SIZE;
567     }
568 
569     return CCU_MIG_INST_COUNTER_Q_SIZE;
570 }
571 
572 /*!
573  * Set ccu stream state
574  *
575  * @param[in]      pGpu         GPU object pointer
576  * @param[in]      pKernelCcu   KernelCcu object pointer
577  * @param[in]      pParams      Ccu stream state param
578  *
579  * @return  NV_OK
580  * @return  NV_ERR_INVALID_ARGUMENT
581  */
582 NV_STATUS kccuStreamStateSet_IMPL
583 (
584     OBJGPU                                         *pGpu,
585     KernelCcu                                      *pKernelCcu,
586     NV_COUNTER_COLLECTION_UNIT_STREAM_STATE_PARAMS *pParams
587 )
588 {
589     NV_STATUS status = NV_OK;
590     NV2080_CTRL_INTERNAL_CCU_STREAM_STATE_PARAMS ccuParams = { 0 };
591 
592     NV_PRINTF(LEVEL_INFO, "KernelCcu: Set ccu stream \n");
593 
594     if (pParams == NULL || (pParams->bStreamState != CCU_STREAM_STATE_ENABLE &&
595                             pParams->bStreamState != CCU_STREAM_STATE_DISABLE))
596     {
597         NV_PRINTF(LEVEL_ERROR, "KernelCcu: Invalid input params\n");
598         return NV_ERR_INVALID_ARGUMENT;
599     }
600 
601     if (pKernelCcu->bStreamState == pParams->bStreamState)
602     {
603         NV_PRINTF(LEVEL_INFO, "KernelCcu: CCU stream state is already (%s)\n",
604                   pKernelCcu->bStreamState ? "ENABLED" : "DISABLED");
605         return NV_OK;
606     }
607 
608     ccuParams.bStreamState = pParams->bStreamState;
609 
610     // RM api ctrl call to physical RM to set ccu stream state
611     RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu);
612 
613     status = pRmApi->Control(pRmApi,
614                              pGpu->hInternalClient,
615                              pGpu->hInternalSubdevice,
616                              NV2080_CTRL_CMD_INTERNAL_CCU_SET_STREAM_STATE,
617                              &ccuParams,
618                              sizeof(ccuParams));
619     if (status != NV_OK)
620     {
621         NV_PRINTF(LEVEL_ERROR, "CCU stream state set failed with status: 0x%x\n", status);
622         return status;
623     }
624 
625     pKernelCcu->bStreamState = ccuParams.bStreamState;
626 
627     // Clear the shared buffer, when stream state is disabled
628     if (pKernelCcu->bStreamState == CCU_STREAM_STATE_DISABLE)
629     {
630         NvU32 i;
631         for (i = 0; i < CCU_SHRBUF_COUNT_MAX; i++)
632         {
633             MEMORY_DESCRIPTOR *pMemDesc = pKernelCcu->pMemDesc[i];
634 
635             if (pMemDesc == NULL)
636                 continue;
637 
638             portMemSet(pKernelCcu->shrBuf[i].pKernelMapInfo->addr, 0, memdescGetSize(pMemDesc));
639         }
640     }
641 
642     return NV_OK;
643 }
644 
645 /*!
646  * Get ccu stream state
647  *
648  * @param[in]      pGpu         GPU object pointer
649  * @param[in]      pKernelCcu   KernelCcu object pointer
650  *
651  * @return  CCU stream state
652  */
653 NvBool kccuStreamStateGet_IMPL
654 (
655     OBJGPU      *pGpu,
656     KernelCcu   *pKernelCcu
657 )
658 {
659     NV_PRINTF(LEVEL_INFO, "KernelCcu: Get ccu stream \n");
660 
661     return pKernelCcu->bStreamState;
662 }
663 
664 /*!
665  * Get the shared buffer memory descriptor for compute inst with
666  * swizz id and compute id
667  *
668  * @param[in]      pGpu                GPU object pointer
669  * @param[in]      pKernelCcu          KernelCcu object pointer
670  * @param[in]      swizzId             Mig inst swizz-id
671  * @param[in]      computeId           Compute inst id
672  * @param[out]     MEMORY_DESCRIPTOR   Location of pMemDesc
673  *
674  * @return  NV_OK
675  * @return  NV_ERR_NOT_SUPPORTED
676  * @return  NV_ERR_INVALID_ARGUMENT
677  */
678 NV_STATUS kccuMemDescGetForComputeInst_IMPL
679 (
680     OBJGPU     *pGpu,
681     KernelCcu  *pKernelCcu,
682     NvU8       swizzId,
683     NvU8       computeId,
684     MEMORY_DESCRIPTOR **ppMemDesc
685 )
686 {
687     NvU32 idx;
688 
689     if (IS_VIRTUAL(pGpu))
690     {
691         return NV_ERR_NOT_SUPPORTED;
692     }
693 
694     for (idx = CCU_MIG_SHRBUF_ID_START; idx < CCU_SHRBUF_COUNT_MAX; idx++)
695     {
696         if (*pKernelCcu->shrBuf[idx].pCounterDstInfo->pSwizzId == swizzId &&
697             *pKernelCcu->shrBuf[idx].pCounterDstInfo->pComputeId == computeId)
698         {
699             *ppMemDesc = pKernelCcu->pMemDesc[idx];
700             break;
701         }
702     }
703 
704     if (idx >= CCU_SHRBUF_COUNT_MAX)
705     {
706         NV_PRINTF(LEVEL_ERROR, "KernelCcu: memdesc get failed for input swizzId(%u), computeInst(%u)\n",
707                   swizzId, computeId);
708 
709         return NV_ERR_INVALID_ARGUMENT;
710     }
711 
712     return NV_OK;
713 }
714 
715