diff options
Diffstat (limited to 'drivers/gpu/pvr/ra.c')
-rw-r--r-- | drivers/gpu/pvr/ra.c | 1725 |
1 files changed, 1725 insertions, 0 deletions
diff --git a/drivers/gpu/pvr/ra.c b/drivers/gpu/pvr/ra.c new file mode 100644 index 00000000000..191be844004 --- /dev/null +++ b/drivers/gpu/pvr/ra.c | |||
@@ -0,0 +1,1725 @@ | |||
1 | /********************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful but, except | ||
10 | * as otherwise stated in writing, without any warranty; without even the | ||
11 | * implied warranty of merchantability or fitness for a particular purpose. | ||
12 | * See the GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in | ||
19 | * the file called "COPYING". | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * Imagination Technologies Ltd. <gpl-support@imgtec.com> | ||
23 | * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK | ||
24 | * | ||
25 | ******************************************************************************/ | ||
26 | |||
27 | #include "services_headers.h" | ||
28 | #include "hash.h" | ||
29 | #include "ra.h" | ||
30 | #include "buffer_manager.h" | ||
31 | #include "osfunc.h" | ||
32 | |||
33 | #ifdef __linux__ | ||
34 | #include <linux/kernel.h> | ||
35 | #include "proc.h" | ||
36 | #endif | ||
37 | |||
38 | #ifdef USE_BM_FREESPACE_CHECK | ||
39 | #include <stdio.h> | ||
40 | #endif | ||
41 | |||
42 | #define MINIMUM_HASH_SIZE (64) | ||
43 | |||
44 | #if defined(VALIDATE_ARENA_TEST) | ||
45 | |||
46 | typedef enum RESOURCE_DESCRIPTOR_TAG { | ||
47 | |||
48 | RESOURCE_SPAN_LIVE = 10, | ||
49 | RESOURCE_SPAN_FREE, | ||
50 | IMPORTED_RESOURCE_SPAN_START, | ||
51 | IMPORTED_RESOURCE_SPAN_LIVE, | ||
52 | IMPORTED_RESOURCE_SPAN_FREE, | ||
53 | IMPORTED_RESOURCE_SPAN_END, | ||
54 | |||
55 | } RESOURCE_DESCRIPTOR; | ||
56 | |||
57 | typedef enum RESOURCE_TYPE_TAG { | ||
58 | |||
59 | IMPORTED_RESOURCE_TYPE = 20, | ||
60 | NON_IMPORTED_RESOURCE_TYPE | ||
61 | |||
62 | } RESOURCE_TYPE; | ||
63 | |||
64 | |||
65 | static IMG_UINT32 ui32BoundaryTagID = 0; | ||
66 | |||
67 | IMG_UINT32 ValidateArena(RA_ARENA *pArena); | ||
68 | #endif | ||
69 | |||
70 | struct _BT_ | ||
71 | { | ||
72 | enum bt_type | ||
73 | { | ||
74 | btt_span, | ||
75 | btt_free, | ||
76 | btt_live | ||
77 | } type; | ||
78 | |||
79 | |||
80 | IMG_UINTPTR_T base; | ||
81 | IMG_SIZE_T uSize; | ||
82 | |||
83 | |||
84 | struct _BT_ *pNextSegment; | ||
85 | struct _BT_ *pPrevSegment; | ||
86 | |||
87 | struct _BT_ *pNextFree; | ||
88 | struct _BT_ *pPrevFree; | ||
89 | |||
90 | BM_MAPPING *psMapping; | ||
91 | |||
92 | #if defined(VALIDATE_ARENA_TEST) | ||
93 | RESOURCE_DESCRIPTOR eResourceSpan; | ||
94 | RESOURCE_TYPE eResourceType; | ||
95 | |||
96 | |||
97 | IMG_UINT32 ui32BoundaryTagID; | ||
98 | #endif | ||
99 | |||
100 | }; | ||
101 | typedef struct _BT_ BT; | ||
102 | |||
103 | |||
104 | struct _RA_ARENA_ | ||
105 | { | ||
106 | |||
107 | IMG_CHAR *name; | ||
108 | |||
109 | |||
110 | IMG_SIZE_T uQuantum; | ||
111 | |||
112 | |||
113 | IMG_BOOL (*pImportAlloc)(IMG_VOID *, | ||
114 | IMG_SIZE_T uSize, | ||
115 | IMG_SIZE_T *pActualSize, | ||
116 | BM_MAPPING **ppsMapping, | ||
117 | IMG_UINT32 uFlags, | ||
118 | IMG_UINTPTR_T *pBase); | ||
119 | IMG_VOID (*pImportFree) (IMG_VOID *, | ||
120 | IMG_UINTPTR_T, | ||
121 | BM_MAPPING *psMapping); | ||
122 | IMG_VOID (*pBackingStoreFree) (IMG_VOID *, IMG_SIZE_T, IMG_SIZE_T, IMG_HANDLE); | ||
123 | |||
124 | |||
125 | IMG_VOID *pImportHandle; | ||
126 | |||
127 | |||
128 | #define FREE_TABLE_LIMIT 32 | ||
129 | |||
130 | |||
131 | BT *aHeadFree [FREE_TABLE_LIMIT]; | ||
132 | |||
133 | |||
134 | BT *pHeadSegment; | ||
135 | BT *pTailSegment; | ||
136 | |||
137 | |||
138 | HASH_TABLE *pSegmentHash; | ||
139 | |||
140 | #ifdef RA_STATS | ||
141 | RA_STATISTICS sStatistics; | ||
142 | #endif | ||
143 | |||
144 | #if defined(CONFIG_PROC_FS) && defined(DEBUG) | ||
145 | #define PROC_NAME_SIZE 32 | ||
146 | |||
147 | struct proc_dir_entry* pProcInfo; | ||
148 | struct proc_dir_entry* pProcSegs; | ||
149 | |||
150 | IMG_BOOL bInitProcEntry; | ||
151 | #endif | ||
152 | }; | ||
153 | #if defined(ENABLE_RA_DUMP) | ||
154 | IMG_VOID RA_Dump (RA_ARENA *pArena); | ||
155 | #endif | ||
156 | |||
157 | #if defined(CONFIG_PROC_FS) && defined(DEBUG) | ||
158 | |||
159 | static void RA_ProcSeqShowInfo(struct seq_file *sfile, void* el); | ||
160 | static void* RA_ProcSeqOff2ElementInfo(struct seq_file * sfile, loff_t off); | ||
161 | |||
162 | static void RA_ProcSeqShowRegs(struct seq_file *sfile, void* el); | ||
163 | static void* RA_ProcSeqOff2ElementRegs(struct seq_file * sfile, loff_t off); | ||
164 | |||
165 | #endif | ||
166 | |||
167 | #ifdef USE_BM_FREESPACE_CHECK | ||
168 | IMG_VOID CheckBMFreespace(IMG_VOID); | ||
169 | #endif | ||
170 | |||
171 | #if defined(CONFIG_PROC_FS) && defined(DEBUG) | ||
172 | static IMG_CHAR *ReplaceSpaces(IMG_CHAR * const pS) | ||
173 | { | ||
174 | IMG_CHAR *pT; | ||
175 | |||
176 | for(pT = pS; *pT != 0; pT++) | ||
177 | { | ||
178 | if (*pT == ' ' || *pT == '\t') | ||
179 | { | ||
180 | *pT = '_'; | ||
181 | } | ||
182 | } | ||
183 | |||
184 | return pS; | ||
185 | } | ||
186 | #endif | ||
187 | |||
188 | static IMG_BOOL | ||
189 | _RequestAllocFail (IMG_VOID *_h, | ||
190 | IMG_SIZE_T _uSize, | ||
191 | IMG_SIZE_T *_pActualSize, | ||
192 | BM_MAPPING **_ppsMapping, | ||
193 | IMG_UINT32 _uFlags, | ||
194 | IMG_UINTPTR_T *_pBase) | ||
195 | { | ||
196 | PVR_UNREFERENCED_PARAMETER (_h); | ||
197 | PVR_UNREFERENCED_PARAMETER (_uSize); | ||
198 | PVR_UNREFERENCED_PARAMETER (_pActualSize); | ||
199 | PVR_UNREFERENCED_PARAMETER (_ppsMapping); | ||
200 | PVR_UNREFERENCED_PARAMETER (_uFlags); | ||
201 | PVR_UNREFERENCED_PARAMETER (_pBase); | ||
202 | |||
203 | return IMG_FALSE; | ||
204 | } | ||
205 | |||
206 | static IMG_UINT32 | ||
207 | pvr_log2 (IMG_SIZE_T n) | ||
208 | { | ||
209 | IMG_UINT32 l = 0; | ||
210 | n>>=1; | ||
211 | while (n>0) | ||
212 | { | ||
213 | n>>=1; | ||
214 | l++; | ||
215 | } | ||
216 | return l; | ||
217 | } | ||
218 | |||
219 | static PVRSRV_ERROR | ||
220 | _SegmentListInsertAfter (RA_ARENA *pArena, | ||
221 | BT *pInsertionPoint, | ||
222 | BT *pBT) | ||
223 | { | ||
224 | PVR_ASSERT (pArena != IMG_NULL); | ||
225 | PVR_ASSERT (pInsertionPoint != IMG_NULL); | ||
226 | |||
227 | if ((pInsertionPoint == IMG_NULL) || (pArena == IMG_NULL)) | ||
228 | { | ||
229 | PVR_DPF ((PVR_DBG_ERROR,"_SegmentListInsertAfter: invalid parameters")); | ||
230 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
231 | } | ||
232 | |||
233 | pBT->pNextSegment = pInsertionPoint->pNextSegment; | ||
234 | pBT->pPrevSegment = pInsertionPoint; | ||
235 | if (pInsertionPoint->pNextSegment == IMG_NULL) | ||
236 | pArena->pTailSegment = pBT; | ||
237 | else | ||
238 | pInsertionPoint->pNextSegment->pPrevSegment = pBT; | ||
239 | pInsertionPoint->pNextSegment = pBT; | ||
240 | |||
241 | return PVRSRV_OK; | ||
242 | } | ||
243 | |||
244 | static PVRSRV_ERROR | ||
245 | _SegmentListInsert (RA_ARENA *pArena, BT *pBT) | ||
246 | { | ||
247 | PVRSRV_ERROR eError = PVRSRV_OK; | ||
248 | |||
249 | |||
250 | if (pArena->pHeadSegment == IMG_NULL) | ||
251 | { | ||
252 | pArena->pHeadSegment = pArena->pTailSegment = pBT; | ||
253 | pBT->pNextSegment = pBT->pPrevSegment = IMG_NULL; | ||
254 | } | ||
255 | else | ||
256 | { | ||
257 | BT *pBTScan; | ||
258 | |||
259 | if (pBT->base < pArena->pHeadSegment->base) | ||
260 | { | ||
261 | |||
262 | pBT->pNextSegment = pArena->pHeadSegment; | ||
263 | pArena->pHeadSegment->pPrevSegment = pBT; | ||
264 | pArena->pHeadSegment = pBT; | ||
265 | pBT->pPrevSegment = IMG_NULL; | ||
266 | } | ||
267 | else | ||
268 | { | ||
269 | |||
270 | |||
271 | |||
272 | |||
273 | pBTScan = pArena->pHeadSegment; | ||
274 | |||
275 | while ((pBTScan->pNextSegment != IMG_NULL) && (pBT->base >= pBTScan->pNextSegment->base)) | ||
276 | { | ||
277 | pBTScan = pBTScan->pNextSegment; | ||
278 | } | ||
279 | |||
280 | eError = _SegmentListInsertAfter (pArena, pBTScan, pBT); | ||
281 | if (eError != PVRSRV_OK) | ||
282 | { | ||
283 | return eError; | ||
284 | } | ||
285 | } | ||
286 | } | ||
287 | return eError; | ||
288 | } | ||
289 | |||
290 | static IMG_VOID | ||
291 | _SegmentListRemove (RA_ARENA *pArena, BT *pBT) | ||
292 | { | ||
293 | if (pBT->pPrevSegment == IMG_NULL) | ||
294 | pArena->pHeadSegment = pBT->pNextSegment; | ||
295 | else | ||
296 | pBT->pPrevSegment->pNextSegment = pBT->pNextSegment; | ||
297 | |||
298 | if (pBT->pNextSegment == IMG_NULL) | ||
299 | pArena->pTailSegment = pBT->pPrevSegment; | ||
300 | else | ||
301 | pBT->pNextSegment->pPrevSegment = pBT->pPrevSegment; | ||
302 | } | ||
303 | |||
304 | static BT * | ||
305 | _SegmentSplit (RA_ARENA *pArena, BT *pBT, IMG_SIZE_T uSize) | ||
306 | { | ||
307 | BT *pNeighbour; | ||
308 | |||
309 | PVR_ASSERT (pArena != IMG_NULL); | ||
310 | |||
311 | if (pArena == IMG_NULL) | ||
312 | { | ||
313 | PVR_DPF ((PVR_DBG_ERROR,"_SegmentSplit: invalid parameter - pArena")); | ||
314 | return IMG_NULL; | ||
315 | } | ||
316 | |||
317 | if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, | ||
318 | sizeof(BT), | ||
319 | (IMG_VOID **)&pNeighbour, IMG_NULL, | ||
320 | "Boundary Tag") != PVRSRV_OK) | ||
321 | { | ||
322 | return IMG_NULL; | ||
323 | } | ||
324 | |||
325 | OSMemSet(pNeighbour, 0, sizeof(BT)); | ||
326 | |||
327 | #if defined(VALIDATE_ARENA_TEST) | ||
328 | pNeighbour->ui32BoundaryTagID = ++ui32BoundaryTagID; | ||
329 | #endif | ||
330 | |||
331 | pNeighbour->pPrevSegment = pBT; | ||
332 | pNeighbour->pNextSegment = pBT->pNextSegment; | ||
333 | if (pBT->pNextSegment == IMG_NULL) | ||
334 | pArena->pTailSegment = pNeighbour; | ||
335 | else | ||
336 | pBT->pNextSegment->pPrevSegment = pNeighbour; | ||
337 | pBT->pNextSegment = pNeighbour; | ||
338 | |||
339 | pNeighbour->type = btt_free; | ||
340 | pNeighbour->uSize = pBT->uSize - uSize; | ||
341 | pNeighbour->base = pBT->base + uSize; | ||
342 | pNeighbour->psMapping = pBT->psMapping; | ||
343 | pBT->uSize = uSize; | ||
344 | |||
345 | #if defined(VALIDATE_ARENA_TEST) | ||
346 | if (pNeighbour->pPrevSegment->eResourceType == IMPORTED_RESOURCE_TYPE) | ||
347 | { | ||
348 | pNeighbour->eResourceType = IMPORTED_RESOURCE_TYPE; | ||
349 | pNeighbour->eResourceSpan = IMPORTED_RESOURCE_SPAN_FREE; | ||
350 | } | ||
351 | else if (pNeighbour->pPrevSegment->eResourceType == NON_IMPORTED_RESOURCE_TYPE) | ||
352 | { | ||
353 | pNeighbour->eResourceType = NON_IMPORTED_RESOURCE_TYPE; | ||
354 | pNeighbour->eResourceSpan = RESOURCE_SPAN_FREE; | ||
355 | } | ||
356 | else | ||
357 | { | ||
358 | PVR_DPF ((PVR_DBG_ERROR,"_SegmentSplit: pNeighbour->pPrevSegment->eResourceType unrecognized")); | ||
359 | PVR_DBG_BREAK; | ||
360 | } | ||
361 | #endif | ||
362 | |||
363 | return pNeighbour; | ||
364 | } | ||
365 | |||
366 | static IMG_VOID | ||
367 | _FreeListInsert (RA_ARENA *pArena, BT *pBT) | ||
368 | { | ||
369 | IMG_UINT32 uIndex; | ||
370 | uIndex = pvr_log2 (pBT->uSize); | ||
371 | pBT->type = btt_free; | ||
372 | pBT->pNextFree = pArena->aHeadFree [uIndex]; | ||
373 | pBT->pPrevFree = IMG_NULL; | ||
374 | if (pArena->aHeadFree[uIndex] != IMG_NULL) | ||
375 | pArena->aHeadFree[uIndex]->pPrevFree = pBT; | ||
376 | pArena->aHeadFree [uIndex] = pBT; | ||
377 | } | ||
378 | |||
379 | static IMG_VOID | ||
380 | _FreeListRemove (RA_ARENA *pArena, BT *pBT) | ||
381 | { | ||
382 | IMG_UINT32 uIndex; | ||
383 | uIndex = pvr_log2 (pBT->uSize); | ||
384 | if (pBT->pNextFree != IMG_NULL) | ||
385 | pBT->pNextFree->pPrevFree = pBT->pPrevFree; | ||
386 | if (pBT->pPrevFree == IMG_NULL) | ||
387 | pArena->aHeadFree[uIndex] = pBT->pNextFree; | ||
388 | else | ||
389 | pBT->pPrevFree->pNextFree = pBT->pNextFree; | ||
390 | } | ||
391 | |||
392 | static BT * | ||
393 | _BuildSpanMarker (IMG_UINTPTR_T base, IMG_SIZE_T uSize) | ||
394 | { | ||
395 | BT *pBT; | ||
396 | |||
397 | if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, | ||
398 | sizeof(BT), | ||
399 | (IMG_VOID **)&pBT, IMG_NULL, | ||
400 | "Boundary Tag") != PVRSRV_OK) | ||
401 | { | ||
402 | return IMG_NULL; | ||
403 | } | ||
404 | |||
405 | OSMemSet(pBT, 0, sizeof(BT)); | ||
406 | |||
407 | #if defined(VALIDATE_ARENA_TEST) | ||
408 | pBT->ui32BoundaryTagID = ++ui32BoundaryTagID; | ||
409 | #endif | ||
410 | |||
411 | pBT->type = btt_span; | ||
412 | pBT->base = base; | ||
413 | pBT->uSize = uSize; | ||
414 | pBT->psMapping = IMG_NULL; | ||
415 | |||
416 | return pBT; | ||
417 | } | ||
418 | |||
419 | static BT * | ||
420 | _BuildBT (IMG_UINTPTR_T base, IMG_SIZE_T uSize) | ||
421 | { | ||
422 | BT *pBT; | ||
423 | |||
424 | if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, | ||
425 | sizeof(BT), | ||
426 | (IMG_VOID **)&pBT, IMG_NULL, | ||
427 | "Boundary Tag") != PVRSRV_OK) | ||
428 | { | ||
429 | return IMG_NULL; | ||
430 | } | ||
431 | |||
432 | OSMemSet(pBT, 0, sizeof(BT)); | ||
433 | |||
434 | #if defined(VALIDATE_ARENA_TEST) | ||
435 | pBT->ui32BoundaryTagID = ++ui32BoundaryTagID; | ||
436 | #endif | ||
437 | |||
438 | pBT->type = btt_free; | ||
439 | pBT->base = base; | ||
440 | pBT->uSize = uSize; | ||
441 | |||
442 | return pBT; | ||
443 | } | ||
444 | |||
445 | static BT * | ||
446 | _InsertResource (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize) | ||
447 | { | ||
448 | BT *pBT; | ||
449 | PVR_ASSERT (pArena!=IMG_NULL); | ||
450 | if (pArena == IMG_NULL) | ||
451 | { | ||
452 | PVR_DPF ((PVR_DBG_ERROR,"_InsertResource: invalid parameter - pArena")); | ||
453 | return IMG_NULL; | ||
454 | } | ||
455 | |||
456 | pBT = _BuildBT (base, uSize); | ||
457 | if (pBT != IMG_NULL) | ||
458 | { | ||
459 | |||
460 | #if defined(VALIDATE_ARENA_TEST) | ||
461 | pBT->eResourceSpan = RESOURCE_SPAN_FREE; | ||
462 | pBT->eResourceType = NON_IMPORTED_RESOURCE_TYPE; | ||
463 | #endif | ||
464 | |||
465 | if (_SegmentListInsert (pArena, pBT) != PVRSRV_OK) | ||
466 | { | ||
467 | PVR_DPF ((PVR_DBG_ERROR,"_InsertResource: call to _SegmentListInsert failed")); | ||
468 | return IMG_NULL; | ||
469 | } | ||
470 | _FreeListInsert (pArena, pBT); | ||
471 | #ifdef RA_STATS | ||
472 | pArena->sStatistics.uTotalResourceCount+=uSize; | ||
473 | pArena->sStatistics.uFreeResourceCount+=uSize; | ||
474 | pArena->sStatistics.uSpanCount++; | ||
475 | #endif | ||
476 | } | ||
477 | return pBT; | ||
478 | } | ||
479 | |||
480 | static BT * | ||
481 | _InsertResourceSpan (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize) | ||
482 | { | ||
483 | PVRSRV_ERROR eError; | ||
484 | BT *pSpanStart; | ||
485 | BT *pSpanEnd; | ||
486 | BT *pBT; | ||
487 | |||
488 | PVR_ASSERT (pArena != IMG_NULL); | ||
489 | if (pArena == IMG_NULL) | ||
490 | { | ||
491 | PVR_DPF ((PVR_DBG_ERROR,"_InsertResourceSpan: invalid parameter - pArena")); | ||
492 | return IMG_NULL; | ||
493 | } | ||
494 | |||
495 | PVR_DPF ((PVR_DBG_MESSAGE, | ||
496 | "RA_InsertResourceSpan: arena='%s', base=0x%x, size=0x%x", | ||
497 | pArena->name, base, uSize)); | ||
498 | |||
499 | pSpanStart = _BuildSpanMarker (base, uSize); | ||
500 | if (pSpanStart == IMG_NULL) | ||
501 | { | ||
502 | goto fail_start; | ||
503 | } | ||
504 | |||
505 | #if defined(VALIDATE_ARENA_TEST) | ||
506 | pSpanStart->eResourceSpan = IMPORTED_RESOURCE_SPAN_START; | ||
507 | pSpanStart->eResourceType = IMPORTED_RESOURCE_TYPE; | ||
508 | #endif | ||
509 | |||
510 | pSpanEnd = _BuildSpanMarker (base + uSize, 0); | ||
511 | if (pSpanEnd == IMG_NULL) | ||
512 | { | ||
513 | goto fail_end; | ||
514 | } | ||
515 | |||
516 | #if defined(VALIDATE_ARENA_TEST) | ||
517 | pSpanEnd->eResourceSpan = IMPORTED_RESOURCE_SPAN_END; | ||
518 | pSpanEnd->eResourceType = IMPORTED_RESOURCE_TYPE; | ||
519 | #endif | ||
520 | |||
521 | pBT = _BuildBT (base, uSize); | ||
522 | if (pBT == IMG_NULL) | ||
523 | { | ||
524 | goto fail_bt; | ||
525 | } | ||
526 | |||
527 | #if defined(VALIDATE_ARENA_TEST) | ||
528 | pBT->eResourceSpan = IMPORTED_RESOURCE_SPAN_FREE; | ||
529 | pBT->eResourceType = IMPORTED_RESOURCE_TYPE; | ||
530 | #endif | ||
531 | |||
532 | eError = _SegmentListInsert (pArena, pSpanStart); | ||
533 | if (eError != PVRSRV_OK) | ||
534 | { | ||
535 | goto fail_SegListInsert; | ||
536 | } | ||
537 | |||
538 | eError = _SegmentListInsertAfter (pArena, pSpanStart, pBT); | ||
539 | if (eError != PVRSRV_OK) | ||
540 | { | ||
541 | goto fail_SegListInsert; | ||
542 | } | ||
543 | |||
544 | _FreeListInsert (pArena, pBT); | ||
545 | |||
546 | eError = _SegmentListInsertAfter (pArena, pBT, pSpanEnd); | ||
547 | if (eError != PVRSRV_OK) | ||
548 | { | ||
549 | goto fail_SegListInsert; | ||
550 | } | ||
551 | |||
552 | #ifdef RA_STATS | ||
553 | pArena->sStatistics.uTotalResourceCount+=uSize; | ||
554 | #endif | ||
555 | return pBT; | ||
556 | |||
557 | fail_SegListInsert: | ||
558 | OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL); | ||
559 | |||
560 | fail_bt: | ||
561 | OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pSpanEnd, IMG_NULL); | ||
562 | |||
563 | fail_end: | ||
564 | OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pSpanStart, IMG_NULL); | ||
565 | |||
566 | fail_start: | ||
567 | return IMG_NULL; | ||
568 | } | ||
569 | |||
570 | static IMG_VOID | ||
571 | _FreeBT (RA_ARENA *pArena, BT *pBT, IMG_BOOL bFreeBackingStore) | ||
572 | { | ||
573 | BT *pNeighbour; | ||
574 | IMG_UINTPTR_T uOrigBase; | ||
575 | IMG_SIZE_T uOrigSize; | ||
576 | |||
577 | PVR_ASSERT (pArena!=IMG_NULL); | ||
578 | PVR_ASSERT (pBT!=IMG_NULL); | ||
579 | |||
580 | if ((pArena == IMG_NULL) || (pBT == IMG_NULL)) | ||
581 | { | ||
582 | PVR_DPF ((PVR_DBG_ERROR,"_FreeBT: invalid parameter")); | ||
583 | return; | ||
584 | } | ||
585 | |||
586 | #ifdef RA_STATS | ||
587 | pArena->sStatistics.uLiveSegmentCount--; | ||
588 | pArena->sStatistics.uFreeSegmentCount++; | ||
589 | pArena->sStatistics.uFreeResourceCount+=pBT->uSize; | ||
590 | #endif | ||
591 | |||
592 | uOrigBase = pBT->base; | ||
593 | uOrigSize = pBT->uSize; | ||
594 | |||
595 | |||
596 | pNeighbour = pBT->pPrevSegment; | ||
597 | if (pNeighbour!=IMG_NULL | ||
598 | && pNeighbour->type == btt_free | ||
599 | && pNeighbour->base + pNeighbour->uSize == pBT->base) | ||
600 | { | ||
601 | _FreeListRemove (pArena, pNeighbour); | ||
602 | _SegmentListRemove (pArena, pNeighbour); | ||
603 | pBT->base = pNeighbour->base; | ||
604 | pBT->uSize += pNeighbour->uSize; | ||
605 | OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pNeighbour, IMG_NULL); | ||
606 | |||
607 | #ifdef RA_STATS | ||
608 | pArena->sStatistics.uFreeSegmentCount--; | ||
609 | #endif | ||
610 | } | ||
611 | |||
612 | |||
613 | pNeighbour = pBT->pNextSegment; | ||
614 | if (pNeighbour!=IMG_NULL | ||
615 | && pNeighbour->type == btt_free | ||
616 | && pBT->base + pBT->uSize == pNeighbour->base) | ||
617 | { | ||
618 | _FreeListRemove (pArena, pNeighbour); | ||
619 | _SegmentListRemove (pArena, pNeighbour); | ||
620 | pBT->uSize += pNeighbour->uSize; | ||
621 | OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pNeighbour, IMG_NULL); | ||
622 | |||
623 | #ifdef RA_STATS | ||
624 | pArena->sStatistics.uFreeSegmentCount--; | ||
625 | #endif | ||
626 | } | ||
627 | |||
628 | |||
629 | if (pArena->pBackingStoreFree != IMG_NULL && bFreeBackingStore) | ||
630 | { | ||
631 | IMG_UINTPTR_T uRoundedStart, uRoundedEnd; | ||
632 | |||
633 | |||
634 | uRoundedStart = (uOrigBase / pArena->uQuantum) * pArena->uQuantum; | ||
635 | |||
636 | if (uRoundedStart < pBT->base) | ||
637 | { | ||
638 | uRoundedStart += pArena->uQuantum; | ||
639 | } | ||
640 | |||
641 | |||
642 | uRoundedEnd = ((uOrigBase + uOrigSize + pArena->uQuantum - 1) / pArena->uQuantum) * pArena->uQuantum; | ||
643 | |||
644 | if (uRoundedEnd > (pBT->base + pBT->uSize)) | ||
645 | { | ||
646 | uRoundedEnd -= pArena->uQuantum; | ||
647 | } | ||
648 | |||
649 | if (uRoundedStart < uRoundedEnd) | ||
650 | { | ||
651 | pArena->pBackingStoreFree(pArena->pImportHandle, (IMG_SIZE_T)uRoundedStart, (IMG_SIZE_T)uRoundedEnd, (IMG_HANDLE)0); | ||
652 | } | ||
653 | } | ||
654 | |||
655 | if (pBT->pNextSegment!=IMG_NULL && pBT->pNextSegment->type == btt_span | ||
656 | && pBT->pPrevSegment!=IMG_NULL && pBT->pPrevSegment->type == btt_span) | ||
657 | { | ||
658 | BT *next = pBT->pNextSegment; | ||
659 | BT *prev = pBT->pPrevSegment; | ||
660 | _SegmentListRemove (pArena, next); | ||
661 | _SegmentListRemove (pArena, prev); | ||
662 | _SegmentListRemove (pArena, pBT); | ||
663 | pArena->pImportFree (pArena->pImportHandle, pBT->base, pBT->psMapping); | ||
664 | #ifdef RA_STATS | ||
665 | pArena->sStatistics.uSpanCount--; | ||
666 | pArena->sStatistics.uExportCount++; | ||
667 | pArena->sStatistics.uFreeSegmentCount--; | ||
668 | pArena->sStatistics.uFreeResourceCount-=pBT->uSize; | ||
669 | pArena->sStatistics.uTotalResourceCount-=pBT->uSize; | ||
670 | #endif | ||
671 | OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), next, IMG_NULL); | ||
672 | |||
673 | OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), prev, IMG_NULL); | ||
674 | |||
675 | OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL); | ||
676 | |||
677 | } | ||
678 | else | ||
679 | _FreeListInsert (pArena, pBT); | ||
680 | } | ||
681 | |||
682 | |||
683 | static IMG_BOOL | ||
684 | _AttemptAllocAligned (RA_ARENA *pArena, | ||
685 | IMG_SIZE_T uSize, | ||
686 | BM_MAPPING **ppsMapping, | ||
687 | IMG_UINT32 uFlags, | ||
688 | IMG_UINT32 uAlignment, | ||
689 | IMG_UINT32 uAlignmentOffset, | ||
690 | IMG_UINTPTR_T *base) | ||
691 | { | ||
692 | IMG_UINT32 uIndex; | ||
693 | PVR_ASSERT (pArena!=IMG_NULL); | ||
694 | if (pArena == IMG_NULL) | ||
695 | { | ||
696 | PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: invalid parameter - pArena")); | ||
697 | return IMG_FALSE; | ||
698 | } | ||
699 | |||
700 | if (uAlignment>1) | ||
701 | uAlignmentOffset %= uAlignment; | ||
702 | |||
703 | |||
704 | |||
705 | uIndex = pvr_log2 (uSize); | ||
706 | |||
707 | #if 0 | ||
708 | |||
709 | if (1u<<uIndex < uSize) | ||
710 | uIndex++; | ||
711 | #endif | ||
712 | |||
713 | while (uIndex < FREE_TABLE_LIMIT && pArena->aHeadFree[uIndex]==IMG_NULL) | ||
714 | uIndex++; | ||
715 | |||
716 | while (uIndex < FREE_TABLE_LIMIT) | ||
717 | { | ||
718 | if (pArena->aHeadFree[uIndex]!=IMG_NULL) | ||
719 | { | ||
720 | |||
721 | BT *pBT; | ||
722 | |||
723 | pBT = pArena->aHeadFree [uIndex]; | ||
724 | while (pBT!=IMG_NULL) | ||
725 | { | ||
726 | IMG_UINTPTR_T aligned_base; | ||
727 | |||
728 | if (uAlignment>1) | ||
729 | aligned_base = (pBT->base + uAlignmentOffset + uAlignment - 1) / uAlignment * uAlignment - uAlignmentOffset; | ||
730 | else | ||
731 | aligned_base = pBT->base; | ||
732 | PVR_DPF ((PVR_DBG_MESSAGE, | ||
733 | "RA_AttemptAllocAligned: pBT-base=0x%x " | ||
734 | "pBT-size=0x%x alignedbase=0x%x size=0x%x", | ||
735 | pBT->base, pBT->uSize, aligned_base, uSize)); | ||
736 | |||
737 | if (pBT->base + pBT->uSize >= aligned_base + uSize) | ||
738 | { | ||
739 | if(!pBT->psMapping || pBT->psMapping->ui32Flags == uFlags) | ||
740 | { | ||
741 | _FreeListRemove (pArena, pBT); | ||
742 | |||
743 | PVR_ASSERT (pBT->type == btt_free); | ||
744 | |||
745 | #ifdef RA_STATS | ||
746 | pArena->sStatistics.uLiveSegmentCount++; | ||
747 | pArena->sStatistics.uFreeSegmentCount--; | ||
748 | pArena->sStatistics.uFreeResourceCount-=pBT->uSize; | ||
749 | #endif | ||
750 | |||
751 | |||
752 | if (aligned_base > pBT->base) | ||
753 | { | ||
754 | BT *pNeighbour; | ||
755 | pNeighbour = _SegmentSplit (pArena, pBT, (IMG_SIZE_T)(aligned_base - pBT->base)); | ||
756 | |||
757 | if (pNeighbour==IMG_NULL) | ||
758 | { | ||
759 | PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: Front split failed")); | ||
760 | |||
761 | _FreeListInsert (pArena, pBT); | ||
762 | return IMG_FALSE; | ||
763 | } | ||
764 | |||
765 | _FreeListInsert (pArena, pBT); | ||
766 | #ifdef RA_STATS | ||
767 | pArena->sStatistics.uFreeSegmentCount++; | ||
768 | pArena->sStatistics.uFreeResourceCount+=pBT->uSize; | ||
769 | #endif | ||
770 | pBT = pNeighbour; | ||
771 | } | ||
772 | |||
773 | |||
774 | if (pBT->uSize > uSize) | ||
775 | { | ||
776 | BT *pNeighbour; | ||
777 | pNeighbour = _SegmentSplit (pArena, pBT, uSize); | ||
778 | |||
779 | if (pNeighbour==IMG_NULL) | ||
780 | { | ||
781 | PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: Back split failed")); | ||
782 | |||
783 | _FreeListInsert (pArena, pBT); | ||
784 | return IMG_FALSE; | ||
785 | } | ||
786 | |||
787 | _FreeListInsert (pArena, pNeighbour); | ||
788 | #ifdef RA_STATS | ||
789 | pArena->sStatistics.uFreeSegmentCount++; | ||
790 | pArena->sStatistics.uFreeResourceCount+=pNeighbour->uSize; | ||
791 | #endif | ||
792 | } | ||
793 | |||
794 | pBT->type = btt_live; | ||
795 | |||
796 | #if defined(VALIDATE_ARENA_TEST) | ||
797 | if (pBT->eResourceType == IMPORTED_RESOURCE_TYPE) | ||
798 | { | ||
799 | pBT->eResourceSpan = IMPORTED_RESOURCE_SPAN_LIVE; | ||
800 | } | ||
801 | else if (pBT->eResourceType == NON_IMPORTED_RESOURCE_TYPE) | ||
802 | { | ||
803 | pBT->eResourceSpan = RESOURCE_SPAN_LIVE; | ||
804 | } | ||
805 | else | ||
806 | { | ||
807 | PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned ERROR: pBT->eResourceType unrecognized")); | ||
808 | PVR_DBG_BREAK; | ||
809 | } | ||
810 | #endif | ||
811 | if (!HASH_Insert (pArena->pSegmentHash, pBT->base, (IMG_UINTPTR_T) pBT)) | ||
812 | { | ||
813 | _FreeBT (pArena, pBT, IMG_FALSE); | ||
814 | return IMG_FALSE; | ||
815 | } | ||
816 | |||
817 | if (ppsMapping!=IMG_NULL) | ||
818 | *ppsMapping = pBT->psMapping; | ||
819 | |||
820 | *base = pBT->base; | ||
821 | |||
822 | return IMG_TRUE; | ||
823 | } | ||
824 | else | ||
825 | { | ||
826 | PVR_DPF ((PVR_DBG_MESSAGE, | ||
827 | "AttemptAllocAligned: mismatch in flags. Import has %x, request was %x", pBT->psMapping->ui32Flags, uFlags)); | ||
828 | |||
829 | } | ||
830 | } | ||
831 | pBT = pBT->pNextFree; | ||
832 | } | ||
833 | |||
834 | } | ||
835 | uIndex++; | ||
836 | } | ||
837 | |||
838 | return IMG_FALSE; | ||
839 | } | ||
840 | |||
841 | |||
842 | |||
843 | RA_ARENA * | ||
844 | RA_Create (IMG_CHAR *name, | ||
845 | IMG_UINTPTR_T base, | ||
846 | IMG_SIZE_T uSize, | ||
847 | BM_MAPPING *psMapping, | ||
848 | IMG_SIZE_T uQuantum, | ||
849 | IMG_BOOL (*imp_alloc)(IMG_VOID *, IMG_SIZE_T uSize, IMG_SIZE_T *pActualSize, | ||
850 | BM_MAPPING **ppsMapping, IMG_UINT32 _flags, IMG_UINTPTR_T *pBase), | ||
851 | IMG_VOID (*imp_free) (IMG_VOID *, IMG_UINTPTR_T, BM_MAPPING *), | ||
852 | IMG_VOID (*backingstore_free) (IMG_VOID*, IMG_SIZE_T, IMG_SIZE_T, IMG_HANDLE), | ||
853 | IMG_VOID *pImportHandle) | ||
854 | { | ||
855 | RA_ARENA *pArena; | ||
856 | BT *pBT; | ||
857 | IMG_INT i; | ||
858 | |||
859 | PVR_DPF ((PVR_DBG_MESSAGE, | ||
860 | "RA_Create: name='%s', base=0x%x, uSize=0x%x, alloc=0x%x, free=0x%x", | ||
861 | name, base, uSize, (IMG_UINTPTR_T)imp_alloc, (IMG_UINTPTR_T)imp_free)); | ||
862 | |||
863 | |||
864 | if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, | ||
865 | sizeof (*pArena), | ||
866 | (IMG_VOID **)&pArena, IMG_NULL, | ||
867 | "Resource Arena") != PVRSRV_OK) | ||
868 | { | ||
869 | goto arena_fail; | ||
870 | } | ||
871 | |||
872 | pArena->name = name; | ||
873 | pArena->pImportAlloc = (imp_alloc!=IMG_NULL) ? imp_alloc : &_RequestAllocFail; | ||
874 | pArena->pImportFree = imp_free; | ||
875 | pArena->pBackingStoreFree = backingstore_free; | ||
876 | pArena->pImportHandle = pImportHandle; | ||
877 | for (i=0; i<FREE_TABLE_LIMIT; i++) | ||
878 | pArena->aHeadFree[i] = IMG_NULL; | ||
879 | pArena->pHeadSegment = IMG_NULL; | ||
880 | pArena->pTailSegment = IMG_NULL; | ||
881 | pArena->uQuantum = uQuantum; | ||
882 | |||
883 | #ifdef RA_STATS | ||
884 | pArena->sStatistics.uSpanCount = 0; | ||
885 | pArena->sStatistics.uLiveSegmentCount = 0; | ||
886 | pArena->sStatistics.uFreeSegmentCount = 0; | ||
887 | pArena->sStatistics.uFreeResourceCount = 0; | ||
888 | pArena->sStatistics.uTotalResourceCount = 0; | ||
889 | pArena->sStatistics.uCumulativeAllocs = 0; | ||
890 | pArena->sStatistics.uCumulativeFrees = 0; | ||
891 | pArena->sStatistics.uImportCount = 0; | ||
892 | pArena->sStatistics.uExportCount = 0; | ||
893 | #endif | ||
894 | |||
895 | #if defined(CONFIG_PROC_FS) && defined(DEBUG) | ||
896 | if(strcmp(pArena->name,"") != 0) | ||
897 | { | ||
898 | IMG_INT ret; | ||
899 | IMG_CHAR szProcInfoName[PROC_NAME_SIZE]; | ||
900 | IMG_CHAR szProcSegsName[PROC_NAME_SIZE]; | ||
901 | struct proc_dir_entry* (*pfnCreateProcEntrySeq)(const IMG_CHAR *, | ||
902 | IMG_VOID*, | ||
903 | pvr_next_proc_seq_t, | ||
904 | pvr_show_proc_seq_t, | ||
905 | pvr_off2element_proc_seq_t, | ||
906 | pvr_startstop_proc_seq_t, | ||
907 | write_proc_t); | ||
908 | |||
909 | pArena->bInitProcEntry = !PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL); | ||
910 | |||
911 | |||
912 | pfnCreateProcEntrySeq = pArena->bInitProcEntry ? CreateProcEntrySeq : CreatePerProcessProcEntrySeq; | ||
913 | |||
914 | ret = snprintf(szProcInfoName, sizeof(szProcInfoName), "ra_info_%s", pArena->name); | ||
915 | if (ret > 0 && ret < sizeof(szProcInfoName)) | ||
916 | { | ||
917 | pArena->pProcInfo = pfnCreateProcEntrySeq(ReplaceSpaces(szProcInfoName), pArena, NULL, | ||
918 | RA_ProcSeqShowInfo, RA_ProcSeqOff2ElementInfo, NULL, NULL); | ||
919 | } | ||
920 | else | ||
921 | { | ||
922 | pArena->pProcInfo = 0; | ||
923 | PVR_DPF((PVR_DBG_ERROR, "RA_Create: couldn't create ra_info proc entry for arena %s", pArena->name)); | ||
924 | } | ||
925 | |||
926 | ret = snprintf(szProcSegsName, sizeof(szProcSegsName), "ra_segs_%s", pArena->name); | ||
927 | if (ret > 0 && ret < sizeof(szProcInfoName)) | ||
928 | { | ||
929 | pArena->pProcSegs = pfnCreateProcEntrySeq(ReplaceSpaces(szProcSegsName), pArena, NULL, | ||
930 | RA_ProcSeqShowRegs, RA_ProcSeqOff2ElementRegs, NULL, NULL); | ||
931 | } | ||
932 | else | ||
933 | { | ||
934 | pArena->pProcSegs = 0; | ||
935 | PVR_DPF((PVR_DBG_ERROR, "RA_Create: couldn't create ra_segs proc entry for arena %s", pArena->name)); | ||
936 | } | ||
937 | } | ||
938 | #endif | ||
939 | |||
940 | pArena->pSegmentHash = HASH_Create (MINIMUM_HASH_SIZE); | ||
941 | if (pArena->pSegmentHash==IMG_NULL) | ||
942 | { | ||
943 | goto hash_fail; | ||
944 | } | ||
945 | if (uSize>0) | ||
946 | { | ||
947 | uSize = (uSize + uQuantum - 1) / uQuantum * uQuantum; | ||
948 | pBT = _InsertResource (pArena, base, uSize); | ||
949 | if (pBT == IMG_NULL) | ||
950 | { | ||
951 | goto insert_fail; | ||
952 | } | ||
953 | pBT->psMapping = psMapping; | ||
954 | |||
955 | } | ||
956 | return pArena; | ||
957 | |||
958 | insert_fail: | ||
959 | HASH_Delete (pArena->pSegmentHash); | ||
960 | hash_fail: | ||
961 | OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RA_ARENA), pArena, IMG_NULL); | ||
962 | |||
963 | arena_fail: | ||
964 | return IMG_NULL; | ||
965 | } | ||
966 | |||
967 | IMG_VOID | ||
968 | RA_Delete (RA_ARENA *pArena) | ||
969 | { | ||
970 | IMG_UINT32 uIndex; | ||
971 | |||
972 | PVR_ASSERT(pArena != IMG_NULL); | ||
973 | |||
974 | if (pArena == IMG_NULL) | ||
975 | { | ||
976 | PVR_DPF ((PVR_DBG_ERROR,"RA_Delete: invalid parameter - pArena")); | ||
977 | return; | ||
978 | } | ||
979 | |||
980 | PVR_DPF ((PVR_DBG_MESSAGE, | ||
981 | "RA_Delete: name='%s'", pArena->name)); | ||
982 | |||
983 | for (uIndex=0; uIndex<FREE_TABLE_LIMIT; uIndex++) | ||
984 | pArena->aHeadFree[uIndex] = IMG_NULL; | ||
985 | |||
986 | while (pArena->pHeadSegment != IMG_NULL) | ||
987 | { | ||
988 | BT *pBT = pArena->pHeadSegment; | ||
989 | |||
990 | if (pBT->type != btt_free) | ||
991 | { | ||
992 | PVR_DPF ((PVR_DBG_ERROR,"RA_Delete: allocations still exist in the arena that is being destroyed")); | ||
993 | PVR_DPF ((PVR_DBG_ERROR,"Likely Cause: client drivers not freeing alocations before destroying devmemcontext")); | ||
994 | PVR_DPF ((PVR_DBG_ERROR,"RA_Delete: base = 0x%x size=0x%x", pBT->base, pBT->uSize)); | ||
995 | } | ||
996 | |||
997 | _SegmentListRemove (pArena, pBT); | ||
998 | OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL); | ||
999 | |||
1000 | #ifdef RA_STATS | ||
1001 | pArena->sStatistics.uSpanCount--; | ||
1002 | #endif | ||
1003 | } | ||
1004 | #if defined(CONFIG_PROC_FS) && defined(DEBUG) | ||
1005 | { | ||
1006 | IMG_VOID (*pfnRemoveProcEntrySeq)(struct proc_dir_entry*); | ||
1007 | |||
1008 | pfnRemoveProcEntrySeq = pArena->bInitProcEntry ? RemoveProcEntrySeq : RemovePerProcessProcEntrySeq; | ||
1009 | |||
1010 | if (pArena->pProcInfo != 0) | ||
1011 | { | ||
1012 | pfnRemoveProcEntrySeq( pArena->pProcInfo ); | ||
1013 | } | ||
1014 | |||
1015 | if (pArena->pProcSegs != 0) | ||
1016 | { | ||
1017 | pfnRemoveProcEntrySeq( pArena->pProcSegs ); | ||
1018 | } | ||
1019 | } | ||
1020 | #endif | ||
1021 | HASH_Delete (pArena->pSegmentHash); | ||
1022 | OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RA_ARENA), pArena, IMG_NULL); | ||
1023 | |||
1024 | } | ||
1025 | |||
1026 | IMG_BOOL | ||
1027 | RA_TestDelete (RA_ARENA *pArena) | ||
1028 | { | ||
1029 | PVR_ASSERT(pArena != IMG_NULL); | ||
1030 | |||
1031 | if (pArena != IMG_NULL) | ||
1032 | { | ||
1033 | while (pArena->pHeadSegment != IMG_NULL) | ||
1034 | { | ||
1035 | BT *pBT = pArena->pHeadSegment; | ||
1036 | if (pBT->type != btt_free) | ||
1037 | { | ||
1038 | PVR_DPF ((PVR_DBG_ERROR,"RA_TestDelete: detected resource leak!")); | ||
1039 | PVR_DPF ((PVR_DBG_ERROR,"RA_TestDelete: base = 0x%x size=0x%x", pBT->base, pBT->uSize)); | ||
1040 | return IMG_FALSE; | ||
1041 | } | ||
1042 | } | ||
1043 | } | ||
1044 | |||
1045 | return IMG_TRUE; | ||
1046 | } | ||
1047 | |||
1048 | IMG_BOOL | ||
1049 | RA_Add (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize) | ||
1050 | { | ||
1051 | PVR_ASSERT (pArena != IMG_NULL); | ||
1052 | |||
1053 | if (pArena == IMG_NULL) | ||
1054 | { | ||
1055 | PVR_DPF ((PVR_DBG_ERROR,"RA_Add: invalid parameter - pArena")); | ||
1056 | return IMG_FALSE; | ||
1057 | } | ||
1058 | |||
1059 | PVR_DPF ((PVR_DBG_MESSAGE, | ||
1060 | "RA_Add: name='%s', base=0x%x, size=0x%x", pArena->name, base, uSize)); | ||
1061 | |||
1062 | uSize = (uSize + pArena->uQuantum - 1) / pArena->uQuantum * pArena->uQuantum; | ||
1063 | return ((IMG_BOOL)(_InsertResource (pArena, base, uSize) != IMG_NULL)); | ||
1064 | } | ||
1065 | |||
1066 | IMG_BOOL | ||
1067 | RA_Alloc (RA_ARENA *pArena, | ||
1068 | IMG_SIZE_T uRequestSize, | ||
1069 | IMG_SIZE_T *pActualSize, | ||
1070 | BM_MAPPING **ppsMapping, | ||
1071 | IMG_UINT32 uFlags, | ||
1072 | IMG_UINT32 uAlignment, | ||
1073 | IMG_UINT32 uAlignmentOffset, | ||
1074 | IMG_UINTPTR_T *base) | ||
1075 | { | ||
1076 | IMG_BOOL bResult; | ||
1077 | IMG_SIZE_T uSize = uRequestSize; | ||
1078 | |||
1079 | PVR_ASSERT (pArena!=IMG_NULL); | ||
1080 | |||
1081 | if (pArena == IMG_NULL) | ||
1082 | { | ||
1083 | PVR_DPF ((PVR_DBG_ERROR,"RA_Alloc: invalid parameter - pArena")); | ||
1084 | return IMG_FALSE; | ||
1085 | } | ||
1086 | |||
1087 | #if defined(VALIDATE_ARENA_TEST) | ||
1088 | ValidateArena(pArena); | ||
1089 | #endif | ||
1090 | |||
1091 | #ifdef USE_BM_FREESPACE_CHECK | ||
1092 | CheckBMFreespace(); | ||
1093 | #endif | ||
1094 | |||
1095 | if (pActualSize != IMG_NULL) | ||
1096 | { | ||
1097 | *pActualSize = uSize; | ||
1098 | } | ||
1099 | |||
1100 | PVR_DPF ((PVR_DBG_MESSAGE, | ||
1101 | "RA_Alloc: arena='%s', size=0x%x(0x%x), alignment=0x%x, offset=0x%x", | ||
1102 | pArena->name, uSize, uRequestSize, uAlignment, uAlignmentOffset)); | ||
1103 | |||
1104 | |||
1105 | |||
1106 | bResult = _AttemptAllocAligned (pArena, uSize, ppsMapping, uFlags, | ||
1107 | uAlignment, uAlignmentOffset, base); | ||
1108 | if (!bResult) | ||
1109 | { | ||
1110 | BM_MAPPING *psImportMapping; | ||
1111 | IMG_UINTPTR_T import_base; | ||
1112 | IMG_SIZE_T uImportSize = uSize; | ||
1113 | |||
1114 | |||
1115 | |||
1116 | |||
1117 | if (uAlignment > pArena->uQuantum) | ||
1118 | { | ||
1119 | uImportSize += (uAlignment - 1); | ||
1120 | } | ||
1121 | |||
1122 | |||
1123 | uImportSize = ((uImportSize + pArena->uQuantum - 1)/pArena->uQuantum)*pArena->uQuantum; | ||
1124 | |||
1125 | bResult = | ||
1126 | pArena->pImportAlloc (pArena->pImportHandle, uImportSize, &uImportSize, | ||
1127 | &psImportMapping, uFlags, &import_base); | ||
1128 | if (bResult) | ||
1129 | { | ||
1130 | BT *pBT; | ||
1131 | pBT = _InsertResourceSpan (pArena, import_base, uImportSize); | ||
1132 | |||
1133 | if (pBT == IMG_NULL) | ||
1134 | { | ||
1135 | |||
1136 | pArena->pImportFree(pArena->pImportHandle, import_base, | ||
1137 | psImportMapping); | ||
1138 | PVR_DPF ((PVR_DBG_MESSAGE, | ||
1139 | "RA_Alloc: name='%s', size=0x%x failed!", | ||
1140 | pArena->name, uSize)); | ||
1141 | |||
1142 | return IMG_FALSE; | ||
1143 | } | ||
1144 | pBT->psMapping = psImportMapping; | ||
1145 | #ifdef RA_STATS | ||
1146 | pArena->sStatistics.uFreeSegmentCount++; | ||
1147 | pArena->sStatistics.uFreeResourceCount += uImportSize; | ||
1148 | pArena->sStatistics.uImportCount++; | ||
1149 | pArena->sStatistics.uSpanCount++; | ||
1150 | #endif | ||
1151 | bResult = _AttemptAllocAligned(pArena, uSize, ppsMapping, uFlags, | ||
1152 | uAlignment, uAlignmentOffset, | ||
1153 | base); | ||
1154 | if (!bResult) | ||
1155 | { | ||
1156 | PVR_DPF ((PVR_DBG_MESSAGE, | ||
1157 | "RA_Alloc: name='%s' uAlignment failed!", | ||
1158 | pArena->name)); | ||
1159 | } | ||
1160 | } | ||
1161 | } | ||
1162 | #ifdef RA_STATS | ||
1163 | if (bResult) | ||
1164 | pArena->sStatistics.uCumulativeAllocs++; | ||
1165 | #endif | ||
1166 | |||
1167 | PVR_DPF ((PVR_DBG_MESSAGE, | ||
1168 | "RA_Alloc: name='%s', size=0x%x, *base=0x%x = %d", | ||
1169 | pArena->name, uSize, *base, bResult)); | ||
1170 | |||
1171 | |||
1172 | |||
1173 | #if defined(VALIDATE_ARENA_TEST) | ||
1174 | ValidateArena(pArena); | ||
1175 | #endif | ||
1176 | |||
1177 | return bResult; | ||
1178 | } | ||
1179 | |||
1180 | |||
1181 | #if defined(VALIDATE_ARENA_TEST) | ||
1182 | |||
1183 | IMG_UINT32 ValidateArena(RA_ARENA *pArena) | ||
1184 | { | ||
1185 | BT* pSegment; | ||
1186 | RESOURCE_DESCRIPTOR eNextSpan; | ||
1187 | |||
1188 | pSegment = pArena->pHeadSegment; | ||
1189 | |||
1190 | if (pSegment == IMG_NULL) | ||
1191 | { | ||
1192 | return 0; | ||
1193 | } | ||
1194 | |||
1195 | if (pSegment->eResourceType == IMPORTED_RESOURCE_TYPE) | ||
1196 | { | ||
1197 | PVR_ASSERT(pSegment->eResourceSpan == IMPORTED_RESOURCE_SPAN_START); | ||
1198 | |||
1199 | while (pSegment->pNextSegment) | ||
1200 | { | ||
1201 | eNextSpan = pSegment->pNextSegment->eResourceSpan; | ||
1202 | |||
1203 | switch (pSegment->eResourceSpan) | ||
1204 | { | ||
1205 | case IMPORTED_RESOURCE_SPAN_LIVE: | ||
1206 | |||
1207 | if (!((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) || | ||
1208 | (eNextSpan == IMPORTED_RESOURCE_SPAN_FREE) || | ||
1209 | (eNextSpan == IMPORTED_RESOURCE_SPAN_END))) | ||
1210 | { | ||
1211 | |||
1212 | PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)", | ||
1213 | pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name)); | ||
1214 | |||
1215 | PVR_DBG_BREAK; | ||
1216 | } | ||
1217 | break; | ||
1218 | |||
1219 | case IMPORTED_RESOURCE_SPAN_FREE: | ||
1220 | |||
1221 | if (!((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) || | ||
1222 | (eNextSpan == IMPORTED_RESOURCE_SPAN_END))) | ||
1223 | { | ||
1224 | |||
1225 | PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)", | ||
1226 | pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name)); | ||
1227 | |||
1228 | PVR_DBG_BREAK; | ||
1229 | } | ||
1230 | break; | ||
1231 | |||
1232 | case IMPORTED_RESOURCE_SPAN_END: | ||
1233 | |||
1234 | if ((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) || | ||
1235 | (eNextSpan == IMPORTED_RESOURCE_SPAN_FREE) || | ||
1236 | (eNextSpan == IMPORTED_RESOURCE_SPAN_END)) | ||
1237 | { | ||
1238 | |||
1239 | PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)", | ||
1240 | pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name)); | ||
1241 | |||
1242 | PVR_DBG_BREAK; | ||
1243 | } | ||
1244 | break; | ||
1245 | |||
1246 | |||
1247 | case IMPORTED_RESOURCE_SPAN_START: | ||
1248 | |||
1249 | if (!((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) || | ||
1250 | (eNextSpan == IMPORTED_RESOURCE_SPAN_FREE))) | ||
1251 | { | ||
1252 | |||
1253 | PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)", | ||
1254 | pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name)); | ||
1255 | |||
1256 | PVR_DBG_BREAK; | ||
1257 | } | ||
1258 | break; | ||
1259 | |||
1260 | default: | ||
1261 | PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)", | ||
1262 | pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name)); | ||
1263 | |||
1264 | PVR_DBG_BREAK; | ||
1265 | break; | ||
1266 | } | ||
1267 | pSegment = pSegment->pNextSegment; | ||
1268 | } | ||
1269 | } | ||
1270 | else if (pSegment->eResourceType == NON_IMPORTED_RESOURCE_TYPE) | ||
1271 | { | ||
1272 | PVR_ASSERT((pSegment->eResourceSpan == RESOURCE_SPAN_FREE) || (pSegment->eResourceSpan == RESOURCE_SPAN_LIVE)); | ||
1273 | |||
1274 | while (pSegment->pNextSegment) | ||
1275 | { | ||
1276 | eNextSpan = pSegment->pNextSegment->eResourceSpan; | ||
1277 | |||
1278 | switch (pSegment->eResourceSpan) | ||
1279 | { | ||
1280 | case RESOURCE_SPAN_LIVE: | ||
1281 | |||
1282 | if (!((eNextSpan == RESOURCE_SPAN_FREE) || | ||
1283 | (eNextSpan == RESOURCE_SPAN_LIVE))) | ||
1284 | { | ||
1285 | |||
1286 | PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)", | ||
1287 | pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name)); | ||
1288 | |||
1289 | PVR_DBG_BREAK; | ||
1290 | } | ||
1291 | break; | ||
1292 | |||
1293 | case RESOURCE_SPAN_FREE: | ||
1294 | |||
1295 | if (!((eNextSpan == RESOURCE_SPAN_FREE) || | ||
1296 | (eNextSpan == RESOURCE_SPAN_LIVE))) | ||
1297 | { | ||
1298 | |||
1299 | PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)", | ||
1300 | pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name)); | ||
1301 | |||
1302 | PVR_DBG_BREAK; | ||
1303 | } | ||
1304 | break; | ||
1305 | |||
1306 | default: | ||
1307 | PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)", | ||
1308 | pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name)); | ||
1309 | |||
1310 | PVR_DBG_BREAK; | ||
1311 | break; | ||
1312 | } | ||
1313 | pSegment = pSegment->pNextSegment; | ||
1314 | } | ||
1315 | |||
1316 | } | ||
1317 | else | ||
1318 | { | ||
1319 | PVR_DPF ((PVR_DBG_ERROR,"ValidateArena ERROR: pSegment->eResourceType unrecognized")); | ||
1320 | |||
1321 | PVR_DBG_BREAK; | ||
1322 | } | ||
1323 | |||
1324 | return 0; | ||
1325 | } | ||
1326 | |||
1327 | #endif | ||
1328 | |||
1329 | |||
1330 | IMG_VOID | ||
1331 | RA_Free (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_BOOL bFreeBackingStore) | ||
1332 | { | ||
1333 | BT *pBT; | ||
1334 | |||
1335 | PVR_ASSERT (pArena != IMG_NULL); | ||
1336 | |||
1337 | if (pArena == IMG_NULL) | ||
1338 | { | ||
1339 | PVR_DPF ((PVR_DBG_ERROR,"RA_Free: invalid parameter - pArena")); | ||
1340 | return; | ||
1341 | } | ||
1342 | |||
1343 | #ifdef USE_BM_FREESPACE_CHECK | ||
1344 | CheckBMFreespace(); | ||
1345 | #endif | ||
1346 | |||
1347 | PVR_DPF ((PVR_DBG_MESSAGE, | ||
1348 | "RA_Free: name='%s', base=0x%x", pArena->name, base)); | ||
1349 | |||
1350 | pBT = (BT *) HASH_Remove (pArena->pSegmentHash, base); | ||
1351 | PVR_ASSERT (pBT != IMG_NULL); | ||
1352 | |||
1353 | if (pBT) | ||
1354 | { | ||
1355 | PVR_ASSERT (pBT->base == base); | ||
1356 | |||
1357 | #ifdef RA_STATS | ||
1358 | pArena->sStatistics.uCumulativeFrees++; | ||
1359 | #endif | ||
1360 | |||
1361 | #ifdef USE_BM_FREESPACE_CHECK | ||
1362 | { | ||
1363 | IMG_BYTE* p; | ||
1364 | IMG_BYTE* endp; | ||
1365 | |||
1366 | p = (IMG_BYTE*)pBT->base + SysGetDevicePhysOffset(); | ||
1367 | endp = (IMG_BYTE*)((IMG_UINT32)(p + pBT->uSize)); | ||
1368 | while ((IMG_UINT32)p & 3) | ||
1369 | { | ||
1370 | *p++ = 0xAA; | ||
1371 | } | ||
1372 | while (p < (IMG_BYTE*)((IMG_UINT32)endp & 0xfffffffc)) | ||
1373 | { | ||
1374 | *(IMG_UINT32*)p = 0xAAAAAAAA; | ||
1375 | p += sizeof(IMG_UINT32); | ||
1376 | } | ||
1377 | while (p < endp) | ||
1378 | { | ||
1379 | *p++ = 0xAA; | ||
1380 | } | ||
1381 | PVR_DPF((PVR_DBG_MESSAGE,"BM_FREESPACE_CHECK: RA_Free Cleared %08X to %08X (size=0x%x)",(IMG_BYTE*)pBT->base + SysGetDevicePhysOffset(),endp-1,pBT->uSize)); | ||
1382 | } | ||
1383 | #endif | ||
1384 | _FreeBT (pArena, pBT, bFreeBackingStore); | ||
1385 | } | ||
1386 | } | ||
1387 | |||
1388 | |||
1389 | IMG_BOOL RA_GetNextLiveSegment(IMG_HANDLE hArena, RA_SEGMENT_DETAILS *psSegDetails) | ||
1390 | { | ||
1391 | BT *pBT; | ||
1392 | |||
1393 | if (psSegDetails->hSegment) | ||
1394 | { | ||
1395 | pBT = (BT *)psSegDetails->hSegment; | ||
1396 | } | ||
1397 | else | ||
1398 | { | ||
1399 | RA_ARENA *pArena = (RA_ARENA *)hArena; | ||
1400 | |||
1401 | pBT = pArena->pHeadSegment; | ||
1402 | } | ||
1403 | |||
1404 | while (pBT != IMG_NULL) | ||
1405 | { | ||
1406 | if (pBT->type == btt_live) | ||
1407 | { | ||
1408 | psSegDetails->uiSize = pBT->uSize; | ||
1409 | psSegDetails->sCpuPhyAddr.uiAddr = pBT->base; | ||
1410 | psSegDetails->hSegment = (IMG_HANDLE)pBT->pNextSegment; | ||
1411 | |||
1412 | return IMG_TRUE; | ||
1413 | } | ||
1414 | |||
1415 | pBT = pBT->pNextSegment; | ||
1416 | } | ||
1417 | |||
1418 | psSegDetails->uiSize = 0; | ||
1419 | psSegDetails->sCpuPhyAddr.uiAddr = 0; | ||
1420 | psSegDetails->hSegment = (IMG_HANDLE)IMG_UNDEF; | ||
1421 | |||
1422 | return IMG_FALSE; | ||
1423 | } | ||
1424 | |||
1425 | |||
1426 | #ifdef USE_BM_FREESPACE_CHECK | ||
1427 | RA_ARENA* pJFSavedArena = IMG_NULL; | ||
1428 | |||
1429 | IMG_VOID CheckBMFreespace(IMG_VOID) | ||
1430 | { | ||
1431 | BT *pBT; | ||
1432 | IMG_BYTE* p; | ||
1433 | IMG_BYTE* endp; | ||
1434 | |||
1435 | if (pJFSavedArena != IMG_NULL) | ||
1436 | { | ||
1437 | for (pBT=pJFSavedArena->pHeadSegment; pBT!=IMG_NULL; pBT=pBT->pNextSegment) | ||
1438 | { | ||
1439 | if (pBT->type == btt_free) | ||
1440 | { | ||
1441 | p = (IMG_BYTE*)pBT->base + SysGetDevicePhysOffset(); | ||
1442 | endp = (IMG_BYTE*)((IMG_UINT32)(p + pBT->uSize) & 0xfffffffc); | ||
1443 | |||
1444 | while ((IMG_UINT32)p & 3) | ||
1445 | { | ||
1446 | if (*p++ != 0xAA) | ||
1447 | { | ||
1448 | fprintf(stderr,"BM_FREESPACE_CHECK: Blank space at %08X has changed to 0x%x\n",p,*(IMG_UINT32*)p); | ||
1449 | for (;;); | ||
1450 | break; | ||
1451 | } | ||
1452 | } | ||
1453 | while (p < endp) | ||
1454 | { | ||
1455 | if (*(IMG_UINT32*)p != 0xAAAAAAAA) | ||
1456 | { | ||
1457 | fprintf(stderr,"BM_FREESPACE_CHECK: Blank space at %08X has changed to 0x%x\n",p,*(IMG_UINT32*)p); | ||
1458 | for (;;); | ||
1459 | break; | ||
1460 | } | ||
1461 | p += 4; | ||
1462 | } | ||
1463 | } | ||
1464 | } | ||
1465 | } | ||
1466 | } | ||
1467 | #endif | ||
1468 | |||
1469 | |||
1470 | #if (defined(CONFIG_PROC_FS) && defined(DEBUG)) || defined (RA_STATS) | ||
1471 | static IMG_CHAR * | ||
1472 | _BTType (IMG_INT eType) | ||
1473 | { | ||
1474 | switch (eType) | ||
1475 | { | ||
1476 | case btt_span: return "span"; | ||
1477 | case btt_free: return "free"; | ||
1478 | case btt_live: return "live"; | ||
1479 | } | ||
1480 | return "junk"; | ||
1481 | } | ||
1482 | #endif | ||
1483 | |||
1484 | #if defined(ENABLE_RA_DUMP) | ||
1485 | IMG_VOID | ||
1486 | RA_Dump (RA_ARENA *pArena) | ||
1487 | { | ||
1488 | BT *pBT; | ||
1489 | PVR_ASSERT (pArena != IMG_NULL); | ||
1490 | PVR_DPF ((PVR_DBG_MESSAGE,"Arena '%s':", pArena->name)); | ||
1491 | PVR_DPF ((PVR_DBG_MESSAGE," alloc=%08X free=%08X handle=%08X quantum=%d", | ||
1492 | pArena->pImportAlloc, pArena->pImportFree, pArena->pImportHandle, | ||
1493 | pArena->uQuantum)); | ||
1494 | PVR_DPF ((PVR_DBG_MESSAGE," segment Chain:")); | ||
1495 | if (pArena->pHeadSegment != IMG_NULL && | ||
1496 | pArena->pHeadSegment->pPrevSegment != IMG_NULL) | ||
1497 | PVR_DPF ((PVR_DBG_MESSAGE," error: head boundary tag has invalid pPrevSegment")); | ||
1498 | if (pArena->pTailSegment != IMG_NULL && | ||
1499 | pArena->pTailSegment->pNextSegment != IMG_NULL) | ||
1500 | PVR_DPF ((PVR_DBG_MESSAGE," error: tail boundary tag has invalid pNextSegment")); | ||
1501 | |||
1502 | for (pBT=pArena->pHeadSegment; pBT!=IMG_NULL; pBT=pBT->pNextSegment) | ||
1503 | { | ||
1504 | PVR_DPF ((PVR_DBG_MESSAGE,"\tbase=0x%x size=0x%x type=%s ref=%08X", | ||
1505 | (IMG_UINT32) pBT->base, pBT->uSize, _BTType (pBT->type), | ||
1506 | pBT->pRef)); | ||
1507 | } | ||
1508 | |||
1509 | #ifdef HASH_TRACE | ||
1510 | HASH_Dump (pArena->pSegmentHash); | ||
1511 | #endif | ||
1512 | } | ||
1513 | #endif | ||
1514 | |||
1515 | |||
1516 | #if defined(CONFIG_PROC_FS) && defined(DEBUG) | ||
1517 | |||
1518 | |||
1519 | static void RA_ProcSeqShowInfo(struct seq_file *sfile, void* el) | ||
1520 | { | ||
1521 | PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)sfile->private; | ||
1522 | RA_ARENA *pArena = (RA_ARENA *)handlers->data; | ||
1523 | IMG_INT off = (IMG_INT)el; | ||
1524 | |||
1525 | switch (off) | ||
1526 | { | ||
1527 | case 1: | ||
1528 | seq_printf(sfile, "quantum\t\t\t%u\n", pArena->uQuantum); | ||
1529 | break; | ||
1530 | case 2: | ||
1531 | seq_printf(sfile, "import_handle\t\t%08X\n", (IMG_UINT)pArena->pImportHandle); | ||
1532 | break; | ||
1533 | #ifdef RA_STATS | ||
1534 | case 3: | ||
1535 | seq_printf(sfile,"span count\t\t%u\n", pArena->sStatistics.uSpanCount); | ||
1536 | break; | ||
1537 | case 4: | ||
1538 | seq_printf(sfile, "live segment count\t%u\n", pArena->sStatistics.uLiveSegmentCount); | ||
1539 | break; | ||
1540 | case 5: | ||
1541 | seq_printf(sfile, "free segment count\t%u\n", pArena->sStatistics.uFreeSegmentCount); | ||
1542 | break; | ||
1543 | case 6: | ||
1544 | seq_printf(sfile, "free resource count\t%u (0x%x)\n", | ||
1545 | pArena->sStatistics.uFreeResourceCount, | ||
1546 | (IMG_UINT)pArena->sStatistics.uFreeResourceCount); | ||
1547 | break; | ||
1548 | case 7: | ||
1549 | seq_printf(sfile, "total allocs\t\t%u\n", pArena->sStatistics.uCumulativeAllocs); | ||
1550 | break; | ||
1551 | case 8: | ||
1552 | seq_printf(sfile, "total frees\t\t%u\n", pArena->sStatistics.uCumulativeFrees); | ||
1553 | break; | ||
1554 | case 9: | ||
1555 | seq_printf(sfile, "import count\t\t%u\n", pArena->sStatistics.uImportCount); | ||
1556 | break; | ||
1557 | case 10: | ||
1558 | seq_printf(sfile, "export count\t\t%u\n", pArena->sStatistics.uExportCount); | ||
1559 | break; | ||
1560 | #endif | ||
1561 | } | ||
1562 | |||
1563 | } | ||
1564 | |||
1565 | static void* RA_ProcSeqOff2ElementInfo(struct seq_file * sfile, loff_t off) | ||
1566 | { | ||
1567 | #ifdef RA_STATS | ||
1568 | if(off <= 9) | ||
1569 | #else | ||
1570 | if(off <= 1) | ||
1571 | #endif | ||
1572 | return (void*)(IMG_INT)(off+1); | ||
1573 | return 0; | ||
1574 | } | ||
1575 | |||
1576 | static void RA_ProcSeqShowRegs(struct seq_file *sfile, void* el) | ||
1577 | { | ||
1578 | PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)sfile->private; | ||
1579 | RA_ARENA *pArena = (RA_ARENA *)handlers->data; | ||
1580 | BT *pBT = (BT*)el; | ||
1581 | |||
1582 | if (el == PVR_PROC_SEQ_START_TOKEN) | ||
1583 | { | ||
1584 | seq_printf(sfile, "Arena \"%s\"\nBase Size Type Ref\n", pArena->name); | ||
1585 | return; | ||
1586 | } | ||
1587 | |||
1588 | if (pBT) | ||
1589 | { | ||
1590 | seq_printf(sfile, "%08x %8x %4s %08x\n", | ||
1591 | (IMG_UINT)pBT->base, (IMG_UINT)pBT->uSize, _BTType (pBT->type), | ||
1592 | (IMG_UINT)pBT->psMapping); | ||
1593 | } | ||
1594 | } | ||
1595 | |||
1596 | static void* RA_ProcSeqOff2ElementRegs(struct seq_file * sfile, loff_t off) | ||
1597 | { | ||
1598 | PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)sfile->private; | ||
1599 | RA_ARENA *pArena = (RA_ARENA *)handlers->data; | ||
1600 | BT *pBT = 0; | ||
1601 | |||
1602 | if(off == 0) | ||
1603 | return PVR_PROC_SEQ_START_TOKEN; | ||
1604 | |||
1605 | for (pBT=pArena->pHeadSegment; --off && pBT; pBT=pBT->pNextSegment); | ||
1606 | |||
1607 | return (void*)pBT; | ||
1608 | } | ||
1609 | |||
1610 | #endif | ||
1611 | |||
1612 | |||
1613 | #ifdef RA_STATS | ||
1614 | PVRSRV_ERROR RA_GetStats(RA_ARENA *pArena, | ||
1615 | IMG_CHAR **ppszStr, | ||
1616 | IMG_UINT32 *pui32StrLen) | ||
1617 | { | ||
1618 | IMG_CHAR *pszStr = *ppszStr; | ||
1619 | IMG_UINT32 ui32StrLen = *pui32StrLen; | ||
1620 | IMG_INT32 i32Count; | ||
1621 | BT *pBT; | ||
1622 | |||
1623 | CHECK_SPACE(ui32StrLen); | ||
1624 | i32Count = OSSNPrintf(pszStr, 100, "\nArena '%s':\n", pArena->name); | ||
1625 | UPDATE_SPACE(pszStr, i32Count, ui32StrLen); | ||
1626 | |||
1627 | |||
1628 | CHECK_SPACE(ui32StrLen); | ||
1629 | i32Count = OSSNPrintf(pszStr, 100, " allocCB=%p freeCB=%p handle=%p quantum=%d\n", | ||
1630 | pArena->pImportAlloc, | ||
1631 | pArena->pImportFree, | ||
1632 | pArena->pImportHandle, | ||
1633 | pArena->uQuantum); | ||
1634 | UPDATE_SPACE(pszStr, i32Count, ui32StrLen); | ||
1635 | |||
1636 | CHECK_SPACE(ui32StrLen); | ||
1637 | i32Count = OSSNPrintf(pszStr, 100, "span count\t\t%u\n", pArena->sStatistics.uSpanCount); | ||
1638 | UPDATE_SPACE(pszStr, i32Count, ui32StrLen); | ||
1639 | |||
1640 | CHECK_SPACE(ui32StrLen); | ||
1641 | i32Count = OSSNPrintf(pszStr, 100, "live segment count\t%u\n", pArena->sStatistics.uLiveSegmentCount); | ||
1642 | UPDATE_SPACE(pszStr, i32Count, ui32StrLen); | ||
1643 | |||
1644 | CHECK_SPACE(ui32StrLen); | ||
1645 | i32Count = OSSNPrintf(pszStr, 100, "free segment count\t%u\n", pArena->sStatistics.uFreeSegmentCount); | ||
1646 | UPDATE_SPACE(pszStr, i32Count, ui32StrLen); | ||
1647 | |||
1648 | CHECK_SPACE(ui32StrLen); | ||
1649 | i32Count = OSSNPrintf(pszStr, 100, "free resource count\t%u (0x%x)\n", | ||
1650 | pArena->sStatistics.uFreeResourceCount, | ||
1651 | (IMG_UINT)pArena->sStatistics.uFreeResourceCount); | ||
1652 | UPDATE_SPACE(pszStr, i32Count, ui32StrLen); | ||
1653 | |||
1654 | CHECK_SPACE(ui32StrLen); | ||
1655 | i32Count = OSSNPrintf(pszStr, 100, "total allocs\t\t%u\n", pArena->sStatistics.uCumulativeAllocs); | ||
1656 | UPDATE_SPACE(pszStr, i32Count, ui32StrLen); | ||
1657 | |||
1658 | CHECK_SPACE(ui32StrLen); | ||
1659 | i32Count = OSSNPrintf(pszStr, 100, "total frees\t\t%u\n", pArena->sStatistics.uCumulativeFrees); | ||
1660 | UPDATE_SPACE(pszStr, i32Count, ui32StrLen); | ||
1661 | |||
1662 | CHECK_SPACE(ui32StrLen); | ||
1663 | i32Count = OSSNPrintf(pszStr, 100, "import count\t\t%u\n", pArena->sStatistics.uImportCount); | ||
1664 | UPDATE_SPACE(pszStr, i32Count, ui32StrLen); | ||
1665 | |||
1666 | CHECK_SPACE(ui32StrLen); | ||
1667 | i32Count = OSSNPrintf(pszStr, 100, "export count\t\t%u\n", pArena->sStatistics.uExportCount); | ||
1668 | UPDATE_SPACE(pszStr, i32Count, ui32StrLen); | ||
1669 | |||
1670 | CHECK_SPACE(ui32StrLen); | ||
1671 | i32Count = OSSNPrintf(pszStr, 100, " segment Chain:\n"); | ||
1672 | UPDATE_SPACE(pszStr, i32Count, ui32StrLen); | ||
1673 | |||
1674 | if (pArena->pHeadSegment != IMG_NULL && | ||
1675 | pArena->pHeadSegment->pPrevSegment != IMG_NULL) | ||
1676 | { | ||
1677 | CHECK_SPACE(ui32StrLen); | ||
1678 | i32Count = OSSNPrintf(pszStr, 100, " error: head boundary tag has invalid pPrevSegment\n"); | ||
1679 | UPDATE_SPACE(pszStr, i32Count, ui32StrLen); | ||
1680 | } | ||
1681 | |||
1682 | if (pArena->pTailSegment != IMG_NULL && | ||
1683 | pArena->pTailSegment->pNextSegment != IMG_NULL) | ||
1684 | { | ||
1685 | CHECK_SPACE(ui32StrLen); | ||
1686 | i32Count = OSSNPrintf(pszStr, 100, " error: tail boundary tag has invalid pNextSegment\n"); | ||
1687 | UPDATE_SPACE(pszStr, i32Count, ui32StrLen); | ||
1688 | } | ||
1689 | |||
1690 | for (pBT=pArena->pHeadSegment; pBT!=IMG_NULL; pBT=pBT->pNextSegment) | ||
1691 | { | ||
1692 | CHECK_SPACE(ui32StrLen); | ||
1693 | i32Count = OSSNPrintf(pszStr, 100, "\tbase=0x%x size=0x%x type=%s ref=%p\n", | ||
1694 | (IMG_UINT32) pBT->base, | ||
1695 | pBT->uSize, | ||
1696 | _BTType(pBT->type), | ||
1697 | pBT->psMapping); | ||
1698 | UPDATE_SPACE(pszStr, i32Count, ui32StrLen); | ||
1699 | } | ||
1700 | |||
1701 | *ppszStr = pszStr; | ||
1702 | *pui32StrLen = ui32StrLen; | ||
1703 | |||
1704 | return PVRSRV_OK; | ||
1705 | } | ||
1706 | |||
1707 | PVRSRV_ERROR RA_GetStatsFreeMem(RA_ARENA *pArena, | ||
1708 | IMG_CHAR **ppszStr, | ||
1709 | IMG_UINT32 *pui32StrLen) | ||
1710 | { | ||
1711 | IMG_CHAR *pszStr = *ppszStr; | ||
1712 | IMG_UINT32 ui32StrLen = *pui32StrLen; | ||
1713 | IMG_INT32 i32Count; | ||
1714 | CHECK_SPACE(ui32StrLen); | ||
1715 | i32Count = OSSNPrintf(pszStr, 100, "Bytes free: Arena %-30s: %u (0x%x)\n", pArena->name, | ||
1716 | pArena->sStatistics.uFreeResourceCount, | ||
1717 | pArena->sStatistics.uFreeResourceCount); | ||
1718 | UPDATE_SPACE(pszStr, i32Count, ui32StrLen); | ||
1719 | *ppszStr = pszStr; | ||
1720 | *pui32StrLen = ui32StrLen; | ||
1721 | |||
1722 | return PVRSRV_OK; | ||
1723 | } | ||
1724 | #endif | ||
1725 | |||