aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/pvr/ra.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/pvr/ra.c')
-rw-r--r--drivers/gpu/pvr/ra.c1725
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
46typedef 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
57typedef enum RESOURCE_TYPE_TAG {
58
59 IMPORTED_RESOURCE_TYPE = 20,
60 NON_IMPORTED_RESOURCE_TYPE
61
62} RESOURCE_TYPE;
63
64
65static IMG_UINT32 ui32BoundaryTagID = 0;
66
67IMG_UINT32 ValidateArena(RA_ARENA *pArena);
68#endif
69
70struct _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};
101typedef struct _BT_ BT;
102
103
104struct _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)
154IMG_VOID RA_Dump (RA_ARENA *pArena);
155#endif
156
157#if defined(CONFIG_PROC_FS) && defined(DEBUG)
158
159static void RA_ProcSeqShowInfo(struct seq_file *sfile, void* el);
160static void* RA_ProcSeqOff2ElementInfo(struct seq_file * sfile, loff_t off);
161
162static void RA_ProcSeqShowRegs(struct seq_file *sfile, void* el);
163static void* RA_ProcSeqOff2ElementRegs(struct seq_file * sfile, loff_t off);
164
165#endif
166
167#ifdef USE_BM_FREESPACE_CHECK
168IMG_VOID CheckBMFreespace(IMG_VOID);
169#endif
170
171#if defined(CONFIG_PROC_FS) && defined(DEBUG)
172static 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
188static 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
206static IMG_UINT32
207pvr_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
219static 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
244static 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
290static 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
304static 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
366static 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
379static 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
392static 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
419static 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
445static 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
480static 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
570static 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
683static 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
843RA_ARENA *
844RA_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
958insert_fail:
959 HASH_Delete (pArena->pSegmentHash);
960hash_fail:
961 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RA_ARENA), pArena, IMG_NULL);
962
963arena_fail:
964 return IMG_NULL;
965}
966
967IMG_VOID
968RA_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
1026IMG_BOOL
1027RA_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
1048IMG_BOOL
1049RA_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
1066IMG_BOOL
1067RA_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
1183IMG_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
1330IMG_VOID
1331RA_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
1389IMG_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
1427RA_ARENA* pJFSavedArena = IMG_NULL;
1428
1429IMG_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)
1471static 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)
1485IMG_VOID
1486RA_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
1519static 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
1565static 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
1576static 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
1596static 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
1614PVRSRV_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
1707PVRSRV_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