1 /**********************************************************************
3 * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
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.
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.
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.
18 * The full GNU General Public License is included in this distribution in
19 * the file called "COPYING".
21 * Contact Information:
22 * Imagination Technologies Ltd. <gpl-support@imgtec.com>
23 * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
25 ******************************************************************************/
27 #include "services_headers.h"
30 #include "buffer_manager.h"
33 #include <linux/kernel.h>
37 #define MINIMUM_HASH_SIZE 64
49 struct BT *pNextSegment;
50 struct BT *pPrevSegment;
55 struct BM_MAPPING *psMapping;
62 IMG_BOOL(*pImportAlloc)(void *, size_t uSize, size_t *pActualSize,
63 struct BM_MAPPING **ppsMapping, u32 uFlags,
65 void (*pImportFree)(void *, u32, struct BM_MAPPING *psMapping);
66 void (*pBackingStoreFree)(void *, u32, u32, void *);
68 #define FREE_TABLE_LIMIT 32
69 struct BT *aHeadFree[FREE_TABLE_LIMIT];
70 struct BT *pHeadSegment;
71 struct BT *pTailSegment;
72 struct HASH_TABLE *pSegmentHash;
74 struct RA_STATISTICS sStatistics;
76 #if defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_DEBUG_EXTRA)
77 #define PROC_NAME_SIZE 32
78 char szProcInfoName[PROC_NAME_SIZE];
79 char szProcSegsName[PROC_NAME_SIZE];
80 IMG_BOOL bInitProcEntry;
84 #if defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_DEBUG_EXTRA)
85 static int RA_DumpSegs(char *page, char **start, off_t off, int count, int *eof,
87 static int RA_DumpInfo(char *page, char **start, off_t off, int count, int *eof,
91 #if defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_DEBUG_EXTRA)
92 static char *ReplaceSpaces(char *const pS)
96 for (pT = pS; *pT != 0; pT++)
97 if (*pT == ' ' || *pT == '\t')
104 static IMG_BOOL _RequestAllocFail(void *_h, size_t _uSize, size_t *_pActualSize,
105 struct BM_MAPPING **_ppsMapping,
106 u32 _uFlags, u32 *_pBase)
108 PVR_UNREFERENCED_PARAMETER(_h);
109 PVR_UNREFERENCED_PARAMETER(_uSize);
110 PVR_UNREFERENCED_PARAMETER(_pActualSize);
111 PVR_UNREFERENCED_PARAMETER(_ppsMapping);
112 PVR_UNREFERENCED_PARAMETER(_uFlags);
113 PVR_UNREFERENCED_PARAMETER(_pBase);
118 static u32 pvr_log2(size_t n)
129 static enum PVRSRV_ERROR _SegmentListInsertAfter(struct RA_ARENA *pArena,
130 struct BT *pInsertionPoint,
133 PVR_ASSERT(pArena != NULL);
134 PVR_ASSERT(pInsertionPoint != NULL);
136 if ((pInsertionPoint == NULL) || (pArena == NULL)) {
137 PVR_DPF(PVR_DBG_ERROR,
138 "_SegmentListInsertAfter: invalid parameters");
139 return PVRSRV_ERROR_INVALID_PARAMS;
142 pBT->pNextSegment = pInsertionPoint->pNextSegment;
143 pBT->pPrevSegment = pInsertionPoint;
144 if (pInsertionPoint->pNextSegment == NULL)
145 pArena->pTailSegment = pBT;
147 pInsertionPoint->pNextSegment->pPrevSegment = pBT;
148 pInsertionPoint->pNextSegment = pBT;
153 static enum PVRSRV_ERROR _SegmentListInsert(struct RA_ARENA *pArena,
156 enum PVRSRV_ERROR eError = PVRSRV_OK;
158 if (pArena->pHeadSegment == NULL) {
159 pArena->pHeadSegment = pArena->pTailSegment = pBT;
160 pBT->pNextSegment = pBT->pPrevSegment = NULL;
163 if (pBT->base < pArena->pHeadSegment->base) {
164 pBT->pNextSegment = pArena->pHeadSegment;
165 pArena->pHeadSegment->pPrevSegment = pBT;
166 pArena->pHeadSegment = pBT;
167 pBT->pPrevSegment = NULL;
169 pBTScan = pArena->pHeadSegment;
171 while ((pBTScan->pNextSegment != NULL) &&
172 (pBT->base >= pBTScan->pNextSegment->base))
173 pBTScan = pBTScan->pNextSegment;
175 eError = _SegmentListInsertAfter(pArena, pBTScan, pBT);
176 if (eError != PVRSRV_OK)
183 static void _SegmentListRemove(struct RA_ARENA *pArena, struct BT *pBT)
185 if (pBT->pPrevSegment == NULL)
186 pArena->pHeadSegment = pBT->pNextSegment;
188 pBT->pPrevSegment->pNextSegment = pBT->pNextSegment;
190 if (pBT->pNextSegment == NULL)
191 pArena->pTailSegment = pBT->pPrevSegment;
193 pBT->pNextSegment->pPrevSegment = pBT->pPrevSegment;
196 static struct BT *_SegmentSplit(struct RA_ARENA *pArena, struct BT *pBT,
199 struct BT *pNeighbour;
201 PVR_ASSERT(pArena != NULL);
203 if (pArena == NULL) {
204 PVR_DPF(PVR_DBG_ERROR,
205 "_SegmentSplit: invalid parameter - pArena");
209 if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
211 (void **) &pNeighbour, NULL) != PVRSRV_OK)
214 pNeighbour->pPrevSegment = pBT;
215 pNeighbour->pNextSegment = pBT->pNextSegment;
216 if (pBT->pNextSegment == NULL)
217 pArena->pTailSegment = pNeighbour;
219 pBT->pNextSegment->pPrevSegment = pNeighbour;
220 pBT->pNextSegment = pNeighbour;
222 pNeighbour->type = btt_free;
223 pNeighbour->uSize = pBT->uSize - uSize;
224 pNeighbour->base = pBT->base + uSize;
225 pNeighbour->psMapping = pBT->psMapping;
230 static void _FreeListInsert(struct RA_ARENA *pArena, struct BT *pBT)
233 uIndex = pvr_log2(pBT->uSize);
234 pBT->type = btt_free;
235 pBT->pNextFree = pArena->aHeadFree[uIndex];
236 pBT->pPrevFree = NULL;
237 if (pArena->aHeadFree[uIndex] != NULL)
238 pArena->aHeadFree[uIndex]->pPrevFree = pBT;
239 pArena->aHeadFree[uIndex] = pBT;
242 static void _FreeListRemove(struct RA_ARENA *pArena, struct BT *pBT)
245 uIndex = pvr_log2(pBT->uSize);
246 if (pBT->pNextFree != NULL)
247 pBT->pNextFree->pPrevFree = pBT->pPrevFree;
248 if (pBT->pPrevFree == NULL)
249 pArena->aHeadFree[uIndex] = pBT->pNextFree;
251 pBT->pPrevFree->pNextFree = pBT->pNextFree;
254 static struct BT *_BuildSpanMarker(u32 base, size_t uSize)
258 if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
260 (void **) &pBT, NULL) != PVRSRV_OK)
263 pBT->type = btt_span;
266 pBT->psMapping = NULL;
271 static struct BT *_BuildBT(u32 base, size_t uSize)
275 if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
277 (void **) &pBT, NULL) != PVRSRV_OK)
280 pBT->type = btt_free;
287 static struct BT *_InsertResource(struct RA_ARENA *pArena, u32 base,
291 PVR_ASSERT(pArena != NULL);
292 if (pArena == NULL) {
293 PVR_DPF(PVR_DBG_ERROR,
294 "_InsertResource: invalid parameter - pArena");
298 pBT = _BuildBT(base, uSize);
300 if (_SegmentListInsert(pArena, pBT) != PVRSRV_OK) {
301 PVR_DPF(PVR_DBG_ERROR,
302 "_InsertResource: call to _SegmentListInsert failed");
305 _FreeListInsert(pArena, pBT);
307 pArena->sStatistics.uTotalResourceCount += uSize;
308 pArena->sStatistics.uFreeResourceCount += uSize;
309 pArena->sStatistics.uSpanCount++;
315 static struct BT *_InsertResourceSpan(struct RA_ARENA *pArena, u32 base,
318 enum PVRSRV_ERROR eError;
319 struct BT *pSpanStart;
323 PVR_ASSERT(pArena != NULL);
324 if (pArena == NULL) {
325 PVR_DPF(PVR_DBG_ERROR,
326 "_InsertResourceSpan: invalid parameter - pArena");
330 PVR_DPF(PVR_DBG_MESSAGE,
331 "RA_InsertResourceSpan: arena='%s', base=0x%x, size=0x%x",
332 pArena->name, base, uSize);
334 pSpanStart = _BuildSpanMarker(base, uSize);
335 if (pSpanStart == NULL)
337 pSpanEnd = _BuildSpanMarker(base + uSize, 0);
338 if (pSpanEnd == NULL)
341 pBT = _BuildBT(base, uSize);
345 eError = _SegmentListInsert(pArena, pSpanStart);
346 if (eError != PVRSRV_OK)
347 goto fail_SegListInsert;
349 eError = _SegmentListInsertAfter(pArena, pSpanStart, pBT);
350 if (eError != PVRSRV_OK)
351 goto fail_SegListInsert;
353 _FreeListInsert(pArena, pBT);
355 eError = _SegmentListInsertAfter(pArena, pBT, pSpanEnd);
356 if (eError != PVRSRV_OK)
357 goto fail_SegListInsert;
360 pArena->sStatistics.uTotalResourceCount += uSize;
365 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BT), pBT, NULL);
367 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BT), pSpanEnd, NULL);
369 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BT), pSpanStart, NULL);
374 static void _FreeBT(struct RA_ARENA *pArena, struct BT *pBT,
375 IMG_BOOL bFreeBackingStore)
377 struct BT *pNeighbour;
381 PVR_ASSERT(pArena != NULL);
382 PVR_ASSERT(pBT != NULL);
384 if ((pArena == NULL) || (pBT == NULL)) {
385 PVR_DPF(PVR_DBG_ERROR, "_FreeBT: invalid parameter");
389 pArena->sStatistics.uLiveSegmentCount--;
390 pArena->sStatistics.uFreeSegmentCount++;
391 pArena->sStatistics.uFreeResourceCount += pBT->uSize;
394 uOrigBase = pBT->base;
395 uOrigSize = pBT->uSize;
397 pNeighbour = pBT->pPrevSegment;
398 if (pNeighbour != NULL && pNeighbour->type == btt_free &&
399 pNeighbour->base + pNeighbour->uSize == pBT->base) {
400 _FreeListRemove(pArena, pNeighbour);
401 _SegmentListRemove(pArena, pNeighbour);
402 pBT->base = pNeighbour->base;
403 pBT->uSize += pNeighbour->uSize;
404 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BT),
407 pArena->sStatistics.uFreeSegmentCount--;
411 pNeighbour = pBT->pNextSegment;
412 if (pNeighbour != NULL && pNeighbour->type == btt_free &&
413 pBT->base + pBT->uSize == pNeighbour->base) {
414 _FreeListRemove(pArena, pNeighbour);
415 _SegmentListRemove(pArena, pNeighbour);
416 pBT->uSize += pNeighbour->uSize;
417 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BT),
420 pArena->sStatistics.uFreeSegmentCount--;
424 if (pArena->pBackingStoreFree != NULL && bFreeBackingStore) {
425 u32 uRoundedStart, uRoundedEnd;
427 uRoundedStart = (uOrigBase / pArena->uQuantum) *
430 if (uRoundedStart < pBT->base)
431 uRoundedStart += pArena->uQuantum;
433 uRoundedEnd = ((uOrigBase + uOrigSize + pArena->uQuantum -
434 1) / pArena->uQuantum) * pArena->uQuantum;
436 if (uRoundedEnd > (pBT->base + pBT->uSize))
437 uRoundedEnd -= pArena->uQuantum;
439 if (uRoundedStart < uRoundedEnd)
440 pArena->pBackingStoreFree(pArena->pImportHandle,
441 uRoundedStart, uRoundedEnd,
445 if (pBT->pNextSegment != NULL && pBT->pNextSegment->type == btt_span &&
446 pBT->pPrevSegment != NULL && pBT->pPrevSegment->type == btt_span) {
447 struct BT *next = pBT->pNextSegment;
448 struct BT *prev = pBT->pPrevSegment;
449 _SegmentListRemove(pArena, next);
450 _SegmentListRemove(pArena, prev);
451 _SegmentListRemove(pArena, pBT);
452 pArena->pImportFree(pArena->pImportHandle, pBT->base,
455 pArena->sStatistics.uSpanCount--;
456 pArena->sStatistics.uExportCount++;
457 pArena->sStatistics.uFreeSegmentCount--;
458 pArena->sStatistics.uFreeResourceCount -= pBT->uSize;
459 pArena->sStatistics.uTotalResourceCount -= pBT->uSize;
461 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BT), next,
463 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BT), prev,
465 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BT), pBT,
468 _FreeListInsert(pArena, pBT);
471 static int alloc_from_bt(struct RA_ARENA *arena, struct BT *bt, u32 start,
472 size_t size, u32 align,
473 struct BM_MAPPING **new_mapping, u32 *new_base)
475 _FreeListRemove(arena, bt);
476 PVR_ASSERT(bt->type == btt_free);
478 arena->sStatistics.uLiveSegmentCount++;
479 arena->sStatistics.uFreeSegmentCount--;
480 arena->sStatistics.uFreeResourceCount -= bt->uSize;
482 if (start > bt->base) {
485 next_bt = _SegmentSplit(arena, bt, start - bt->base);
488 PVR_DPF(PVR_DBG_ERROR, "_AttemptAllocAligned: "
489 "Front split failed");
491 _FreeListInsert(arena, bt);
495 _FreeListInsert(arena, bt);
497 arena->sStatistics.uFreeSegmentCount++;
498 arena->sStatistics.uFreeResourceCount += bt->uSize;
503 if (bt->uSize > size) {
505 next_bt = _SegmentSplit(arena, bt, size);
508 PVR_DPF(PVR_DBG_ERROR, "_AttemptAllocAligned: "
509 "Back split failed");
511 _FreeListInsert(arena, bt);
515 _FreeListInsert(arena, next_bt);
517 arena->sStatistics.uFreeSegmentCount++;
518 arena->sStatistics.uFreeResourceCount += next_bt->uSize;
524 if (!HASH_Insert(arena->pSegmentHash, bt->base, (u32)bt)) {
525 _FreeBT(arena, bt, IMG_FALSE);
530 *new_mapping = bt->psMapping;
532 *new_base = bt->base;
537 static IMG_BOOL _AttemptAllocAligned(struct RA_ARENA *pArena, size_t uSize,
538 struct BM_MAPPING **ppsMapping, u32 uFlags, u32 uAlignment,
542 PVR_ASSERT(pArena != NULL);
543 if (pArena == NULL) {
544 PVR_DPF(PVR_DBG_ERROR,
545 "_AttemptAllocAligned: invalid parameter - pArena");
549 uIndex = pvr_log2(uSize);
551 while (uIndex < FREE_TABLE_LIMIT && pArena->aHeadFree[uIndex] == NULL)
554 for (; uIndex < FREE_TABLE_LIMIT; uIndex++) {
557 pBT = pArena->aHeadFree[uIndex];
561 for (; pBT != NULL; pBT = pBT->pNextFree) {
565 aligned_base = (pBT->base + uAlignment -
566 1) / uAlignment * uAlignment;
568 aligned_base = pBT->base;
569 PVR_DPF(PVR_DBG_MESSAGE,
570 "RA_AttemptAllocAligned: pBT-base=0x%x "
571 "pBT-size=0x%x alignedbase=0x%x size=0x%x",
572 pBT->base, pBT->uSize, aligned_base, uSize);
574 if (pBT->base + pBT->uSize < aligned_base + uSize)
577 if (pBT->psMapping && pBT->psMapping->ui32Flags !=
579 PVR_DPF(PVR_DBG_MESSAGE,
580 "AttemptAllocAligned: mismatch in "
581 "flags. Import has %x, request was %x",
582 pBT->psMapping->ui32Flags, uFlags);
586 if (alloc_from_bt(pArena, pBT, aligned_base, uSize,
587 uFlags, ppsMapping, base) < 0)
597 struct RA_ARENA *RA_Create(char *name, u32 base, size_t uSize,
598 struct BM_MAPPING *psMapping, size_t uQuantum,
599 IMG_BOOL(*imp_alloc) (void *, size_t uSize,
601 struct BM_MAPPING **ppsMapping,
602 u32 _flags, u32 *pBase),
603 void (*imp_free) (void *, u32, struct BM_MAPPING *),
604 void(*backingstore_free) (void *, u32, u32, void *),
607 struct RA_ARENA *pArena;
611 PVR_DPF(PVR_DBG_MESSAGE, "RA_Create: "
612 "name='%s', base=0x%x, uSize=0x%x, alloc=0x%x, free=0x%x",
613 name, base, uSize, imp_alloc, imp_free);
615 if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
617 (void **) &pArena, NULL) != PVRSRV_OK)
621 pArena->pImportAlloc =
622 (imp_alloc != NULL) ? imp_alloc : _RequestAllocFail;
623 pArena->pImportFree = imp_free;
624 pArena->pBackingStoreFree = backingstore_free;
625 pArena->pImportHandle = pImportHandle;
626 for (i = 0; i < FREE_TABLE_LIMIT; i++)
627 pArena->aHeadFree[i] = NULL;
628 pArena->pHeadSegment = NULL;
629 pArena->pTailSegment = NULL;
630 pArena->uQuantum = uQuantum;
633 pArena->sStatistics.uSpanCount = 0;
634 pArena->sStatistics.uLiveSegmentCount = 0;
635 pArena->sStatistics.uFreeSegmentCount = 0;
636 pArena->sStatistics.uFreeResourceCount = 0;
637 pArena->sStatistics.uTotalResourceCount = 0;
638 pArena->sStatistics.uCumulativeAllocs = 0;
639 pArena->sStatistics.uCumulativeFrees = 0;
640 pArena->sStatistics.uImportCount = 0;
641 pArena->sStatistics.uExportCount = 0;
644 #if defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_DEBUG_EXTRA)
645 if (strcmp(pArena->name, "") != 0) {
647 int (*pfnCreateProcEntry) (const char *, read_proc_t,
648 write_proc_t, void *);
650 pArena->bInitProcEntry =
651 !PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL);
653 pfnCreateProcEntry = pArena->bInitProcEntry ? CreateProcEntry :
654 CreatePerProcessProcEntry;
656 ret = snprintf(pArena->szProcInfoName,
657 sizeof(pArena->szProcInfoName), "ra_info_%s",
659 if (ret > 0 && ret < sizeof(pArena->szProcInfoName)) {
660 (void)pfnCreateProcEntry(ReplaceSpaces
661 (pArena->szProcInfoName),
662 RA_DumpInfo, NULL, pArena);
664 pArena->szProcInfoName[0] = 0;
665 PVR_DPF(PVR_DBG_ERROR, "RA_Create: "
666 "couldn't create ra_info proc entry for arena %s",
670 ret = snprintf(pArena->szProcSegsName,
671 sizeof(pArena->szProcSegsName), "ra_segs_%s",
673 if (ret > 0 && ret < sizeof(pArena->szProcInfoName)) {
674 (void)pfnCreateProcEntry(ReplaceSpaces
675 (pArena->szProcSegsName),
676 RA_DumpSegs, NULL, pArena);
678 pArena->szProcSegsName[0] = 0;
679 PVR_DPF(PVR_DBG_ERROR, "RA_Create: "
680 "couldn't create ra_segs proc entry for arena %s",
686 pArena->pSegmentHash = HASH_Create(MINIMUM_HASH_SIZE);
687 if (pArena->pSegmentHash == NULL)
690 uSize = (uSize + uQuantum - 1) / uQuantum * uQuantum;
691 pBT = _InsertResource(pArena, base, uSize);
694 pBT->psMapping = psMapping;
700 HASH_Delete(pArena->pSegmentHash);
702 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct RA_ARENA), pArena,
708 void RA_Delete(struct RA_ARENA *pArena)
712 PVR_ASSERT(pArena != NULL);
714 if (pArena == NULL) {
715 PVR_DPF(PVR_DBG_ERROR,
716 "RA_Delete: invalid parameter - pArena");
720 PVR_DPF(PVR_DBG_MESSAGE, "RA_Delete: name='%s'", pArena->name);
722 for (uIndex = 0; uIndex < FREE_TABLE_LIMIT; uIndex++)
723 pArena->aHeadFree[uIndex] = NULL;
725 while (pArena->pHeadSegment != NULL) {
726 struct BT *pBT = pArena->pHeadSegment;
727 PVR_ASSERT(pBT->type == btt_free);
728 _SegmentListRemove(pArena, pBT);
729 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BT), pBT,
732 pArena->sStatistics.uSpanCount--;
735 #if defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_DEBUG_EXTRA)
737 void (*pfnRemoveProcEntry) (const char *);
741 bInitProcEntry ? RemoveProcEntry :
742 RemovePerProcessProcEntry;
744 if (pArena->szProcInfoName[0] != 0)
745 pfnRemoveProcEntry(pArena->szProcInfoName);
747 if (pArena->szProcSegsName[0] != 0)
748 pfnRemoveProcEntry(pArena->szProcSegsName);
751 HASH_Delete(pArena->pSegmentHash);
752 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct RA_ARENA), pArena,
756 IMG_BOOL RA_TestDelete(struct RA_ARENA *pArena)
758 PVR_ASSERT(pArena != NULL);
761 while (pArena->pHeadSegment != NULL) {
762 struct BT *pBT = pArena->pHeadSegment;
763 if (pBT->type != btt_free)
770 IMG_BOOL RA_Add(struct RA_ARENA *pArena, u32 base, size_t uSize)
772 PVR_ASSERT(pArena != NULL);
774 if (pArena == NULL) {
775 PVR_DPF(PVR_DBG_ERROR, "RA_Add: invalid parameter - pArena");
779 PVR_DPF(PVR_DBG_MESSAGE,
780 "RA_Add: name='%s', base=0x%x, size=0x%x", pArena->name, base,
783 uSize = (uSize + pArena->uQuantum - 1) /
784 pArena->uQuantum * pArena->uQuantum;
785 return (IMG_BOOL)(_InsertResource(pArena, base, uSize) != NULL);
788 IMG_BOOL RA_Alloc(struct RA_ARENA *pArena, size_t uRequestSize,
789 struct BM_MAPPING **ppsMapping, u32 uFlags, u32 uAlignment,
793 size_t uSize = uRequestSize;
795 PVR_ASSERT(pArena != NULL);
797 if (pArena == NULL) {
798 PVR_DPF(PVR_DBG_ERROR,
799 "RA_Alloc: invalid parameter - pArena");
803 PVR_DPF(PVR_DBG_MESSAGE, "RA_Alloc: "
804 "arena='%s', size=0x%x(0x%x), alignment=0x%x",
805 pArena->name, uSize, uRequestSize, uAlignment);
807 bResult = _AttemptAllocAligned(pArena, uSize, ppsMapping, uFlags,
810 struct BM_MAPPING *psImportMapping;
812 size_t uImportSize = uSize;
814 if (uAlignment > pArena->uQuantum)
815 uImportSize += (uAlignment - 1);
818 ((uImportSize + pArena->uQuantum - 1) /
819 pArena->uQuantum) * pArena->uQuantum;
822 pArena->pImportAlloc(pArena->pImportHandle, uImportSize,
823 &uImportSize, &psImportMapping, uFlags,
827 pBT = _InsertResourceSpan(pArena, import_base,
831 pArena->pImportFree(pArena->pImportHandle,
834 PVR_DPF(PVR_DBG_MESSAGE, "RA_Alloc: "
835 "name='%s', size=0x%x failed!",
836 pArena->name, uSize);
840 pBT->psMapping = psImportMapping;
842 pArena->sStatistics.uFreeSegmentCount++;
843 pArena->sStatistics.uFreeResourceCount += uImportSize;
844 pArena->sStatistics.uImportCount++;
845 pArena->sStatistics.uSpanCount++;
847 bResult = _AttemptAllocAligned(pArena, uSize,
848 ppsMapping, uFlags, uAlignment,
851 PVR_DPF(PVR_DBG_MESSAGE, "RA_Alloc: "
852 "name='%s' uAlignment failed!",
858 pArena->sStatistics.uCumulativeAllocs++;
861 PVR_DPF(PVR_DBG_MESSAGE,
862 "RA_Alloc: name='%s', size=0x%x, *base=0x%x = %d",
863 pArena->name, uSize, *base, bResult);
868 void RA_Free(struct RA_ARENA *pArena, u32 base, IMG_BOOL bFreeBackingStore)
872 PVR_ASSERT(pArena != NULL);
874 if (pArena == NULL) {
875 PVR_DPF(PVR_DBG_ERROR, "RA_Free: invalid parameter - pArena");
879 PVR_DPF(PVR_DBG_MESSAGE,
880 "RA_Free: name='%s', base=0x%x", pArena->name, base);
882 pBT = (struct BT *)HASH_Remove(pArena->pSegmentHash, base);
883 PVR_ASSERT(pBT != NULL);
886 PVR_ASSERT(pBT->base == base);
889 pArena->sStatistics.uCumulativeFrees++;
892 _FreeBT(pArena, pBT, bFreeBackingStore);
896 IMG_BOOL RA_GetNextLiveSegment(void *hArena,
897 struct RA_SEGMENT_DETAILS *psSegDetails)
901 if (psSegDetails->hSegment) {
902 pBT = (struct BT *)psSegDetails->hSegment;
904 struct RA_ARENA *pArena = (struct RA_ARENA *)hArena;
905 pBT = pArena->pHeadSegment;
908 while (pBT != NULL) {
909 if (pBT->type == btt_live) {
910 psSegDetails->uiSize = pBT->uSize;
911 psSegDetails->sCpuPhyAddr.uiAddr = pBT->base;
912 psSegDetails->hSegment = (void *) pBT->pNextSegment;
917 pBT = pBT->pNextSegment;
920 psSegDetails->uiSize = 0;
921 psSegDetails->sCpuPhyAddr.uiAddr = 0;
922 psSegDetails->hSegment = (void *) -1;
927 #if (defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_DEBUG_EXTRA)) || \
929 static char *_BTType(int eType)
943 #if defined(ENABLE_RA_DUMP)
944 void RA_Dump(struct RA_ARENA *pArena)
947 PVR_ASSERT(pArena != NULL);
948 PVR_DPF(PVR_DBG_MESSAGE, "Arena '%s':", pArena->name);
949 PVR_DPF(PVR_DBG_MESSAGE,
950 " alloc=%08X free=%08X handle=%08X quantum=%d",
951 pArena->pImportAlloc, pArena->pImportFree,
952 pArena->pImportHandle, pArena->uQuantum);
953 PVR_DPF(PVR_DBG_MESSAGE, " segment Chain:");
954 if (pArena->pHeadSegment != NULL &&
955 pArena->pHeadSegment->pPrevSegment != NULL)
956 PVR_DPF(PVR_DBG_MESSAGE,
957 " error: head boundary tag has invalid pPrevSegment");
958 if (pArena->pTailSegment != NULL &&
959 pArena->pTailSegment->pNextSegment != NULL)
960 PVR_DPF(PVR_DBG_MESSAGE,
961 " error: tail boundary tag has invalid pNextSegment");
963 for (pBT = pArena->pHeadSegment; pBT != NULL; pBT = pBT->pNextSegment)
964 PVR_DPF(PVR_DBG_MESSAGE,
965 "\tbase=0x%x size=0x%x type=%s ref=%08X",
966 (u32) pBT->base, pBT->uSize, _BTType(pBT->type),
972 #if defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_DEBUG_EXTRA)
973 static int RA_DumpSegs(char *page, char **start, off_t off, int count, int *eof,
976 struct BT *pBT = NULL;
978 struct RA_ARENA *pArena = (struct RA_ARENA *)data;
987 return printAppend(page, count, 0,
988 "Arena \"%s\"\nBase Size Type Ref\n",
990 for (pBT = pArena->pHeadSegment; --off && pBT;
991 pBT = pBT->pNextSegment)
994 len = printAppend(page, count, 0, "%08x %8x %4s %08x\n",
995 (unsigned)pBT->base, (unsigned)pBT->uSize,
996 _BTType(pBT->type), (unsigned)pBT->psMapping);
1002 static int RA_DumpInfo(char *page, char **start, off_t off, int count, int *eof,
1006 struct RA_ARENA *pArena = (struct RA_ARENA *)data;
1015 len = printAppend(page, count, 0, "quantum\t\t\t%u\n",
1019 len = printAppend(page, count, 0, "import_handle\t\t%08X\n",
1020 (unsigned)pArena->pImportHandle);
1024 len = printAppend(page, count, 0, "span count\t\t%u\n",
1025 pArena->sStatistics.uSpanCount);
1028 len = printAppend(page, count, 0, "live segment count\t%u\n",
1029 pArena->sStatistics.uLiveSegmentCount);
1032 len = printAppend(page, count, 0, "free segment count\t%u\n",
1033 pArena->sStatistics.uFreeSegmentCount);
1036 len = printAppend(page, count, 0,
1037 "free resource count\t%u (0x%x)\n",
1038 pArena->sStatistics.uFreeResourceCount,
1039 (unsigned)pArena->sStatistics.
1040 uFreeResourceCount);
1043 len = printAppend(page, count, 0, "total allocs\t\t%u\n",
1044 pArena->sStatistics.uCumulativeAllocs);
1047 len = printAppend(page, count, 0, "total frees\t\t%u\n",
1048 pArena->sStatistics.uCumulativeFrees);
1051 len = printAppend(page, count, 0, "import count\t\t%u\n",
1052 pArena->sStatistics.uImportCount);
1055 len = printAppend(page, count, 0, "export count\t\t%u\n",
1056 pArena->sStatistics.uExportCount);
1069 enum PVRSRV_ERROR RA_GetStats(struct RA_ARENA *pArena, char **ppszStr,
1072 char *pszStr = *ppszStr;
1073 u32 ui32StrLen = *pui32StrLen;
1077 CHECK_SPACE(ui32StrLen);
1078 i32Count = OSSNPrintf(pszStr, 100, "\nArena '%s':\n", pArena->name);
1079 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1081 CHECK_SPACE(ui32StrLen);
1082 i32Count = OSSNPrintf(pszStr, 100,
1083 " allocCB=%08X freeCB=%08X handle=%08X quantum=%d\n",
1084 pArena->pImportAlloc, pArena->pImportFree,
1085 pArena->pImportHandle, pArena->uQuantum);
1086 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1088 CHECK_SPACE(ui32StrLen);
1089 i32Count = OSSNPrintf(pszStr, 100, "span count\t\t%lu\n",
1090 pArena->sStatistics.uSpanCount);
1091 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1093 CHECK_SPACE(ui32StrLen);
1094 i32Count = OSSNPrintf(pszStr, 100, "live segment count\t%lu\n",
1095 pArena->sStatistics.uLiveSegmentCount);
1096 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1098 CHECK_SPACE(ui32StrLen);
1099 i32Count = OSSNPrintf(pszStr, 100, "free segment count\t%lu\n",
1100 pArena->sStatistics.uFreeSegmentCount);
1101 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1103 CHECK_SPACE(ui32StrLen);
1104 i32Count = OSSNPrintf(pszStr, 100, "free resource count\t%lu (0x%x)\n",
1105 pArena->sStatistics.uFreeResourceCount,
1106 (unsigned)pArena->sStatistics.uFreeResourceCount);
1107 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1109 CHECK_SPACE(ui32StrLen);
1110 i32Count = OSSNPrintf(pszStr, 100, "total allocs\t\t%lu\n",
1111 pArena->sStatistics.uCumulativeAllocs);
1112 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1114 CHECK_SPACE(ui32StrLen);
1115 i32Count = OSSNPrintf(pszStr, 100, "total frees\t\t%lu\n",
1116 pArena->sStatistics.uCumulativeFrees);
1117 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1119 CHECK_SPACE(ui32StrLen);
1120 i32Count = OSSNPrintf(pszStr, 100, "import count\t\t%lu\n",
1121 pArena->sStatistics.uImportCount);
1122 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1124 CHECK_SPACE(ui32StrLen);
1125 i32Count = OSSNPrintf(pszStr, 100, "export count\t\t%lu\n",
1126 pArena->sStatistics.uExportCount);
1127 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1129 CHECK_SPACE(ui32StrLen);
1130 i32Count = OSSNPrintf(pszStr, 100, " segment Chain:\n");
1131 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1133 if (pArena->pHeadSegment != NULL &&
1134 pArena->pHeadSegment->pPrevSegment != NULL) {
1135 CHECK_SPACE(ui32StrLen);
1136 i32Count = OSSNPrintf(pszStr, 100,
1137 " error: head boundary tag has invalid pPrevSegment\n");
1138 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1141 if (pArena->pTailSegment != NULL &&
1142 pArena->pTailSegment->pNextSegment != NULL) {
1143 CHECK_SPACE(ui32StrLen);
1144 i32Count = OSSNPrintf(pszStr, 100,
1145 " error: tail boundary tag has invalid pNextSegment\n");
1146 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1149 for (pBT = pArena->pHeadSegment; pBT != NULL;
1150 pBT = pBT->pNextSegment) {
1151 CHECK_SPACE(ui32StrLen);
1152 i32Count = OSSNPrintf(pszStr, 100,
1153 "\tbase=0x%x size=0x%x type=%s ref=%08X\n",
1154 (u32) pBT->base, pBT->uSize, _BTType(pBT->type),
1156 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1160 *pui32StrLen = ui32StrLen;