1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 2016-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3  * SPDX-License-Identifier: MIT
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 /*!
25  * @file   vaddr_list.c
26  * @brief  Virtual memory map tracking utility routines.
27  */
28 
29 #include "mem_mgr/vaddr_list.h"
30 
31 /*!
32  * @brief Permanently converts a VA_LIST_SIMPLE into a VA_LIST_DICT
33  */
34 NV_STATUS
vaListInitMap(VA_LIST * pVaList)35 vaListInitMap(VA_LIST *pVaList)
36 {
37     NV_STATUS status;
38     VADDR_LIST_INFO *pVaListInfo;
39     VA_INFO *pVaInfo;
40     struct VA_LIST_INLINE vaCache[2];
41 
42     NV_ASSERT_OR_RETURN(pVaList != NULL, NV_ERR_INVALID_ARGUMENT);
43 
44     // Save the data in the simple list
45     pVaListInfo = portMemAllocNonPaged(sizeof(*pVaListInfo));
46     if (pVaListInfo == NULL)
47     {
48         return NV_ERR_INSUFFICIENT_RESOURCES;
49     }
50     *pVaListInfo = pVaList->impl.simple.common;
51     vaCache[0] = pVaList->impl.simple.entries[0];
52     vaCache[1] = pVaList->impl.simple.entries[1];
53 
54     // Initialize the new map
55     portMemSet(pVaList, 0, sizeof(*pVaList));
56     mapInit(&pVaList->impl.map, portMemAllocatorGetGlobalNonPaged());
57 
58     // Insert the common info into the map
59     pVaInfo = mapInsertNew(&pVaList->impl.map, 0);
60     if (pVaInfo == NULL)
61     {
62         mapDestroy(&pVaList->impl.map);
63         portMemFree(pVaListInfo);
64         return NV_ERR_INSUFFICIENT_RESOURCES;
65     }
66 
67     pVaInfo->pVaListInfo = pVaListInfo;
68     pVaList->type = VA_LIST_DICT;
69 
70     // Safe to use vaListDestroy from this point
71 
72     // Add the cached va into the map
73     status = vaListAddVa(pVaList, vaCache[0].pVas, vaCache[0].vAddr);
74     if (status != NV_OK)
75     {
76         vaListDestroy(pVaList);
77         return status;
78     }
79 
80     // Add the cached va into the map
81     status = vaListAddVa(pVaList, vaCache[1].pVas, vaCache[1].vAddr);
82     if (status != NV_OK)
83     {
84         vaListDestroy(pVaList);
85         return status;
86     }
87 
88     // Update the refcount from the cache
89     pVaInfo = mapFind(&pVaList->impl.map, (NvU64)NV_PTR_TO_NvP64(vaCache[0].pVas));
90     if (pVaInfo == NULL)
91     {
92         vaListDestroy(pVaList);
93         return NV_ERR_INVALID_STATE;
94     }
95     pVaInfo->refCnt = vaCache[0].refCnt;
96 
97     // Update the refcount from the cache
98     pVaInfo = mapFind(&pVaList->impl.map, (NvU64)NV_PTR_TO_NvP64(vaCache[1].pVas));
99     if (pVaInfo == NULL)
100     {
101         vaListDestroy(pVaList);
102         return NV_ERR_INVALID_STATE;
103     }
104     pVaInfo->refCnt = vaCache[1].refCnt;
105 
106     return NV_OK;
107 }
108 
109 /*!
110  * @brief Return number of unique addresses in this map
111  */
112 NvU32
vaListMapCount(VA_LIST * pVaList)113 vaListMapCount(VA_LIST *pVaList)
114 {
115     NvU32 count;
116 
117     NV_ASSERT_OR_RETURN(pVaList != NULL, 0);
118 
119     count = 0;
120     switch (pVaList->type)
121     {
122         case VA_LIST_SIMPLE:
123         {
124             if (pVaList->impl.simple.entries[0].pVas != NULL)
125                 count++;
126 
127             if (pVaList->impl.simple.entries[1].pVas != NULL)
128                 count++;
129 
130             break;
131         }
132         case VA_LIST_DICT:
133         {
134             count += mapCount(&pVaList->impl.map);
135             // Account for the extra node
136             if (count > 0)
137                 count--;
138 
139             break;
140         }
141     }
142 
143     return count;
144 }
145 
146 /*!
147  * @brief Init map tracker object
148  *
149  * @param[in] pVaList   tracker object pointer
150  */
151 NV_STATUS
vaListInit(VA_LIST * pVaList)152 vaListInit(VA_LIST *pVaList)
153 {
154     NV_ASSERT_OR_RETURN(pVaList != NULL, NV_ERR_INVALID_ARGUMENT);
155 
156     portMemSet(pVaList, 0, sizeof(*pVaList));
157     pVaList->type = VA_LIST_SIMPLE;
158     pVaList->impl.simple.common.bRelease = NV_TRUE;
159     return NV_OK;
160 }
161 
162 /*!
163  * @brief Remove all mappings from the list
164  */
165 void
vaListClear(VA_LIST * pVaList)166 vaListClear(VA_LIST *pVaList)
167 {
168     NvBool bManaged = vaListGetManaged(pVaList);
169 
170     NV_ASSERT_OR_RETURN_VOID(pVaList != NULL);
171 
172     switch (pVaList->type)
173     {
174         case VA_LIST_SIMPLE:
175         {
176             break;
177         }
178         case VA_LIST_DICT:
179         {
180             VA_INFO *pVaInfo = mapFind(&pVaList->impl.map, 0);
181 
182             // Delete the dummy state node
183             if (pVaInfo != NULL)
184                 portMemFree(pVaInfo->pVaListInfo);
185 
186             // Remove all of the map nodes and delete the map
187             mapDestroy(&pVaList->impl.map);
188 
189             break;
190         }
191     }
192 
193     portMemSet(pVaList, 0, sizeof(*pVaList));
194     pVaList->type = VA_LIST_SIMPLE;
195     pVaList->impl.simple.common.bRelease = bManaged;
196 }
197 
198 /*!
199  * @brief Destroy map tracker object
200  */
201 void
vaListDestroy(VA_LIST * pVaList)202 vaListDestroy(VA_LIST *pVaList)
203 {
204     NV_ASSERT_OR_RETURN_VOID(pVaList != NULL);
205 
206     //
207     // Skip DBG_BREAKPOINT when we are in Physical RM.
208     // DBG_BREAKPOINT is the result of the lack of eviction of the context buffers from client RM.
209     //
210     if (vaListMapCount(pVaList) != 0)
211     {
212         NV_PRINTF(LEVEL_ERROR, "non-zero mapCount(pVaList): 0x%x\n",
213                   vaListMapCount(pVaList));
214 
215         DBG_BREAKPOINT();
216     }
217 
218     switch (pVaList->type)
219     {
220         case VA_LIST_SIMPLE:
221         {
222             portMemSet(pVaList, 0, sizeof(*pVaList));
223 
224             break;
225         }
226         case VA_LIST_DICT:
227         {
228             VA_INFO *pVaInfo = mapFind(&pVaList->impl.map, 0);
229             if (pVaInfo != NULL)
230             {
231                 NV_ASSERT(pVaInfo->vAddr  == 0);
232                 NV_ASSERT(pVaInfo->refCnt == 0);
233                 NV_ASSERT(pVaInfo->pVaListInfo);
234 
235                 portMemFree(pVaInfo->pVaListInfo);
236                 pVaInfo->pVaListInfo = NULL;
237 
238                 mapRemove(&pVaList->impl.map, pVaInfo);
239             }
240             else
241             {
242                 DBG_BREAKPOINT();
243             }
244 
245             mapDestroy(&pVaList->impl.map);
246 
247             break;
248         }
249     }
250 }
251 
252 /*!
253  * @brief Indicate that this list tracks addresses mapped by RM
254  *        The mode may only be changed when the list is empty.
255  *
256  * @param pVaList
257  * @param bManaged   NV_FALSE to indicate addresses not mapped by RM
258  *
259  * @return NV_ERR_INVALID_STATE if list is not empty and mode is changing
260  */
261 NV_STATUS
vaListSetManaged(VA_LIST * pVaList,NvBool bManaged)262 vaListSetManaged(VA_LIST *pVaList, NvBool bManaged)
263 {
264     NV_ASSERT_OR_RETURN(pVaList != NULL, NV_ERR_INVALID_ARGUMENT);
265 
266     // We can change the prop only when no active maps
267     NV_ASSERT_OR_RETURN((vaListMapCount(pVaList) == 0) ||
268                         (vaListGetManaged(pVaList) == bManaged),
269                         NV_ERR_INVALID_STATE);
270 
271     switch (pVaList->type)
272     {
273         case VA_LIST_SIMPLE:
274         {
275             pVaList->impl.simple.common.bRelease = bManaged;
276 
277             break;
278         }
279         case VA_LIST_DICT:
280         {
281             VA_INFO *pVaInfo = mapFind(&pVaList->impl.map, 0);
282 
283             NV_ASSERT_OR_RETURN(pVaInfo != NULL, NV_ERR_INVALID_STATE);
284 
285             pVaInfo->pVaListInfo->bRelease = bManaged;
286 
287             break;
288         }
289     }
290 
291     return NV_OK;
292 }
293 
294 /*!
295  * @brief returns NV_TRUE if the addresses tracked by this list are mapped by RM
296  */
297 NvBool
vaListGetManaged(VA_LIST * pVaList)298 vaListGetManaged(VA_LIST *pVaList)
299 {
300     NvBool bRelease = NV_TRUE;
301     NV_ASSERT_OR_RETURN(pVaList != NULL, NV_FALSE);
302 
303     switch (pVaList->type)
304     {
305         case VA_LIST_SIMPLE:
306         {
307             bRelease = pVaList->impl.simple.common.bRelease;
308 
309             break;
310         }
311         case VA_LIST_DICT:
312         {
313             VA_INFO *pVaInfo = mapFind(&pVaList->impl.map, 0);
314 
315             NV_ASSERT_OR_RETURN(pVaInfo != NULL, NV_FALSE);
316 
317             bRelease = pVaInfo->pVaListInfo->bRelease;
318 
319             break;
320         }
321     }
322 
323     return bRelease;
324 }
325 
326 /*!
327  * @brief Add a new VAS / vAddr pair to the list
328  *        If the pair already exists, increase its refcount
329  *
330  * @param pVaList
331  * @param pVas         OBJVASPACE this vaddr belongs to
332  * @param vAddr        Virtual address being tracked
333  */
334 NV_STATUS
vaListAddVa(VA_LIST * pVaList,OBJVASPACE * pVAS,NvU64 vAddr)335 vaListAddVa(VA_LIST *pVaList, OBJVASPACE *pVAS, NvU64 vAddr)
336 {
337     NV_STATUS status = NV_OK;
338     NV_ASSERT_OR_RETURN(pVaList != NULL, NV_ERR_INVALID_ARGUMENT);
339     NV_ASSERT_OR_RETURN(pVAS != NULL, NV_ERR_INVALID_ARGUMENT);
340 
341     switch (pVaList->type)
342     {
343         case VA_LIST_SIMPLE:
344         {
345             if (pVaList->impl.simple.entries[0].pVas == pVAS)
346             {
347                 NV_ASSERT_OR_RETURN(pVaList->impl.simple.entries[0].refCnt > 0, NV_ERR_INVALID_STATE);
348                 NV_ASSERT_OR_RETURN(pVaList->impl.simple.entries[0].refCnt < NV_U64_MAX, NV_ERR_INVALID_STATE);
349                 NV_ASSERT_OR_RETURN(pVaList->impl.simple.entries[0].vAddr == vAddr, NV_ERR_INVALID_STATE);
350                 pVaList->impl.simple.entries[0].refCnt++;
351 
352                 break;
353             }
354             else if (pVaList->impl.simple.entries[1].pVas == pVAS)
355             {
356                 NV_ASSERT_OR_RETURN(pVaList->impl.simple.entries[1].refCnt > 0, NV_ERR_INVALID_STATE);
357                 NV_ASSERT_OR_RETURN(pVaList->impl.simple.entries[1].refCnt < NV_U64_MAX, NV_ERR_INVALID_STATE);
358                 NV_ASSERT_OR_RETURN(pVaList->impl.simple.entries[1].vAddr == vAddr, NV_ERR_INVALID_STATE);
359                 pVaList->impl.simple.entries[1].refCnt++;
360 
361                 break;
362             }
363 
364             if (vaListMapCount(pVaList) == 2)
365             {
366                 // Convert the SIMPLE list into a MAP
367                 status = vaListInitMap(pVaList);
368                 if (status != NV_OK)
369                     return status;
370 
371                 return vaListAddVa(pVaList, pVAS, vAddr);
372             }
373 
374             if (pVaList->impl.simple.entries[0].pVas == NULL)
375             {
376                 pVaList->impl.simple.entries[0].pVas = pVAS;
377                 pVaList->impl.simple.entries[0].vAddr = vAddr;
378                 pVaList->impl.simple.entries[0].refCnt = 1;
379             }
380             else if (pVaList->impl.simple.entries[1].pVas == NULL)
381             {
382                 pVaList->impl.simple.entries[1].pVas = pVAS;
383                 pVaList->impl.simple.entries[1].vAddr = vAddr;
384                 pVaList->impl.simple.entries[1].refCnt = 1;
385             }
386             else
387             {
388                 // Should never be reached. Should've converted to map
389                 NV_ASSERT_FAILED("Simple va list full");
390                 return NV_ERR_INVALID_STATE;
391             }
392 
393             break;
394         }
395         case VA_LIST_DICT:
396         {
397             VA_INFO *pVaInfo = mapFind(&pVaList->impl.map, (NvU64)NV_PTR_TO_NvP64(pVAS));
398 
399             if (pVaInfo != NULL)
400             {
401                 NV_ASSERT_OR_RETURN(pVaInfo->refCnt > 0, NV_ERR_INVALID_STATE);
402                 NV_ASSERT_OR_RETURN(pVaInfo->refCnt < NV_U64_MAX, NV_ERR_INVALID_STATE);
403                 NV_ASSERT_OR_RETURN(pVaInfo->vAddr == vAddr, NV_ERR_INVALID_STATE);
404                 pVaInfo->refCnt++;
405             }
406             else
407             {
408                 pVaInfo = mapInsertNew(&pVaList->impl.map, (NvU64)NV_PTR_TO_NvP64(pVAS));
409                 NV_ASSERT_OR_RETURN(pVaInfo != NULL, NV_ERR_INSUFFICIENT_RESOURCES);
410                 pVaInfo->vAddr  = vAddr;
411                 pVaInfo->refCnt = 1;
412             }
413 
414             break;
415         }
416     }
417 
418     return status;
419 }
420 
421 /*!
422  * @brief Remove mapping associated with VAS from tracking
423  *
424  * @param pVaList
425  * @param pVAS      OBJVASPACE to remove
426  *
427  * @return NV_ERR_OBJECT_NOT_FOUND if VAS not in list
428  */
429 NV_STATUS
vaListRemoveVa(VA_LIST * pVaList,OBJVASPACE * pVAS)430 vaListRemoveVa(VA_LIST *pVaList, OBJVASPACE *pVAS)
431 {
432     NV_STATUS status = NV_OK;
433 
434     NV_ASSERT_OR_RETURN(pVaList != NULL, NV_ERR_INVALID_ARGUMENT);
435     NV_ASSERT_OR_RETURN(pVAS != NULL, NV_ERR_INVALID_ARGUMENT);
436 
437     switch (pVaList->type)
438     {
439         case VA_LIST_SIMPLE:
440         {
441             if (pVaList->impl.simple.entries[0].pVas == pVAS)
442             {
443                 NV_ASSERT_OR_RETURN(pVaList->impl.simple.entries[0].refCnt > 0, NV_ERR_INVALID_STATE);
444 
445                 pVaList->impl.simple.entries[0].refCnt--;
446                 if (pVaList->impl.simple.entries[0].refCnt == 0)
447                 {
448                     pVaList->impl.simple.entries[0].pVas = NULL;
449                     pVaList->impl.simple.entries[0].vAddr = 0;
450                 }
451             }
452             else if (pVaList->impl.simple.entries[1].pVas == pVAS)
453             {
454                 NV_ASSERT_OR_RETURN(pVaList->impl.simple.entries[1].refCnt > 0, NV_ERR_INVALID_STATE);
455 
456                 pVaList->impl.simple.entries[1].refCnt--;
457                 if (pVaList->impl.simple.entries[1].refCnt == 0)
458                 {
459                     pVaList->impl.simple.entries[1].pVas = NULL;
460                     pVaList->impl.simple.entries[1].vAddr = 0;
461                 }
462             }
463             else
464             {
465                 status = NV_ERR_OBJECT_NOT_FOUND;
466             }
467 
468             break;
469         }
470         case VA_LIST_DICT:
471         {
472             VA_INFO *pVaInfo = mapFind(&pVaList->impl.map, (NvU64)NV_PTR_TO_NvP64(pVAS));
473             if (pVaInfo != NULL)
474             {
475                 NV_ASSERT_OR_RETURN(pVaInfo->refCnt > 0, NV_ERR_INVALID_STATE);
476 
477                 pVaInfo->refCnt--;
478 
479                 if (pVaInfo->refCnt == 0)
480                 {
481                     mapRemove(&pVaList->impl.map, pVaInfo);
482                 }
483             }
484             else
485             {
486                 status = NV_ERR_OBJECT_NOT_FOUND;
487             }
488 
489             break;
490         }
491     }
492 
493     return status;
494 }
495 
496 /*!
497  * @brief Find virtual address associated with given OBJVASPACE
498  *
499  * @param pVaList
500  * @param pVAS      OBJVASPACE to remove
501  * @param pVaddr    address associated with VAS
502  *
503  * @return NV_ERR_OBJECT_NOT_FOUND if VAS not in list
504  */
505 NV_STATUS
vaListFindVa(VA_LIST * pVaList,OBJVASPACE * pVAS,NvU64 * pVaddr)506 vaListFindVa(VA_LIST *pVaList, OBJVASPACE *pVAS, NvU64 *pVaddr)
507 {
508     NV_STATUS status = NV_OK;
509 
510     NV_ASSERT_OR_RETURN(pVaList != NULL, NV_ERR_INVALID_ARGUMENT);
511     NV_ASSERT_OR_RETURN(pVAS != NULL, NV_ERR_INVALID_ARGUMENT);
512     NV_ASSERT_OR_RETURN(pVaddr != NULL, NV_ERR_INVALID_ARGUMENT);
513 
514     switch (pVaList->type)
515     {
516         case VA_LIST_SIMPLE:
517         {
518             if (pVaList->impl.simple.entries[0].pVas == pVAS)
519             {
520                 NV_ASSERT_OR_RETURN(pVaList->impl.simple.entries[0].refCnt > 0, NV_ERR_INVALID_STATE);
521                 *pVaddr = pVaList->impl.simple.entries[0].vAddr;
522             }
523             else if (pVaList->impl.simple.entries[1].pVas == pVAS)
524             {
525                 NV_ASSERT_OR_RETURN(pVaList->impl.simple.entries[1].refCnt > 0, NV_ERR_INVALID_STATE);
526                 *pVaddr = pVaList->impl.simple.entries[1].vAddr;
527             }
528             else
529             {
530                 status = NV_ERR_OBJECT_NOT_FOUND;
531             }
532 
533             break;
534         }
535         case VA_LIST_DICT:
536         {
537             VA_INFO *pVaInfo = mapFind(&pVaList->impl.map, (NvU64)NV_PTR_TO_NvP64(pVAS));
538             if (pVaInfo != NULL)
539             {
540                 NV_ASSERT_OR_RETURN(pVaInfo->refCnt > 0, NV_ERR_INVALID_STATE);
541                 *pVaddr = pVaInfo->vAddr;
542             }
543             else
544             {
545                 status = NV_ERR_OBJECT_NOT_FOUND;
546             }
547 
548             break;
549         }
550     }
551 
552     return status;
553 }
554 
555 /*!
556  * @brief Get refcount of OBJVASPACE in list
557  *
558  * @param pVaList
559  * @param pVAS      OBJVASPACE to check
560  * @param pRefCount refcount associated with VAS
561  *
562  * @return NV_ERR_OBJECT_NOT_FOUND if VAS not in list
563  */
564 NV_STATUS
vaListGetRefCount(VA_LIST * pVaList,OBJVASPACE * pVAS,NvU64 * pRefCount)565 vaListGetRefCount(VA_LIST *pVaList, OBJVASPACE *pVAS, NvU64 *pRefCount)
566 {
567     NV_STATUS status = NV_OK;
568 
569     NV_ASSERT_OR_RETURN(pVaList != NULL, NV_ERR_INVALID_ARGUMENT);
570     NV_ASSERT_OR_RETURN(pVAS != NULL, NV_ERR_INVALID_ARGUMENT);
571     NV_ASSERT_OR_RETURN(pRefCount != NULL, NV_ERR_INVALID_ARGUMENT);
572 
573     switch (pVaList->type)
574     {
575         case VA_LIST_SIMPLE:
576         {
577             if (pVaList->impl.simple.entries[0].pVas == pVAS)
578             {
579                 NV_ASSERT_OR_RETURN(pVaList->impl.simple.entries[0].refCnt > 0, NV_ERR_INVALID_STATE);
580                 *pRefCount = pVaList->impl.simple.entries[0].refCnt;
581             }
582             else if (pVaList->impl.simple.entries[1].pVas == pVAS)
583             {
584                 NV_ASSERT_OR_RETURN(pVaList->impl.simple.entries[1].refCnt > 0, NV_ERR_INVALID_STATE);
585                 *pRefCount = pVaList->impl.simple.entries[1].refCnt;
586             }
587             else
588             {
589                 status = NV_ERR_OBJECT_NOT_FOUND;
590             }
591 
592             break;
593         }
594         case VA_LIST_DICT:
595         {
596             VA_INFO *pVaInfo = mapFind(&pVaList->impl.map, (NvU64)NV_PTR_TO_NvP64(pVAS));
597             if (pVaInfo != NULL)
598             {
599                 NV_ASSERT_OR_RETURN(pVaInfo->refCnt > 0, NV_ERR_INVALID_STATE);
600                 *pRefCount = pVaInfo->refCnt;
601             }
602             else
603             {
604                 status = NV_ERR_OBJECT_NOT_FOUND;
605             }
606 
607             break;
608         }
609     }
610 
611     return status;
612 }
613 
614 /*!
615  * @brief Set refcount of OBJVASPACE in list
616  *
617  * @param pVaList
618  * @param pVAS      OBJVASPACE to check
619  * @param refCount  refcount associated with VAS
620  *
621  * @return NV_ERR_OBJECT_NOT_FOUND if VAS not in list
622  */
623 NV_STATUS
vaListSetRefCount(VA_LIST * pVaList,OBJVASPACE * pVAS,NvU64 refCount)624 vaListSetRefCount(VA_LIST *pVaList, OBJVASPACE *pVAS, NvU64 refCount)
625 {
626     NV_STATUS status = NV_OK;
627 
628     NV_ASSERT_OR_RETURN(pVaList != NULL, NV_ERR_INVALID_ARGUMENT);
629     NV_ASSERT_OR_RETURN(pVAS != NULL, NV_ERR_INVALID_ARGUMENT);
630     NV_ASSERT_OR_RETURN(refCount != 0, NV_ERR_INVALID_ARGUMENT);
631 
632     switch (pVaList->type)
633     {
634         case VA_LIST_SIMPLE:
635         {
636             if (pVaList->impl.simple.entries[0].pVas == pVAS)
637             {
638                 pVaList->impl.simple.entries[0].refCnt = refCount;
639             }
640             else if (pVaList->impl.simple.entries[1].pVas == pVAS)
641             {
642                 pVaList->impl.simple.entries[1].refCnt = refCount;
643             }
644             else
645             {
646                 status = NV_ERR_OBJECT_NOT_FOUND;
647             }
648 
649             break;
650         }
651         case VA_LIST_DICT:
652         {
653             VA_INFO *pVaInfo = mapFind(&pVaList->impl.map, (NvU64)NV_PTR_TO_NvP64(pVAS));
654             if (pVaInfo != NULL)
655             {
656                 pVaInfo->refCnt = refCount;
657             }
658             else
659             {
660                 status = NV_ERR_OBJECT_NOT_FOUND;
661             }
662 
663             break;
664         }
665     }
666 
667     return status;
668 }
669 
670