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