Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(108)

Side by Side Diff: arch/arm/mach-tegra/nv/nvreftrack/nvreftrack.c

Issue 3256004: [ARM] tegra: add nvos/nvrm/nvmap drivers (Closed) Base URL: ssh://git@gitrw.chromium.org/kernel.git
Patch Set: remove ap15 headers Created 10 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « arch/arm/mach-tegra/nv/nvreftrack/Makefile ('k') | arch/arm/mach-tegra/nv/nvrm/Makefile » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2009 NVIDIA Corporation.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * Neither the name of the NVIDIA Corporation nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 */
32
33 #include "nvreftrack.h"
34 #include "nvos.h"
35 #include "nvassert.h"
36
37 #define NVRT_MAX_PACKAGES 8
38 #define NVRT_MAX_OBJ_TYPES_PER_PACKAGE 8
39 #define NVRT_CLIENT_SIZE_INCR 16
40 #define NVRT_OBJ_SIZE_INCR 128
41
42 typedef struct
43 {
44 // linked list next ptr (live and free objects)
45 NvU32 NextObj;
46 // the opaque ptr identifier of the object
47 void* Ptr;
48 } NvRtObj;
49
50 typedef struct
51 {
52 union
53 {
54 // linked list next ptr for free list, -1 == none
55 NvU32 NextFree;
56 // in use client refcount, -1 == cleaning up
57 NvS32 RefCount;
58 } State;
59
60 void* UserData;
61
62 // lists of objects per obj type. array size can't
63 // be determined compile time so this is not declared
64 //NvU32 Objs[];
65 } NvRtClient;
66
67 typedef struct NvRtRec
68 {
69 NvOsMutexHandle Mutex;
70
71 NvU32 NumPackages;
72 NvU32 MaxTypesPerPkg;
73 NvU32* ObjTypeIdxLUT;
74 NvU32 NumObjTypes;
75
76 NvU8* ClientArr;
77 NvU32 ClientArrSize;
78 NvU32 FreeClientList;
79
80 NvRtObj* ObjArr;
81 NvU32 ObjArrSize;
82 NvU32 FreeObjList;
83 } NvRt;
84
85 static NV_INLINE NvU32
86 NvRtClientSize(NvRt* Rt)
87 {
88 return sizeof(NvRtClient) + Rt->NumObjTypes*sizeof(NvU32);
89 }
90
91 static NV_INLINE NvRtClient*
92 GetClient(NvRt* Rt, NvU32 Idx)
93 {
94 void* ptr = (void*)(Rt->ClientArr + Idx*NvRtClientSize(Rt));
95 return (NvRtClient*)ptr;
96 }
97
98 static NV_INLINE NvU32
99 GetObjTypeIdx(NvRt* Rt, NvU32 Package, NvU32 Type)
100 {
101 NvU32 LutIdx = Package*Rt->MaxTypesPerPkg + Type;
102 NvU32 Idx;
103
104 Idx = Rt->ObjTypeIdxLUT[LutIdx];
105 NV_ASSERT(Idx != (NvU32)-1);
106
107 return Idx;
108 }
109
110 static NV_INLINE NvU32*
111 GetObjListHead(NvRt* Rt, NvU32 ClientIdx, NvU32 ObjIdx)
112 {
113 NvRtClient* Client = GetClient(Rt, ClientIdx);
114 NvU32* Objs = (NvU32*)(Client + 1);
115 return Objs + ObjIdx;
116 }
117
118 // Temporary wrapper for realloc as the linux kernel nvos doesn't
119 // implement NvOsRealloc
120 static NV_INLINE void*
121 NvRtRealloc(void* old, size_t size, size_t oldsize)
122 {
123 #if NVOS_IS_LINUX_KERNEL
124 void* ret;
125
126 if (!size)
127 {
128 if (old) NvOsFree(old);
129 return NULL;
130 }
131
132 ret = NvOsAlloc(size);
133
134 if (ret && old)
135 {
136 NV_ASSERT(oldsize > 0);
137
138 NvOsMemcpy(ret, old, NV_MIN(size, oldsize));
139 NvOsFree(old);
140 }
141
142 return ret;
143 #else
144 return NvOsRealloc(old, size);
145 #endif
146 }
147
148 NvError NvRtCreate(
149 NvU32 NumPackages,
150 const NvU32* NumObjTypesPerPackage,
151 NvRtHandle* RtOut)
152 {
153 NvRtHandle Ctx;
154 NvU32 i;
155
156 if (NumPackages == 0)
157 {
158 NV_ASSERT(!"Zero packages is not allowed");
159 return NvError_BadParameter;
160 }
161
162 if (NumPackages > NVRT_MAX_PACKAGES)
163 {
164 NV_ASSERT(!"NumPackages exceeds NVRT_MAX_PACKAGES");
165 return NvError_BadParameter;
166 }
167
168 Ctx = NvOsAlloc(sizeof(NvRt));
169 if (!Ctx) return NvError_InsufficientMemory;
170 NvOsMemset(Ctx, 0, sizeof(NvRt));
171
172 Ctx->FreeClientList = -1;
173 Ctx->FreeObjList = -1;
174 Ctx->NumPackages = NumPackages;
175
176 for (i = 0; i < NumPackages; i++)
177 {
178 if (NumObjTypesPerPackage[i] >
179 NVRT_MAX_OBJ_TYPES_PER_PACKAGE)
180 {
181 NV_ASSERT(!"Too many object types");
182 NvOsFree(Ctx);
183 return NvError_BadParameter;
184 }
185
186 Ctx->NumObjTypes += NumObjTypesPerPackage[i];
187
188 if (NumObjTypesPerPackage[i] > Ctx->MaxTypesPerPkg)
189 Ctx->MaxTypesPerPkg = NumObjTypesPerPackage[i];
190 }
191
192 if (Ctx->MaxTypesPerPkg)
193 {
194 NvU32 idx = 0;
195
196 Ctx->ObjTypeIdxLUT = NvOsAlloc(sizeof(NvU32)*Ctx->MaxTypesPerPkg*NumPack ages);
197 if (!Ctx->ObjTypeIdxLUT)
198 {
199 NvOsFree(Ctx);
200 return NvError_InsufficientMemory;
201 }
202
203 for (i = 0; i < NumPackages; i++)
204 {
205 NvU32 start = i*Ctx->MaxTypesPerPkg;
206 NvU32 j = 0;
207
208 for (; j < NumObjTypesPerPackage[i]; j++)
209 {
210 Ctx->ObjTypeIdxLUT[start+j] = idx++;
211 }
212 for (; j < Ctx->MaxTypesPerPkg; j++)
213 {
214 Ctx->ObjTypeIdxLUT[start+j] = (NvU32)-1;
215 }
216 }
217 }
218
219 if (NvOsMutexCreate(&Ctx->Mutex) != NvSuccess)
220 {
221 NvOsFree(Ctx->ObjTypeIdxLUT);
222 NvOsFree(Ctx);
223 return NvError_InsufficientMemory;
224 }
225
226 *RtOut = Ctx;
227 return NvSuccess;
228 }
229
230 void NvRtDestroy(NvRtHandle Rt)
231 {
232 NvOsMutexDestroy(Rt->Mutex);
233 NvOsFree(Rt->ObjTypeIdxLUT);
234 NvOsFree(Rt);
235 }
236
237 NvError NvRtRegisterClient(
238 NvRtHandle Rt,
239 NvRtClientHandle* ClientOut)
240 {
241 NvOsMutexLock(Rt->Mutex);
242
243 // Allocate new clients if necessary
244
245 if (Rt->FreeClientList == -1)
246 {
247 NvU8* NewArr;
248 NvU32 NewSize;
249 NvU32 i;
250
251 // Grow array by increment
252
253 NewSize = Rt->ClientArrSize + NVRT_CLIENT_SIZE_INCR;
254 NewArr = NvRtRealloc(Rt->ClientArr,
255 NvRtClientSize(Rt)*NewSize,
256 NvRtClientSize(Rt)*Rt->ClientArrSize);
257 if (NewArr == NULL)
258 {
259 NvOsMutexUnlock(Rt->Mutex);
260 return NvError_InsufficientMemory;
261 }
262 Rt->ClientArr = NewArr;
263
264 // Initialize new clients and create free list
265
266 for (i = Rt->ClientArrSize; i < NewSize; i++)
267 {
268 NvRtClient* c = GetClient(Rt, i);
269 NvU32* objs = (NvU32*)(c+1);
270 NvU32 j;
271
272 c->State.NextFree = (i == NewSize-1) ? -1 : i+1;
273
274 for (j = 0; j < Rt->NumObjTypes; j++)
275 objs[j] = -1;
276 }
277
278 Rt->FreeClientList = Rt->ClientArrSize;
279 Rt->ClientArrSize = NewSize;
280 }
281
282 NV_ASSERT(Rt->FreeClientList != -1);
283
284 {
285 NvU32 ClientIdx = Rt->FreeClientList;
286 NvRtClient* Client = GetClient(Rt, ClientIdx);
287
288 Rt->FreeClientList = Client->State.NextFree;
289
290 NvOsMutexUnlock(Rt->Mutex);
291
292 // Initialize client
293
294 Client->State.RefCount = 1;
295 Client->UserData = NULL;
296
297 *ClientOut = ClientIdx + 1;
298 }
299
300 return NvSuccess;
301 }
302
303 NvError NvRtAddClientRef(
304 NvRtHandle Rt,
305 NvRtClientHandle ClientHandle)
306 {
307 NvRtClient* Client;
308 NvU32 ClientIdx = ClientHandle - 1;
309 NvError Ret = NvSuccess;
310
311 NV_ASSERT(ClientHandle != 0);
312 NV_ASSERT(ClientHandle <= Rt->ClientArrSize);
313
314 NvOsMutexLock(Rt->Mutex);
315
316 Client = GetClient(Rt, ClientIdx);
317
318 if (Client->State.RefCount < 1)
319 Ret = NvError_InvalidState;
320 else
321 Client->State.RefCount++;
322
323 NvOsMutexUnlock(Rt->Mutex);
324
325 return Ret;
326 }
327
328 NvBool NvRtUnregisterClient(
329 NvRtHandle Rt,
330 NvRtClientHandle ClientHandle)
331 {
332 NvRtClient* Client;
333 NvU32 ClientIdx = ClientHandle - 1;
334 NvU32* Objs;
335 NvU32 i;
336
337 NV_ASSERT(ClientHandle != 0);
338 NV_ASSERT(ClientHandle <= Rt->ClientArrSize);
339
340 NvOsMutexLock(Rt->Mutex);
341
342 Client = GetClient(Rt, ClientIdx);
343 Client->State.RefCount--;
344
345 if (Client->State.RefCount >= 0)
346 {
347 NvBool DoClean = (Client->State.RefCount == 0);
348 NvOsMutexUnlock(Rt->Mutex);
349 return DoClean;
350 }
351
352 Objs = (NvU32*)(Client+1);
353
354 // Check that object references are free'd
355
356 for (i = Rt->NumObjTypes; i != 0; i--)
357 {
358 NvU32 Idx = i - 1;
359 NvU32 Cur = Objs[Idx];
360
361 // The caller should free all object referenced before
362 // unregistering. Assert that this is so.
363
364 NV_ASSERT(Cur == -1 || !"Leaked object reference");
365
366 // In release builds free at least our state for the leaked
367 // objects. There's nothing we can do about the leaked objects.
368
369 while (Cur != -1)
370 {
371 NvRtObj* Obj = &Rt->ObjArr[Cur];
372 NvU32 Next = Obj->NextObj;
373
374 Obj->NextObj = Rt->FreeObjList;
375 Rt->FreeObjList = Cur;
376 Cur = Next;
377 }
378
379 Objs[Idx] = -1;
380 }
381
382 // Release client
383
384 Client->State.NextFree = Rt->FreeClientList;
385 Rt->FreeClientList = ClientIdx;
386
387 NvOsMutexUnlock(Rt->Mutex);
388
389 return NV_FALSE;
390 }
391
392 void NvRtSetClientUserData(
393 NvRtHandle Rt,
394 NvRtClientHandle ClientHandle,
395 void* UserData)
396 {
397 NvRtClient* Client;
398 NvU32 ClientIdx = ClientHandle - 1;
399
400 NV_ASSERT(ClientHandle != 0);
401 NV_ASSERT(ClientHandle <= Rt->ClientArrSize);
402
403 NvOsMutexLock(Rt->Mutex);
404
405 Client = GetClient(Rt, ClientIdx);
406 Client->UserData = UserData;
407
408 NvOsMutexUnlock(Rt->Mutex);
409 }
410
411 void* NvRtGetClientUserData(
412 NvRtHandle Rt,
413 NvRtClientHandle ClientHandle)
414 {
415 NvRtClient* Client;
416 NvU32 ClientIdx = ClientHandle - 1;
417 void* UserData;
418
419 NV_ASSERT(ClientHandle != 0);
420 NV_ASSERT(ClientHandle <= Rt->ClientArrSize);
421
422 NvOsMutexLock(Rt->Mutex);
423
424 Client = GetClient(Rt, ClientIdx);
425 UserData = Client->UserData;
426
427 NvOsMutexUnlock(Rt->Mutex);
428
429 return UserData;
430 }
431
432 NvError NvRtAllocObjRef(
433 const NvDispatchCtx* Ctx,
434 NvRtObjRefHandle* Out)
435 {
436 NvRt* Rt = Ctx->Rt;
437 NvU32 ObjIdx;
438 NvRtObj* Obj;
439
440 NvOsMutexLock(Rt->Mutex);
441
442 // Allocate new space if necessary
443
444 if (Rt->FreeObjList == -1)
445 {
446 NvRtObj* NewArr;
447 NvRtObj* Cur;
448 NvU32 NewSize;
449 NvU32 i;
450
451 // Grow array by increment
452
453 NewSize = Rt->ObjArrSize + NVRT_OBJ_SIZE_INCR;
454 NewArr = NvRtRealloc(Rt->ObjArr,
455 sizeof(NvRtObj)*NewSize,
456 sizeof(NvRtObj)*Rt->ObjArrSize);
457 if (NewArr == NULL)
458 {
459 NvOsMutexUnlock(Rt->Mutex);
460 return NvError_InsufficientMemory;
461 }
462
463 // Create free list
464
465 Cur = NewArr + Rt->ObjArrSize;
466 for (i = Rt->ObjArrSize + 1; i < NewSize; i++)
467 {
468 Cur->NextObj = i;
469 Cur++;
470 }
471 Cur->NextObj = -1;
472
473 // Store new values
474
475 Rt->ObjArr = NewArr;
476 Rt->FreeObjList = Rt->ObjArrSize;
477 Rt->ObjArrSize = NewSize;
478 }
479
480 NV_ASSERT(Rt->FreeObjList != -1);
481
482 ObjIdx = Rt->FreeObjList;
483 Obj = &Rt->ObjArr[ObjIdx];
484 Rt->FreeObjList = Obj->NextObj;
485
486 Obj->NextObj = -1;
487 Obj->Ptr = NULL;
488
489 NvOsMutexUnlock(Rt->Mutex);
490
491 *Out = ObjIdx + 1;
492 return NvSuccess;
493 }
494
495 void NvRtDiscardObjRef(
496 const NvDispatchCtx* Ctx,
497 NvRtObjRefHandle ObjRef)
498 {
499 NvRt* Rt = Ctx->Rt;
500 NvRtObj* Obj;
501
502 if (!ObjRef--) return;
503
504 NvOsMutexLock(Rt->Mutex);
505
506 Obj = &Rt->ObjArr[ObjRef];
507
508 NV_ASSERT(Obj->NextObj == -1);
509 NV_ASSERT(Obj->Ptr == NULL);
510
511 Obj->NextObj = Rt->FreeObjList;
512 Rt->FreeObjList = ObjRef;
513
514 NvOsMutexUnlock(Rt->Mutex);
515 }
516
517 void NvRtStoreObjRef(
518 const NvDispatchCtx* Ctx,
519 NvRtObjRefHandle ObjRef,
520 NvU32 ObjType,
521 void* ObjPtr)
522 {
523 NvRt* Rt = Ctx->Rt;
524 NvU32 ClientIdx = Ctx->Client - 1;
525 NvU32 ObjTypeIdx = GetObjTypeIdx(Rt, Ctx->PackageIdx, ObjType);
526 NvRtObj* Obj;
527 NvU32* List;
528
529 NV_ASSERT(ClientIdx < Rt->ClientArrSize);
530
531 if (ObjPtr == NULL)
532 {
533 NV_ASSERT(!"Bad object ptr");
534 return;
535 }
536
537 if (!ObjRef--)
538 {
539 NV_ASSERT(!"Bad object ref handle");
540 return;
541 }
542
543 NvOsMutexLock(Rt->Mutex);
544
545 Obj = &Rt->ObjArr[ObjRef];
546
547 NV_ASSERT(Obj->NextObj == -1);
548 NV_ASSERT(Obj->Ptr == NULL);
549
550 List = GetObjListHead(Rt, ClientIdx, ObjTypeIdx);
551
552 Obj->NextObj = *List;
553 Obj->Ptr = ObjPtr;
554
555 *List = ObjRef;
556
557 NvOsMutexUnlock(Rt->Mutex);
558 }
559
560 void* NvRtFreeObjRef(
561 const NvDispatchCtx* Ctx,
562 NvU32 ObjType,
563 void* ObjPtr)
564 {
565 NvRt* Rt = Ctx->Rt;
566 NvU32 ClientIdx = Ctx->Client - 1;
567 NvU32 ObjTypeIdx = GetObjTypeIdx(Rt, Ctx->PackageIdx, ObjType);
568 NvU32 PrevIdx;
569 NvU32 CurIdx;
570 NvU32* List;
571 void* RetVal = NULL;
572
573 NV_ASSERT(ClientIdx < Rt->ClientArrSize);
574
575 NvOsMutexLock(Rt->Mutex);
576
577 List = GetObjListHead(Rt, ClientIdx, ObjTypeIdx);
578 CurIdx = *List;
579 PrevIdx = -1;
580
581 // If user requested to find a specific object look it up
582
583 if (ObjPtr != NULL)
584 {
585 while (CurIdx != -1)
586 {
587 NvRtObj* Obj = &Rt->ObjArr[CurIdx];
588
589 if (Obj->Ptr == ObjPtr) break;
590
591 PrevIdx = CurIdx;
592 CurIdx = Obj->NextObj;
593 }
594
595 // User should not ask to free non-existent objects
596
597 if (CurIdx == -1)
598 {
599 NV_ASSERT(!"Trying to free non-existent object reference");
600 NvOsMutexUnlock(Rt->Mutex);
601 return NULL;
602 }
603 }
604
605 // If we have an object, free it
606
607 if (CurIdx != -1)
608 {
609 NvRtObj* Obj = &Rt->ObjArr[CurIdx];
610
611 RetVal = Obj->Ptr;
612
613 if (PrevIdx == -1)
614 {
615 *List = Obj->NextObj;
616 }
617 else
618 {
619 NvRtObj* PrevObj = &Rt->ObjArr[PrevIdx];
620 PrevObj->NextObj = Obj->NextObj;
621 }
622
623 Obj->Ptr = NULL;
624 Obj->NextObj = Rt->FreeObjList;
625 Rt->FreeObjList = CurIdx;
626 }
627
628 NvOsMutexUnlock(Rt->Mutex);
629
630 return RetVal;
631 }
632
633 #include <linux/module.h>
634
635 EXPORT_SYMBOL(NvRtAllocObjRef);
636 EXPORT_SYMBOL(NvRtDiscardObjRef);
637 EXPORT_SYMBOL(NvRtFreeObjRef);
638 EXPORT_SYMBOL(NvRtStoreObjRef);
639
640 EXPORT_SYMBOL(NvRtCreate);
641 EXPORT_SYMBOL(NvRtDestroy);
642 EXPORT_SYMBOL(NvRtRegisterClient);
643 EXPORT_SYMBOL(NvRtUnregisterClient);
OLDNEW
« no previous file with comments | « arch/arm/mach-tegra/nv/nvreftrack/Makefile ('k') | arch/arm/mach-tegra/nv/nvrm/Makefile » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698