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];
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) {
648 if (PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL))
649 pArena->ui32PID = OSGetCurrentProcessIDKM();
653 ret = snprintf(pArena->szProcInfoName,
654 sizeof(pArena->szProcInfoName), "ra_info_%s",
656 if ((ret > 0) && (ret < sizeof(pArena->szProcInfoName))) {
657 ReplaceSpaces(pArena->szProcInfoName);
658 ret = CreatePerProcessProcEntry(pArena->ui32PID,
659 pArena->szProcInfoName,
660 RA_DumpInfo, pArena);
662 pArena->szProcInfoName[0] = 0;
665 pArena->szProcInfoName[0] = 0;
666 pr_err("%s: couldn't create ra_info proc entry for "
667 "arena %s", __func__, pArena->name);
670 ret = snprintf(pArena->szProcSegsName,
671 sizeof(pArena->szProcSegsName), "ra_segs_%s",
673 if ((ret > 0) && (ret < sizeof(pArena->szProcSegsName))) {
674 ReplaceSpaces(pArena->szProcSegsName);
675 ret = CreatePerProcessProcEntry(pArena->ui32PID,
676 pArena->szProcSegsName,
677 RA_DumpSegs, pArena);
682 pArena->szProcSegsName[0] = 0;
683 pr_err("%s: couldn't create ra_segs proc entry for "
684 "arena %s", __func__, pArena->name);
689 pArena->pSegmentHash = HASH_Create(MINIMUM_HASH_SIZE);
690 if (pArena->pSegmentHash == NULL)
693 uSize = (uSize + uQuantum - 1) / uQuantum * uQuantum;
694 pBT = _InsertResource(pArena, base, uSize);
697 pBT->psMapping = psMapping;
703 HASH_Delete(pArena->pSegmentHash);
705 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct RA_ARENA), pArena,
711 void RA_Delete(struct RA_ARENA *pArena)
715 PVR_ASSERT(pArena != NULL);
717 if (pArena == NULL) {
718 PVR_DPF(PVR_DBG_ERROR,
719 "RA_Delete: invalid parameter - pArena");
723 PVR_DPF(PVR_DBG_MESSAGE, "RA_Delete: name='%s'", pArena->name);
725 for (uIndex = 0; uIndex < FREE_TABLE_LIMIT; uIndex++)
726 pArena->aHeadFree[uIndex] = NULL;
728 while (pArena->pHeadSegment != NULL) {
729 struct BT *pBT = pArena->pHeadSegment;
730 PVR_ASSERT(pBT->type == btt_free);
731 _SegmentListRemove(pArena, pBT);
732 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BT), pBT,
735 pArena->sStatistics.uSpanCount--;
738 #if defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_DEBUG_EXTRA)
740 if (pArena->szProcInfoName[0] != 0)
741 RemovePerProcessProcEntry(pArena->ui32PID,
742 pArena->szProcInfoName);
744 if (pArena->szProcSegsName[0] != 0)
745 RemovePerProcessProcEntry(pArena->ui32PID,
746 pArena->szProcSegsName);
749 HASH_Delete(pArena->pSegmentHash);
750 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct RA_ARENA), pArena,
754 IMG_BOOL RA_TestDelete(struct RA_ARENA *pArena)
756 PVR_ASSERT(pArena != NULL);
759 while (pArena->pHeadSegment != NULL) {
760 struct BT *pBT = pArena->pHeadSegment;
761 if (pBT->type != btt_free)
768 IMG_BOOL RA_Add(struct RA_ARENA *pArena, u32 base, size_t uSize)
770 PVR_ASSERT(pArena != NULL);
772 if (pArena == NULL) {
773 PVR_DPF(PVR_DBG_ERROR, "RA_Add: invalid parameter - pArena");
777 PVR_DPF(PVR_DBG_MESSAGE,
778 "RA_Add: name='%s', base=0x%x, size=0x%x", pArena->name, base,
781 uSize = (uSize + pArena->uQuantum - 1) /
782 pArena->uQuantum * pArena->uQuantum;
783 return (IMG_BOOL)(_InsertResource(pArena, base, uSize) != NULL);
786 IMG_BOOL RA_Alloc(struct RA_ARENA *pArena, size_t uRequestSize,
787 struct BM_MAPPING **ppsMapping, u32 uFlags, u32 uAlignment,
791 size_t uSize = uRequestSize;
793 PVR_ASSERT(pArena != NULL);
795 if (pArena == NULL) {
796 PVR_DPF(PVR_DBG_ERROR,
797 "RA_Alloc: invalid parameter - pArena");
801 PVR_DPF(PVR_DBG_MESSAGE, "RA_Alloc: "
802 "arena='%s', size=0x%x(0x%x), alignment=0x%x",
803 pArena->name, uSize, uRequestSize, uAlignment);
805 bResult = _AttemptAllocAligned(pArena, uSize, ppsMapping, uFlags,
808 struct BM_MAPPING *psImportMapping;
810 size_t uImportSize = uSize;
812 if (uAlignment > pArena->uQuantum)
813 uImportSize += (uAlignment - 1);
816 ((uImportSize + pArena->uQuantum - 1) /
817 pArena->uQuantum) * pArena->uQuantum;
820 pArena->pImportAlloc(pArena->pImportHandle, uImportSize,
821 &uImportSize, &psImportMapping, uFlags,
825 pBT = _InsertResourceSpan(pArena, import_base,
829 pArena->pImportFree(pArena->pImportHandle,
832 PVR_DPF(PVR_DBG_MESSAGE, "RA_Alloc: "
833 "name='%s', size=0x%x failed!",
834 pArena->name, uSize);
838 pBT->psMapping = psImportMapping;
840 pArena->sStatistics.uFreeSegmentCount++;
841 pArena->sStatistics.uFreeResourceCount += uImportSize;
842 pArena->sStatistics.uImportCount++;
843 pArena->sStatistics.uSpanCount++;
845 bResult = _AttemptAllocAligned(pArena, uSize,
846 ppsMapping, uFlags, uAlignment,
849 PVR_DPF(PVR_DBG_MESSAGE, "RA_Alloc: "
850 "name='%s' uAlignment failed!",
856 pArena->sStatistics.uCumulativeAllocs++;
859 PVR_DPF(PVR_DBG_MESSAGE,
860 "RA_Alloc: name='%s', size=0x%x, *base=0x%x = %d",
861 pArena->name, uSize, *base, bResult);
866 void RA_Free(struct RA_ARENA *pArena, u32 base, IMG_BOOL bFreeBackingStore)
870 PVR_ASSERT(pArena != NULL);
872 if (pArena == NULL) {
873 PVR_DPF(PVR_DBG_ERROR, "RA_Free: invalid parameter - pArena");
877 PVR_DPF(PVR_DBG_MESSAGE,
878 "RA_Free: name='%s', base=0x%x", pArena->name, base);
880 pBT = (struct BT *)HASH_Remove(pArena->pSegmentHash, base);
881 PVR_ASSERT(pBT != NULL);
884 PVR_ASSERT(pBT->base == base);
887 pArena->sStatistics.uCumulativeFrees++;
890 _FreeBT(pArena, pBT, bFreeBackingStore);
894 IMG_BOOL RA_GetNextLiveSegment(void *hArena,
895 struct RA_SEGMENT_DETAILS *psSegDetails)
899 if (psSegDetails->hSegment) {
900 pBT = (struct BT *)psSegDetails->hSegment;
902 struct RA_ARENA *pArena = (struct RA_ARENA *)hArena;
903 pBT = pArena->pHeadSegment;
906 while (pBT != NULL) {
907 if (pBT->type == btt_live) {
908 psSegDetails->uiSize = pBT->uSize;
909 psSegDetails->sCpuPhyAddr.uiAddr = pBT->base;
910 psSegDetails->hSegment = (void *) pBT->pNextSegment;
915 pBT = pBT->pNextSegment;
918 psSegDetails->uiSize = 0;
919 psSegDetails->sCpuPhyAddr.uiAddr = 0;
920 psSegDetails->hSegment = (void *) -1;
925 #if (defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_DEBUG_EXTRA)) || \
927 static char *_BTType(int eType)
941 #if defined(ENABLE_RA_DUMP)
942 void RA_Dump(struct RA_ARENA *pArena)
945 PVR_ASSERT(pArena != NULL);
946 PVR_DPF(PVR_DBG_MESSAGE, "Arena '%s':", pArena->name);
947 PVR_DPF(PVR_DBG_MESSAGE,
948 " alloc=%08X free=%08X handle=%08X quantum=%d",
949 pArena->pImportAlloc, pArena->pImportFree,
950 pArena->pImportHandle, pArena->uQuantum);
951 PVR_DPF(PVR_DBG_MESSAGE, " segment Chain:");
952 if (pArena->pHeadSegment != NULL &&
953 pArena->pHeadSegment->pPrevSegment != NULL)
954 PVR_DPF(PVR_DBG_MESSAGE,
955 " error: head boundary tag has invalid pPrevSegment");
956 if (pArena->pTailSegment != NULL &&
957 pArena->pTailSegment->pNextSegment != NULL)
958 PVR_DPF(PVR_DBG_MESSAGE,
959 " error: tail boundary tag has invalid pNextSegment");
961 for (pBT = pArena->pHeadSegment; pBT != NULL; pBT = pBT->pNextSegment)
962 PVR_DPF(PVR_DBG_MESSAGE,
963 "\tbase=0x%x size=0x%x type=%s ref=%08X",
964 (u32) pBT->base, pBT->uSize, _BTType(pBT->type),
970 #if defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_DEBUG_EXTRA)
971 static int RA_DumpSegs(char *page, char **start, off_t off, int count, int *eof,
974 struct BT *pBT = NULL;
976 struct RA_ARENA *pArena = (struct RA_ARENA *)data;
985 return printAppend(page, count, 0,
986 "Arena \"%s\"\nBase Size Type Ref\n",
988 for (pBT = pArena->pHeadSegment; --off && pBT;
989 pBT = pBT->pNextSegment)
992 len = printAppend(page, count, 0, "%08x %8x %4s %08x\n",
993 (unsigned)pBT->base, (unsigned)pBT->uSize,
994 _BTType(pBT->type), (unsigned)pBT->psMapping);
1000 static int RA_DumpInfo(char *page, char **start, off_t off, int count, int *eof,
1004 struct RA_ARENA *pArena = (struct RA_ARENA *)data;
1013 len = printAppend(page, count, 0, "quantum\t\t\t%u\n",
1017 len = printAppend(page, count, 0, "import_handle\t\t%08X\n",
1018 (unsigned)pArena->pImportHandle);
1022 len = printAppend(page, count, 0, "span count\t\t%u\n",
1023 pArena->sStatistics.uSpanCount);
1026 len = printAppend(page, count, 0, "live segment count\t%u\n",
1027 pArena->sStatistics.uLiveSegmentCount);
1030 len = printAppend(page, count, 0, "free segment count\t%u\n",
1031 pArena->sStatistics.uFreeSegmentCount);
1034 len = printAppend(page, count, 0,
1035 "free resource count\t%u (0x%x)\n",
1036 pArena->sStatistics.uFreeResourceCount,
1037 (unsigned)pArena->sStatistics.
1038 uFreeResourceCount);
1041 len = printAppend(page, count, 0, "total allocs\t\t%u\n",
1042 pArena->sStatistics.uCumulativeAllocs);
1045 len = printAppend(page, count, 0, "total frees\t\t%u\n",
1046 pArena->sStatistics.uCumulativeFrees);
1049 len = printAppend(page, count, 0, "import count\t\t%u\n",
1050 pArena->sStatistics.uImportCount);
1053 len = printAppend(page, count, 0, "export count\t\t%u\n",
1054 pArena->sStatistics.uExportCount);
1067 enum PVRSRV_ERROR RA_GetStats(struct RA_ARENA *pArena, char **ppszStr,
1070 char *pszStr = *ppszStr;
1071 u32 ui32StrLen = *pui32StrLen;
1075 CHECK_SPACE(ui32StrLen);
1076 i32Count = OSSNPrintf(pszStr, 100, "\nArena '%s':\n", pArena->name);
1077 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1079 CHECK_SPACE(ui32StrLen);
1080 i32Count = OSSNPrintf(pszStr, 100,
1081 " allocCB=%08X freeCB=%08X handle=%08X quantum=%d\n",
1082 pArena->pImportAlloc, pArena->pImportFree,
1083 pArena->pImportHandle, pArena->uQuantum);
1084 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1086 CHECK_SPACE(ui32StrLen);
1087 i32Count = OSSNPrintf(pszStr, 100, "span count\t\t%lu\n",
1088 pArena->sStatistics.uSpanCount);
1089 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1091 CHECK_SPACE(ui32StrLen);
1092 i32Count = OSSNPrintf(pszStr, 100, "live segment count\t%lu\n",
1093 pArena->sStatistics.uLiveSegmentCount);
1094 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1096 CHECK_SPACE(ui32StrLen);
1097 i32Count = OSSNPrintf(pszStr, 100, "free segment count\t%lu\n",
1098 pArena->sStatistics.uFreeSegmentCount);
1099 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1101 CHECK_SPACE(ui32StrLen);
1102 i32Count = OSSNPrintf(pszStr, 100, "free resource count\t%lu (0x%x)\n",
1103 pArena->sStatistics.uFreeResourceCount,
1104 (unsigned)pArena->sStatistics.uFreeResourceCount);
1105 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1107 CHECK_SPACE(ui32StrLen);
1108 i32Count = OSSNPrintf(pszStr, 100, "total allocs\t\t%lu\n",
1109 pArena->sStatistics.uCumulativeAllocs);
1110 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1112 CHECK_SPACE(ui32StrLen);
1113 i32Count = OSSNPrintf(pszStr, 100, "total frees\t\t%lu\n",
1114 pArena->sStatistics.uCumulativeFrees);
1115 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1117 CHECK_SPACE(ui32StrLen);
1118 i32Count = OSSNPrintf(pszStr, 100, "import count\t\t%lu\n",
1119 pArena->sStatistics.uImportCount);
1120 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1122 CHECK_SPACE(ui32StrLen);
1123 i32Count = OSSNPrintf(pszStr, 100, "export count\t\t%lu\n",
1124 pArena->sStatistics.uExportCount);
1125 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1127 CHECK_SPACE(ui32StrLen);
1128 i32Count = OSSNPrintf(pszStr, 100, " segment Chain:\n");
1129 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1131 if (pArena->pHeadSegment != NULL &&
1132 pArena->pHeadSegment->pPrevSegment != NULL) {
1133 CHECK_SPACE(ui32StrLen);
1134 i32Count = OSSNPrintf(pszStr, 100,
1135 " error: head boundary tag has invalid pPrevSegment\n");
1136 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1139 if (pArena->pTailSegment != NULL &&
1140 pArena->pTailSegment->pNextSegment != NULL) {
1141 CHECK_SPACE(ui32StrLen);
1142 i32Count = OSSNPrintf(pszStr, 100,
1143 " error: tail boundary tag has invalid pNextSegment\n");
1144 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1147 for (pBT = pArena->pHeadSegment; pBT != NULL;
1148 pBT = pBT->pNextSegment) {
1149 CHECK_SPACE(ui32StrLen);
1150 i32Count = OSSNPrintf(pszStr, 100,
1151 "\tbase=0x%x size=0x%x type=%s ref=%08X\n",
1152 (u32) pBT->base, pBT->uSize, _BTType(pBT->type),
1154 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1158 *pui32StrLen = ui32StrLen;