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 <linux/version.h>
29 #include <linux/vmalloc.h>
31 #include <linux/slab.h>
32 #include <linux/highmem.h>
33 #include <linux/sched.h>
34 #include <linux/dma-mapping.h>
38 #include "servicesint.h"
39 #include "syscommon.h"
45 #include "pvr_debug.h"
48 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
49 enum DEBUG_MEM_ALLOC_TYPE {
50 DEBUG_MEM_ALLOC_TYPE_KMALLOC,
51 DEBUG_MEM_ALLOC_TYPE_VMALLOC,
52 DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES,
53 DEBUG_MEM_ALLOC_TYPE_IOREMAP,
54 DEBUG_MEM_ALLOC_TYPE_IO,
55 DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE,
56 DEBUG_MEM_ALLOC_TYPE_COUNT
59 struct DEBUG_MEM_ALLOC_REC {
60 enum DEBUG_MEM_ALLOC_TYPE eAllocType;
70 struct DEBUG_MEM_ALLOC_REC *psNext;
73 static struct DEBUG_MEM_ALLOC_REC *g_MemoryRecords;
75 static u32 g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_COUNT];
76 static u32 g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_COUNT];
78 static u32 g_SysRAMWaterMark;
79 static u32 g_SysRAMHighWaterMark;
81 static u32 g_IOMemWaterMark;
82 static u32 g_IOMemHighWaterMark;
84 static void DebugMemAllocRecordAdd(enum DEBUG_MEM_ALLOC_TYPE eAllocType,
85 void *pvKey, void *pvCpuVAddr,
86 u32 ulCpuPAddr, void *pvPrivateData,
87 u32 ui32Bytes, char *pszFileName,
90 static void DebugMemAllocRecordRemove(enum DEBUG_MEM_ALLOC_TYPE eAllocType,
91 void *pvKey, char *pszFileName,
94 static char *DebugMemAllocRecordTypeToString(
95 enum DEBUG_MEM_ALLOC_TYPE eAllocType);
97 static off_t printMemoryRecords(char *buffer, size_t size, off_t off);
100 #if defined(DEBUG_LINUX_MEM_AREAS)
101 struct DEBUG_LINUX_MEM_AREA_REC {
102 struct LinuxMemArea *psLinuxMemArea;
106 struct DEBUG_LINUX_MEM_AREA_REC *psNext;
109 #if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
110 static struct mutex g_sDebugMutex;
113 static struct DEBUG_LINUX_MEM_AREA_REC *g_LinuxMemAreaRecords;
114 static u32 g_LinuxMemAreaCount;
115 static u32 g_LinuxMemAreaWaterMark;
116 static u32 g_LinuxMemAreaHighWaterMark;
118 static off_t printLinuxMemAreaRecords(char *buffer, size_t size, off_t off);
121 static struct kmem_cache *psLinuxMemAreaCache;
124 static struct LinuxMemArea *LinuxMemAreaStructAlloc(void);
125 static void LinuxMemAreaStructFree(struct LinuxMemArea *psLinuxMemArea);
126 #if defined(DEBUG_LINUX_MEM_AREAS)
127 static void DebugLinuxMemAreaRecordAdd(struct LinuxMemArea *psLinuxMemArea,
129 static struct DEBUG_LINUX_MEM_AREA_REC *DebugLinuxMemAreaRecordFind(
130 struct LinuxMemArea *psLinuxMemArea);
131 static void DebugLinuxMemAreaRecordRemove(struct LinuxMemArea *psLinuxMemArea);
134 enum PVRSRV_ERROR LinuxMMInit(void)
136 #if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
137 mutex_init(&g_sDebugMutex);
140 #if defined(DEBUG_LINUX_MEM_AREAS)
144 CreateProcReadEntry("mem_areas", printLinuxMemAreaRecords);
146 return PVRSRV_ERROR_OUT_OF_MEMORY;
150 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
153 iStatus = CreateProcReadEntry("meminfo", printMemoryRecords);
155 return PVRSRV_ERROR_OUT_OF_MEMORY;
158 psLinuxMemAreaCache =
159 kmem_cache_create("img-mm", sizeof(struct LinuxMemArea), 0, 0,
161 if (!psLinuxMemAreaCache) {
162 PVR_DPF(PVR_DBG_ERROR, "%s: failed to allocate kmem_cache",
164 return PVRSRV_ERROR_OUT_OF_MEMORY;
170 void LinuxMMCleanup(void)
172 #if defined(DEBUG_LINUX_MEM_AREAS)
174 struct DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord =
175 g_LinuxMemAreaRecords, *psNextRecord;
177 if (g_LinuxMemAreaCount)
178 PVR_DPF(PVR_DBG_ERROR, "%s: BUG!: "
179 "There are %d struct LinuxMemArea "
180 "allocation unfreed (%ld bytes)",
181 __func__, g_LinuxMemAreaCount,
182 g_LinuxMemAreaWaterMark);
184 while (psCurrentRecord) {
185 struct LinuxMemArea *psLinuxMemArea;
187 psNextRecord = psCurrentRecord->psNext;
188 psLinuxMemArea = psCurrentRecord->psLinuxMemArea;
189 PVR_DPF(PVR_DBG_ERROR, "%s: BUG!: "
190 "Cleaning up Linux memory area (%p), "
191 "type=%s, size=%ld bytes",
192 __func__, psCurrentRecord->psLinuxMemArea,
193 LinuxMemAreaTypeToString(psCurrentRecord->
196 psCurrentRecord->psLinuxMemArea->
199 LinuxMemAreaDeepFree(psLinuxMemArea);
201 psCurrentRecord = psNextRecord;
203 RemoveProcEntry("mem_areas");
207 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
209 struct DEBUG_MEM_ALLOC_REC *psCurrentRecord =
210 g_MemoryRecords, *psNextRecord;
212 while (psCurrentRecord) {
213 psNextRecord = psCurrentRecord->psNext;
214 PVR_DPF(PVR_DBG_ERROR, "%s: BUG!: Cleaning up memory: "
215 "type=%s CpuVAddr=%p CpuPAddr=0x%08lx, "
216 "allocated @ file=%s,line=%d",
218 DebugMemAllocRecordTypeToString
219 (psCurrentRecord->eAllocType),
220 psCurrentRecord->pvCpuVAddr,
221 psCurrentRecord->ulCpuPAddr,
222 psCurrentRecord->pszFileName,
223 psCurrentRecord->ui32Line);
224 switch (psCurrentRecord->eAllocType) {
225 case DEBUG_MEM_ALLOC_TYPE_KMALLOC:
226 KFreeWrapper(psCurrentRecord->pvCpuVAddr);
228 case DEBUG_MEM_ALLOC_TYPE_IOREMAP:
229 IOUnmapWrapper((__force __iomem void *)
230 psCurrentRecord->pvCpuVAddr);
232 case DEBUG_MEM_ALLOC_TYPE_IO:
234 DebugMemAllocRecordRemove
235 (DEBUG_MEM_ALLOC_TYPE_IO,
236 psCurrentRecord->pvKey, __FILE__,
239 case DEBUG_MEM_ALLOC_TYPE_VMALLOC:
240 VFreeWrapper(psCurrentRecord->pvCpuVAddr);
242 case DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES:
244 DebugMemAllocRecordRemove
245 (DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES,
246 psCurrentRecord->pvKey, __FILE__,
249 case DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE:
250 KMemCacheFreeWrapper(psCurrentRecord->
258 psCurrentRecord = psNextRecord;
260 RemoveProcEntry("meminfo");
264 if (psLinuxMemAreaCache) {
265 kmem_cache_destroy(psLinuxMemAreaCache);
266 psLinuxMemAreaCache = NULL;
270 void *_KMallocWrapper(u32 ui32ByteSize, char *pszFileName,
274 pvRet = kmalloc(ui32ByteSize, GFP_KERNEL);
275 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
277 DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_KMALLOC,
278 pvRet, pvRet, 0, NULL, ui32ByteSize,
279 pszFileName, ui32Line);
284 void _KFreeWrapper(void *pvCpuVAddr, char *pszFileName,
287 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
288 DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_KMALLOC, pvCpuVAddr,
289 pszFileName, ui32Line);
294 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
295 static void DebugMemAllocRecordAdd(enum DEBUG_MEM_ALLOC_TYPE eAllocType,
296 void *pvKey, void *pvCpuVAddr,
297 u32 ulCpuPAddr, void *pvPrivateData,
298 u32 ui32Bytes, char *pszFileName,
301 struct DEBUG_MEM_ALLOC_REC *psRecord;
303 mutex_lock(&g_sDebugMutex);
305 psRecord = kmalloc(sizeof(struct DEBUG_MEM_ALLOC_REC), GFP_KERNEL);
307 psRecord->eAllocType = eAllocType;
308 psRecord->pvKey = pvKey;
309 psRecord->pvCpuVAddr = pvCpuVAddr;
310 psRecord->ulCpuPAddr = ulCpuPAddr;
311 psRecord->pvPrivateData = pvPrivateData;
312 psRecord->pid = current->pid;
313 psRecord->ui32Bytes = ui32Bytes;
314 psRecord->pszFileName = pszFileName;
315 psRecord->ui32Line = ui32Line;
317 psRecord->psNext = g_MemoryRecords;
318 g_MemoryRecords = psRecord;
320 g_WaterMarkData[eAllocType] += ui32Bytes;
321 if (g_WaterMarkData[eAllocType] > g_HighWaterMarkData[eAllocType])
322 g_HighWaterMarkData[eAllocType] = g_WaterMarkData[eAllocType];
324 if (eAllocType == DEBUG_MEM_ALLOC_TYPE_KMALLOC ||
325 eAllocType == DEBUG_MEM_ALLOC_TYPE_VMALLOC ||
326 eAllocType == DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES ||
327 eAllocType == DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE) {
328 g_SysRAMWaterMark += ui32Bytes;
329 if (g_SysRAMWaterMark > g_SysRAMHighWaterMark)
330 g_SysRAMHighWaterMark = g_SysRAMWaterMark;
331 } else if (eAllocType == DEBUG_MEM_ALLOC_TYPE_IOREMAP ||
332 eAllocType == DEBUG_MEM_ALLOC_TYPE_IO) {
333 g_IOMemWaterMark += ui32Bytes;
334 if (g_IOMemWaterMark > g_IOMemHighWaterMark)
335 g_IOMemHighWaterMark = g_IOMemWaterMark;
338 mutex_unlock(&g_sDebugMutex);
341 static void DebugMemAllocRecordRemove(enum DEBUG_MEM_ALLOC_TYPE eAllocType,
342 void *pvKey, char *pszFileName,
345 struct DEBUG_MEM_ALLOC_REC **ppsCurrentRecord;
347 mutex_lock(&g_sDebugMutex);
349 for (ppsCurrentRecord = &g_MemoryRecords; *ppsCurrentRecord;
350 ppsCurrentRecord = &((*ppsCurrentRecord)->psNext))
351 if ((*ppsCurrentRecord)->eAllocType == eAllocType &&
352 (*ppsCurrentRecord)->pvKey == pvKey) {
353 struct DEBUG_MEM_ALLOC_REC *psNextRecord;
355 psNextRecord = (*ppsCurrentRecord)->psNext;
356 g_WaterMarkData[eAllocType] -=
357 (*ppsCurrentRecord)->ui32Bytes;
359 if (eAllocType == DEBUG_MEM_ALLOC_TYPE_KMALLOC ||
360 eAllocType == DEBUG_MEM_ALLOC_TYPE_VMALLOC ||
361 eAllocType == DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES ||
362 eAllocType == DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE) {
364 (*ppsCurrentRecord)->ui32Bytes;
366 if (eAllocType == DEBUG_MEM_ALLOC_TYPE_IOREMAP
367 || eAllocType == DEBUG_MEM_ALLOC_TYPE_IO)
369 (*ppsCurrentRecord)->ui32Bytes;
373 kfree(*ppsCurrentRecord);
374 *ppsCurrentRecord = psNextRecord;
378 PVR_DPF(PVR_DBG_ERROR, "%s: couldn't find an entry for type=%s "
379 "with pvKey=%p (called from %s, line %d\n",
380 __func__, DebugMemAllocRecordTypeToString(eAllocType), pvKey,
381 pszFileName, ui32Line);
384 mutex_unlock(&g_sDebugMutex);
387 static char *DebugMemAllocRecordTypeToString(
388 enum DEBUG_MEM_ALLOC_TYPE eAllocType)
390 char *apszDebugMemoryRecordTypes[] = {
398 return apszDebugMemoryRecordTypes[eAllocType];
402 void *_VMallocWrapper(u32 ui32Bytes, u32 ui32AllocFlags, char *pszFileName,
405 pgprot_t PGProtFlags;
408 switch (ui32AllocFlags & PVRSRV_HAP_CACHETYPE_MASK) {
409 case PVRSRV_HAP_CACHED:
410 PGProtFlags = PAGE_KERNEL;
412 case PVRSRV_HAP_WRITECOMBINE:
413 PGProtFlags = PGPROT_WC(PAGE_KERNEL);
415 case PVRSRV_HAP_UNCACHED:
416 PGProtFlags = PGPROT_UC(PAGE_KERNEL);
419 PVR_DPF(PVR_DBG_ERROR,
420 "VMAllocWrapper: unknown mapping flags=0x%08lx",
426 pvRet = __vmalloc(ui32Bytes, GFP_KERNEL | __GFP_HIGHMEM, PGProtFlags);
428 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
430 DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_VMALLOC,
431 pvRet, pvRet, 0, NULL,
432 PAGE_ALIGN(ui32Bytes),
433 pszFileName, ui32Line);
439 void _VFreeWrapper(void *pvCpuVAddr, char *pszFileName, u32 ui32Line)
441 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
442 DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_VMALLOC, pvCpuVAddr,
443 pszFileName, ui32Line);
448 struct LinuxMemArea *NewVMallocLinuxMemArea(u32 ui32Bytes, u32 ui32AreaFlags)
450 struct LinuxMemArea *psLinuxMemArea;
453 psLinuxMemArea = LinuxMemAreaStructAlloc();
457 pvCpuVAddr = VMallocWrapper(ui32Bytes, ui32AreaFlags);
461 psLinuxMemArea->eAreaType = LINUX_MEM_AREA_VMALLOC;
462 psLinuxMemArea->uData.sVmalloc.pvVmallocAddress = pvCpuVAddr;
463 psLinuxMemArea->ui32ByteSize = ui32Bytes;
464 psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
465 psLinuxMemArea->bMMapRegistered = IMG_FALSE;
466 INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
468 #if defined(DEBUG_LINUX_MEM_AREAS)
469 DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
472 return psLinuxMemArea;
475 PVR_DPF(PVR_DBG_ERROR, "%s: failed!", __func__);
477 LinuxMemAreaStructFree(psLinuxMemArea);
481 void FreeVMallocLinuxMemArea(struct LinuxMemArea *psLinuxMemArea)
483 PVR_ASSERT(psLinuxMemArea);
484 PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_VMALLOC);
485 PVR_ASSERT(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress);
487 #if defined(DEBUG_LINUX_MEM_AREAS)
488 DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
492 PVR_DPF(PVR_DBG_MESSAGE, "%s: pvCpuVAddr: %p",
494 psLinuxMemArea->uData.sVmalloc.pvVmallocAddress);
495 VFreeWrapper(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress);
497 LinuxMemAreaStructFree(psLinuxMemArea);
500 void __iomem *_IORemapWrapper(struct IMG_CPU_PHYADDR BasePAddr,
501 u32 ui32Bytes, u32 ui32MappingFlags,
502 char *pszFileName, u32 ui32Line)
504 void __iomem *pvIORemapCookie = NULL;
506 switch (ui32MappingFlags & PVRSRV_HAP_CACHETYPE_MASK) {
507 case PVRSRV_HAP_CACHED:
508 pvIORemapCookie = IOREMAP(BasePAddr.uiAddr, ui32Bytes);
510 case PVRSRV_HAP_WRITECOMBINE:
511 pvIORemapCookie = IOREMAP_WC(BasePAddr.uiAddr, ui32Bytes);
513 case PVRSRV_HAP_UNCACHED:
514 pvIORemapCookie = IOREMAP_UC(BasePAddr.uiAddr, ui32Bytes);
517 PVR_DPF(PVR_DBG_ERROR,
518 "IORemapWrapper: unknown mapping flags");
522 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
524 DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_IOREMAP,
525 (__force void *)pvIORemapCookie,
526 (__force void *)pvIORemapCookie,
528 NULL, ui32Bytes, pszFileName, ui32Line);
531 return pvIORemapCookie;
534 void _IOUnmapWrapper(void __iomem *pvIORemapCookie, char *pszFileName,
537 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
538 DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IOREMAP,
539 (__force void *)pvIORemapCookie,
540 pszFileName, ui32Line);
542 iounmap(pvIORemapCookie);
545 struct LinuxMemArea *NewIORemapLinuxMemArea(struct IMG_CPU_PHYADDR BasePAddr,
546 u32 ui32Bytes, u32 ui32AreaFlags)
548 struct LinuxMemArea *psLinuxMemArea;
549 void __iomem *pvIORemapCookie;
551 psLinuxMemArea = LinuxMemAreaStructAlloc();
555 pvIORemapCookie = IORemapWrapper(BasePAddr, ui32Bytes, ui32AreaFlags);
556 if (!pvIORemapCookie) {
557 LinuxMemAreaStructFree(psLinuxMemArea);
561 psLinuxMemArea->eAreaType = LINUX_MEM_AREA_IOREMAP;
562 psLinuxMemArea->uData.sIORemap.pvIORemapCookie = pvIORemapCookie;
563 psLinuxMemArea->uData.sIORemap.CPUPhysAddr = BasePAddr;
564 psLinuxMemArea->ui32ByteSize = ui32Bytes;
565 psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
566 psLinuxMemArea->bMMapRegistered = IMG_FALSE;
567 INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
569 #if defined(DEBUG_LINUX_MEM_AREAS)
570 DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
573 return psLinuxMemArea;
576 void FreeIORemapLinuxMemArea(struct LinuxMemArea *psLinuxMemArea)
578 PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_IOREMAP);
580 #if defined(DEBUG_LINUX_MEM_AREAS)
581 DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
584 IOUnmapWrapper(psLinuxMemArea->uData.sIORemap.pvIORemapCookie);
586 LinuxMemAreaStructFree(psLinuxMemArea);
589 static IMG_BOOL PagesAreContiguous(struct IMG_SYS_PHYADDR *psSysPhysAddr,
594 u32 ui32NumPages = RANGE_TO_PAGES(ui32Bytes);
596 for (ui32 = 0, ui32AddrChk = psSysPhysAddr[0].uiAddr;
597 ui32 < ui32NumPages; ui32++, ui32AddrChk += PAGE_SIZE)
598 if (psSysPhysAddr[ui32].uiAddr != ui32AddrChk)
604 struct LinuxMemArea *NewExternalKVLinuxMemArea(struct IMG_SYS_PHYADDR
605 *pBasePAddr, void *pvCPUVAddr,
607 IMG_BOOL bPhysContig,
610 struct LinuxMemArea *psLinuxMemArea;
612 psLinuxMemArea = LinuxMemAreaStructAlloc();
616 psLinuxMemArea->eAreaType = LINUX_MEM_AREA_EXTERNAL_KV;
617 psLinuxMemArea->uData.sExternalKV.pvExternalKV = pvCPUVAddr;
618 psLinuxMemArea->uData.sExternalKV.bPhysContig = bPhysContig ||
619 PagesAreContiguous(pBasePAddr, ui32Bytes);
621 if (psLinuxMemArea->uData.sExternalKV.bPhysContig)
622 psLinuxMemArea->uData.sExternalKV.uPhysAddr.SysPhysAddr =
625 psLinuxMemArea->uData.sExternalKV.uPhysAddr.pSysPhysAddr =
627 psLinuxMemArea->ui32ByteSize = ui32Bytes;
628 psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
629 psLinuxMemArea->bMMapRegistered = IMG_FALSE;
630 INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
632 #if defined(DEBUG_LINUX_MEM_AREAS)
633 DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
636 return psLinuxMemArea;
639 void FreeExternalKVLinuxMemArea(struct LinuxMemArea *psLinuxMemArea)
641 PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_EXTERNAL_KV);
643 #if defined(DEBUG_LINUX_MEM_AREAS)
644 DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
647 LinuxMemAreaStructFree(psLinuxMemArea);
650 struct LinuxMemArea *NewIOLinuxMemArea(struct IMG_CPU_PHYADDR BasePAddr,
651 u32 ui32Bytes, u32 ui32AreaFlags)
653 struct LinuxMemArea *psLinuxMemArea = LinuxMemAreaStructAlloc();
657 psLinuxMemArea->eAreaType = LINUX_MEM_AREA_IO;
658 psLinuxMemArea->uData.sIO.CPUPhysAddr.uiAddr = BasePAddr.uiAddr;
659 psLinuxMemArea->ui32ByteSize = ui32Bytes;
660 psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
661 psLinuxMemArea->bMMapRegistered = IMG_FALSE;
662 INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
664 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
665 DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_IO,
666 (void *)BasePAddr.uiAddr, NULL,
667 BasePAddr.uiAddr, NULL, ui32Bytes, "unknown", 0);
670 #if defined(DEBUG_LINUX_MEM_AREAS)
671 DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
674 return psLinuxMemArea;
677 void FreeIOLinuxMemArea(struct LinuxMemArea *psLinuxMemArea)
679 PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_IO);
681 #if defined(DEBUG_LINUX_MEM_AREAS)
682 DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
685 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
686 DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IO,
687 (void *)psLinuxMemArea->uData.sIO.
688 CPUPhysAddr.uiAddr, __FILE__, __LINE__);
691 LinuxMemAreaStructFree(psLinuxMemArea);
694 struct LinuxMemArea *NewAllocPagesLinuxMemArea(u32 ui32Bytes,
697 struct LinuxMemArea *psLinuxMemArea;
699 struct page **pvPageList;
700 void *hBlockPageList;
702 enum PVRSRV_ERROR eError;
704 psLinuxMemArea = LinuxMemAreaStructAlloc();
706 goto failed_area_alloc;
708 ui32PageCount = RANGE_TO_PAGES(ui32Bytes);
709 eError = OSAllocMem(0, sizeof(*pvPageList) * ui32PageCount,
710 (void **)&pvPageList, &hBlockPageList);
711 if (eError != PVRSRV_OK)
712 goto failed_page_list_alloc;
714 for (i = 0; i < ui32PageCount; i++) {
715 pvPageList[i] = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, 0);
717 goto failed_alloc_pages;
721 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
722 DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES,
723 pvPageList, NULL, 0, NULL, PAGE_ALIGN(ui32Bytes),
727 psLinuxMemArea->eAreaType = LINUX_MEM_AREA_ALLOC_PAGES;
728 psLinuxMemArea->uData.sPageList.pvPageList = pvPageList;
729 psLinuxMemArea->uData.sPageList.hBlockPageList = hBlockPageList;
730 psLinuxMemArea->ui32ByteSize = ui32Bytes;
731 psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
732 psLinuxMemArea->bMMapRegistered = IMG_FALSE;
733 INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
735 #if defined(DEBUG_LINUX_MEM_AREAS)
736 DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
739 return psLinuxMemArea;
742 for (i--; i >= 0; i--)
743 __free_pages(pvPageList[i], 0);
744 OSFreeMem(0, sizeof(*pvPageList) * ui32PageCount, pvPageList,
746 failed_page_list_alloc:
747 LinuxMemAreaStructFree(psLinuxMemArea);
749 PVR_DPF(PVR_DBG_ERROR, "%s: failed", __func__);
754 void FreeAllocPagesLinuxMemArea(struct LinuxMemArea *psLinuxMemArea)
757 struct page **pvPageList;
758 void *hBlockPageList;
761 PVR_ASSERT(psLinuxMemArea);
762 PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_ALLOC_PAGES);
764 #if defined(DEBUG_LINUX_MEM_AREAS)
765 DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
768 ui32PageCount = RANGE_TO_PAGES(psLinuxMemArea->ui32ByteSize);
769 pvPageList = psLinuxMemArea->uData.sPageList.pvPageList;
770 hBlockPageList = psLinuxMemArea->uData.sPageList.hBlockPageList;
772 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
773 DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, pvPageList,
777 for (i = 0; i < ui32PageCount; i++)
778 __free_pages(pvPageList[i], 0);
780 OSFreeMem(0, sizeof(*pvPageList) * ui32PageCount, pvPageList,
783 LinuxMemAreaStructFree(psLinuxMemArea);
786 struct page *LinuxMemAreaOffsetToPage(struct LinuxMemArea *psLinuxMemArea,
792 switch (psLinuxMemArea->eAreaType) {
793 case LINUX_MEM_AREA_ALLOC_PAGES:
794 ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
796 psLinuxMemArea->uData.sPageList.pvPageList[ui32PageIndex];
798 case LINUX_MEM_AREA_VMALLOC:
799 pui8Addr = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
800 pui8Addr += ui32ByteOffset;
801 return vmalloc_to_page(pui8Addr);
803 case LINUX_MEM_AREA_SUB_ALLOC:
804 return LinuxMemAreaOffsetToPage(psLinuxMemArea->
805 uData.sSubAlloc.psParentLinuxMemArea,
807 uData.sSubAlloc.ui32ByteOffset +
810 PVR_DPF(PVR_DBG_ERROR, "%s: Unsupported request for "
811 "struct page from struct LinuxMemArea with type=%s",
812 LinuxMemAreaTypeToString(psLinuxMemArea->eAreaType));
817 void *_KMemCacheAllocWrapper(struct kmem_cache *psCache,
819 char *pszFileName, u32 ui32Line)
823 pvRet = kmem_cache_alloc(psCache, Flags);
825 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
826 DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE, pvRet, pvRet,
827 0, psCache, kmem_cache_size(psCache),
828 pszFileName, ui32Line);
834 void _KMemCacheFreeWrapper(struct kmem_cache *psCache, void *pvObject,
835 char *pszFileName, u32 ui32Line)
837 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
838 DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE, pvObject,
839 pszFileName, ui32Line);
842 kmem_cache_free(psCache, pvObject);
845 const char *KMemCacheNameWrapper(struct kmem_cache *psCache)
851 struct LinuxMemArea *NewSubLinuxMemArea(struct LinuxMemArea
852 *psParentLinuxMemArea, u32 ui32ByteOffset,
855 struct LinuxMemArea *psLinuxMemArea;
857 PVR_ASSERT((ui32ByteOffset + ui32Bytes) <=
858 psParentLinuxMemArea->ui32ByteSize);
860 psLinuxMemArea = LinuxMemAreaStructAlloc();
864 psLinuxMemArea->eAreaType = LINUX_MEM_AREA_SUB_ALLOC;
865 psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea =
866 psParentLinuxMemArea;
867 psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset = ui32ByteOffset;
868 psLinuxMemArea->ui32ByteSize = ui32Bytes;
869 psLinuxMemArea->ui32AreaFlags = psParentLinuxMemArea->ui32AreaFlags;
870 psLinuxMemArea->bMMapRegistered = IMG_FALSE;
871 INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
873 #if defined(DEBUG_LINUX_MEM_AREAS)
875 struct DEBUG_LINUX_MEM_AREA_REC *psParentRecord;
877 DebugLinuxMemAreaRecordFind(psParentLinuxMemArea);
878 DebugLinuxMemAreaRecordAdd(psLinuxMemArea,
879 psParentRecord->ui32Flags);
883 return psLinuxMemArea;
886 static void FreeSubLinuxMemArea(struct LinuxMemArea *psLinuxMemArea)
888 PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC);
890 #if defined(DEBUG_LINUX_MEM_AREAS)
891 DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
894 LinuxMemAreaStructFree(psLinuxMemArea);
897 static struct LinuxMemArea *LinuxMemAreaStructAlloc(void)
899 return KMemCacheAllocWrapper(psLinuxMemAreaCache, GFP_KERNEL);
902 static void LinuxMemAreaStructFree(struct LinuxMemArea *psLinuxMemArea)
904 KMemCacheFreeWrapper(psLinuxMemAreaCache, psLinuxMemArea);
908 void LinuxMemAreaDeepFree(struct LinuxMemArea *psLinuxMemArea)
910 switch (psLinuxMemArea->eAreaType) {
911 case LINUX_MEM_AREA_VMALLOC:
912 FreeVMallocLinuxMemArea(psLinuxMemArea);
914 case LINUX_MEM_AREA_ALLOC_PAGES:
915 FreeAllocPagesLinuxMemArea(psLinuxMemArea);
917 case LINUX_MEM_AREA_IOREMAP:
918 FreeIORemapLinuxMemArea(psLinuxMemArea);
920 case LINUX_MEM_AREA_EXTERNAL_KV:
921 FreeExternalKVLinuxMemArea(psLinuxMemArea);
923 case LINUX_MEM_AREA_IO:
924 FreeIOLinuxMemArea(psLinuxMemArea);
926 case LINUX_MEM_AREA_SUB_ALLOC:
927 FreeSubLinuxMemArea(psLinuxMemArea);
930 PVR_DPF(PVR_DBG_ERROR, "%s: Unknown are type (%d)\n",
931 __func__, psLinuxMemArea->eAreaType);
935 #if defined(DEBUG_LINUX_MEM_AREAS)
936 static void DebugLinuxMemAreaRecordAdd(struct LinuxMemArea *psLinuxMemArea,
939 struct DEBUG_LINUX_MEM_AREA_REC *psNewRecord;
940 const char *pi8FlagsString;
942 mutex_lock(&g_sDebugMutex);
944 if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC) {
945 g_LinuxMemAreaWaterMark += psLinuxMemArea->ui32ByteSize;
946 if (g_LinuxMemAreaWaterMark > g_LinuxMemAreaHighWaterMark)
947 g_LinuxMemAreaHighWaterMark = g_LinuxMemAreaWaterMark;
949 g_LinuxMemAreaCount++;
951 psNewRecord = kmalloc(sizeof(struct DEBUG_LINUX_MEM_AREA_REC),
954 psNewRecord->psLinuxMemArea = psLinuxMemArea;
955 psNewRecord->ui32Flags = ui32Flags;
956 psNewRecord->pid = current->pid;
957 psNewRecord->psNext = g_LinuxMemAreaRecords;
958 g_LinuxMemAreaRecords = psNewRecord;
960 PVR_DPF(PVR_DBG_ERROR,
961 "%s: failed to allocate linux memory area record.",
965 pi8FlagsString = HAPFlagsToString(ui32Flags);
966 if (strstr(pi8FlagsString, "UNKNOWN"))
967 PVR_DPF(PVR_DBG_ERROR, "%s: Unexpected flags "
968 "(0x%08lx) associated with psLinuxMemArea @ 0x%08lx",
969 __func__, ui32Flags, psLinuxMemArea);
971 mutex_unlock(&g_sDebugMutex);
974 static struct DEBUG_LINUX_MEM_AREA_REC *DebugLinuxMemAreaRecordFind(
975 struct LinuxMemArea *psLinuxMemArea)
977 struct DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord;
979 mutex_lock(&g_sDebugMutex);
981 for (psCurrentRecord = g_LinuxMemAreaRecords;
982 psCurrentRecord; psCurrentRecord = psCurrentRecord->psNext)
983 if (psCurrentRecord->psLinuxMemArea == psLinuxMemArea)
987 mutex_unlock(&g_sDebugMutex);
989 return psCurrentRecord;
992 static void DebugLinuxMemAreaRecordRemove(struct LinuxMemArea *psLinuxMemArea)
994 struct DEBUG_LINUX_MEM_AREA_REC **ppsCurrentRecord;
996 mutex_lock(&g_sDebugMutex);
998 if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
999 g_LinuxMemAreaWaterMark -= psLinuxMemArea->ui32ByteSize;
1000 g_LinuxMemAreaCount--;
1002 for (ppsCurrentRecord = &g_LinuxMemAreaRecords;
1004 ppsCurrentRecord = &((*ppsCurrentRecord)->psNext))
1005 if ((*ppsCurrentRecord)->psLinuxMemArea == psLinuxMemArea) {
1006 struct DEBUG_LINUX_MEM_AREA_REC *psNextRecord;
1008 psNextRecord = (*ppsCurrentRecord)->psNext;
1009 kfree(*ppsCurrentRecord);
1010 *ppsCurrentRecord = psNextRecord;
1014 PVR_DPF(PVR_DBG_ERROR,
1015 "%s: couldn't find an entry for psLinuxMemArea=%p\n", __func__,
1019 mutex_unlock(&g_sDebugMutex);
1023 void *LinuxMemAreaToCpuVAddr(struct LinuxMemArea *psLinuxMemArea)
1025 switch (psLinuxMemArea->eAreaType) {
1026 case LINUX_MEM_AREA_VMALLOC:
1027 return psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
1028 case LINUX_MEM_AREA_IOREMAP:
1029 return (void __force *)
1030 psLinuxMemArea->uData.sIORemap.pvIORemapCookie;
1031 case LINUX_MEM_AREA_EXTERNAL_KV:
1032 return psLinuxMemArea->uData.sExternalKV.pvExternalKV;
1033 case LINUX_MEM_AREA_SUB_ALLOC:
1036 LinuxMemAreaToCpuVAddr(psLinuxMemArea->uData.
1038 psParentLinuxMemArea);
1042 psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset;
1049 struct IMG_CPU_PHYADDR LinuxMemAreaToCpuPAddr(
1050 struct LinuxMemArea *psLinuxMemArea,
1053 struct IMG_CPU_PHYADDR CpuPAddr;
1055 CpuPAddr.uiAddr = 0;
1057 switch (psLinuxMemArea->eAreaType) {
1058 case LINUX_MEM_AREA_IOREMAP:
1060 CpuPAddr = psLinuxMemArea->uData.sIORemap.CPUPhysAddr;
1061 CpuPAddr.uiAddr += ui32ByteOffset;
1064 case LINUX_MEM_AREA_EXTERNAL_KV:
1066 if (psLinuxMemArea->uData.sExternalKV.bPhysContig) {
1068 SysSysPAddrToCpuPAddr(
1069 psLinuxMemArea->uData.
1070 sExternalKV.uPhysAddr.
1072 CpuPAddr.uiAddr += ui32ByteOffset;
1075 PHYS_TO_PFN(ui32ByteOffset);
1076 struct IMG_SYS_PHYADDR SysPAddr =
1077 psLinuxMemArea->uData.sExternalKV.uPhysAddr.
1078 pSysPhysAddr[ui32PageIndex];
1080 CpuPAddr = SysSysPAddrToCpuPAddr(SysPAddr);
1082 ADDR_TO_PAGE_OFFSET(ui32ByteOffset);
1086 case LINUX_MEM_AREA_IO:
1088 CpuPAddr = psLinuxMemArea->uData.sIO.CPUPhysAddr;
1089 CpuPAddr.uiAddr += ui32ByteOffset;
1092 case LINUX_MEM_AREA_VMALLOC:
1096 (char *) psLinuxMemArea->uData.sVmalloc.
1098 pCpuVAddr += ui32ByteOffset;
1099 CpuPAddr.uiAddr = VMallocToPhys(pCpuVAddr);
1102 case LINUX_MEM_AREA_ALLOC_PAGES:
1105 u32 ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
1107 psLinuxMemArea->uData.sPageList.
1108 pvPageList[ui32PageIndex];
1109 CpuPAddr.uiAddr = page_to_phys(page);
1110 CpuPAddr.uiAddr += ADDR_TO_PAGE_OFFSET(ui32ByteOffset);
1113 case LINUX_MEM_AREA_SUB_ALLOC:
1116 OSMemHandleToCpuPAddr(psLinuxMemArea->uData.
1118 psParentLinuxMemArea,
1119 psLinuxMemArea->uData.
1120 sSubAlloc.ui32ByteOffset +
1125 PVR_DPF(PVR_DBG_ERROR,
1126 "%s: Unknown struct LinuxMemArea type (%d)\n",
1127 __func__, psLinuxMemArea->eAreaType);
1130 PVR_ASSERT(CpuPAddr.uiAddr);
1134 static void inv_cache_vmalloc(const struct LinuxMemArea *mem_area)
1141 u32 vaddr, vaddr_end;
1143 vaddr = (u32)mem_area->uData.sVmalloc.pvVmallocAddress;
1144 vaddr_end = vaddr + mem_area->ui32ByteSize;
1145 pg_cnt = (PAGE_ALIGN(vaddr_end) - (vaddr & PAGE_MASK)) / PAGE_SIZE;
1148 pg = pfn_to_page(VMallocToPhys((void *)vaddr) >> PAGE_SHIFT);
1149 kaddr = page_address(pg);
1150 pg_ofs = vaddr & ~PAGE_MASK;
1152 chunk = min_t(ssize_t, vaddr_end - vaddr, PAGE_SIZE - pg_ofs);
1153 dmac_map_area(kaddr, chunk, DMA_FROM_DEVICE);
1158 static void inv_cache_page_list(const struct LinuxMemArea *mem_area)
1161 struct page **pg_list;
1163 pg_cnt = RANGE_TO_PAGES(mem_area->ui32ByteSize);
1164 pg_list = mem_area->uData.sPageList.pvPageList;
1166 dmac_map_area(page_address(*pg_list++), PAGE_SIZE,
1170 void inv_cache_mem_area(const struct LinuxMemArea *mem_area)
1172 switch (mem_area->eAreaType) {
1173 case LINUX_MEM_AREA_VMALLOC:
1174 inv_cache_vmalloc(mem_area);
1176 case LINUX_MEM_AREA_ALLOC_PAGES:
1177 inv_cache_page_list(mem_area);
1179 case LINUX_MEM_AREA_IOREMAP:
1180 case LINUX_MEM_AREA_EXTERNAL_KV:
1181 case LINUX_MEM_AREA_IO:
1182 case LINUX_MEM_AREA_SUB_ALLOC:
1183 PVR_DPF(PVR_DBG_ERROR,
1184 "%s: Not implemented for type (%d)\n",
1185 __func__, mem_area->eAreaType);
1188 PVR_DPF(PVR_DBG_ERROR,
1189 "%s: Unknown LinuxMemArea type (%d)\n",
1190 __func__, mem_area->eAreaType);
1195 IMG_BOOL LinuxMemAreaPhysIsContig(struct LinuxMemArea *psLinuxMemArea)
1197 switch (psLinuxMemArea->eAreaType) {
1198 case LINUX_MEM_AREA_IOREMAP:
1199 case LINUX_MEM_AREA_IO:
1202 case LINUX_MEM_AREA_EXTERNAL_KV:
1203 return psLinuxMemArea->uData.sExternalKV.bPhysContig;
1205 case LINUX_MEM_AREA_VMALLOC:
1206 case LINUX_MEM_AREA_ALLOC_PAGES:
1209 case LINUX_MEM_AREA_SUB_ALLOC:
1210 return LinuxMemAreaPhysIsContig(psLinuxMemArea->uData.sSubAlloc.
1211 psParentLinuxMemArea);
1214 PVR_DPF(PVR_DBG_ERROR,
1215 "%s: Unknown struct LinuxMemArea type (%d)\n",
1216 __func__, psLinuxMemArea->eAreaType);
1222 const char *LinuxMemAreaTypeToString(enum LINUX_MEM_AREA_TYPE eMemAreaType)
1224 switch (eMemAreaType) {
1225 case LINUX_MEM_AREA_IOREMAP:
1226 return "LINUX_MEM_AREA_IOREMAP";
1227 case LINUX_MEM_AREA_EXTERNAL_KV:
1228 return "LINUX_MEM_AREA_EXTERNAL_KV";
1229 case LINUX_MEM_AREA_IO:
1230 return "LINUX_MEM_AREA_IO";
1231 case LINUX_MEM_AREA_VMALLOC:
1232 return "LINUX_MEM_AREA_VMALLOC";
1233 case LINUX_MEM_AREA_SUB_ALLOC:
1234 return "LINUX_MEM_AREA_SUB_ALLOC";
1235 case LINUX_MEM_AREA_ALLOC_PAGES:
1236 return "LINUX_MEM_AREA_ALLOC_PAGES";
1244 #if defined(DEBUG_LINUX_MEM_AREAS)
1245 static off_t printLinuxMemAreaRecords(char *buffer, size_t count, off_t off)
1247 struct DEBUG_LINUX_MEM_AREA_REC *psRecord;
1250 mutex_lock(&g_sDebugMutex);
1255 goto unlock_and_return;
1257 Ret = printAppend(buffer, count, 0,
1258 "Number of Linux Memory Areas: %u\n"
1259 "At the current water mark these areas "
1260 "correspond to %u bytes "
1261 "(excluding SUB areas)\n"
1262 "At the highest water mark these areas "
1263 "corresponded to %u bytes "
1264 "(excluding SUB areas)\n"
1265 "\nDetails for all Linux Memory Areas:\n"
1266 "%s %-24s %s %s %-8s %-5s %s\n",
1267 g_LinuxMemAreaCount,
1268 g_LinuxMemAreaWaterMark,
1269 g_LinuxMemAreaHighWaterMark,
1273 "CpuPAddr", "Bytes", "Pid", "Flags");
1274 goto unlock_and_return;
1277 for (psRecord = g_LinuxMemAreaRecords; --off && psRecord;
1278 psRecord = psRecord->psNext)
1282 goto unlock_and_return;
1287 goto unlock_and_return;
1290 Ret = printAppend(buffer, count, 0,
1291 "%8p %-24s %8p %08x %-8d %-5u %08x=(%s)\n",
1292 psRecord->psLinuxMemArea,
1293 LinuxMemAreaTypeToString(psRecord->psLinuxMemArea->
1295 LinuxMemAreaToCpuVAddr(psRecord->psLinuxMemArea),
1296 LinuxMemAreaToCpuPAddr(psRecord->psLinuxMemArea,
1298 psRecord->psLinuxMemArea->ui32ByteSize, psRecord->pid,
1299 psRecord->ui32Flags,
1300 HAPFlagsToString(psRecord->ui32Flags)
1304 mutex_unlock(&g_sDebugMutex);
1309 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
1310 static off_t printMemoryRecords(char *buffer, size_t count, off_t off)
1312 struct DEBUG_MEM_ALLOC_REC *psRecord;
1315 mutex_lock(&g_sDebugMutex);
1320 goto unlock_and_return;
1323 Ret = printAppend(buffer, count, 0, "%-60s: %d bytes\n",
1324 "Current Water Mark of bytes allocated via kmalloc",
1325 g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
1326 Ret = printAppend(buffer, count, Ret, "%-60s: %d bytes\n",
1327 "Highest Water Mark of bytes allocated via kmalloc",
1329 [DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
1330 Ret = printAppend(buffer, count, Ret, "%-60s: %d bytes\n",
1331 "Current Water Mark of bytes allocated via vmalloc",
1332 g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
1333 Ret = printAppend(buffer, count, Ret, "%-60s: %d bytes\n",
1334 "Highest Water Mark of bytes allocated via vmalloc",
1336 [DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
1337 Ret = printAppend(buffer, count, Ret, "%-60s: %d bytes\n",
1338 "Current Water Mark of bytes allocated via alloc_pages",
1340 [DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
1341 Ret = printAppend(buffer, count, Ret, "%-60s: %d bytes\n",
1342 "Highest Water Mark of bytes allocated via alloc_pages",
1344 [DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
1345 Ret = printAppend(buffer, count, Ret, "%-60s: %d bytes\n",
1346 "Current Water Mark of bytes allocated via ioremap",
1347 g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
1348 Ret = printAppend(buffer, count, Ret, "%-60s: %d bytes\n",
1349 "Highest Water Mark of bytes allocated via ioremap",
1351 [DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
1352 Ret = printAppend(buffer, count, Ret, "%-60s: %d bytes\n",
1353 "Current Water Mark of bytes reserved for "
1354 "\"IO\" memory areas",
1355 g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
1356 Ret = printAppend(buffer, count, Ret, "%-60s: %d bytes\n",
1357 "Highest Water Mark of bytes allocated for "
1358 "\"IO\" memory areas",
1359 g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
1360 Ret = printAppend(buffer, count, Ret, "%-60s: %d bytes\n",
1361 "Current Water Mark of bytes allocated via "
1364 [DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
1365 Ret = printAppend(buffer, count, Ret, "%-60s: %d bytes\n",
1366 "Highest Water Mark of bytes allocated via "
1369 [DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
1370 Ret = printAppend(buffer, count, Ret, "\n");
1372 Ret = printAppend(buffer, count, Ret, "%-60s: %d bytes\n",
1373 "The Current Water Mark for memory allocated from system RAM",
1375 Ret = printAppend(buffer, count, Ret, "%-60s: %d bytes\n",
1376 "The Highest Water Mark for memory allocated from system RAM",
1377 g_SysRAMHighWaterMark);
1378 Ret = printAppend(buffer, count, Ret, "%-60s: %d bytes\n",
1379 "The Current Water Mark for memory allocated from IO memory",
1381 Ret = printAppend(buffer, count, Ret, "%-60s: %d bytes\n",
1382 "The Highest Water Mark for memory allocated from IO memory",
1383 g_IOMemHighWaterMark);
1385 Ret = printAppend(buffer, count, Ret, "\n");
1387 Ret = printAppend(buffer, count, Ret,
1388 "Details for all known allocations:\n"
1389 "%-16s %-8s %-8s %-10s %-5s %-10s %s\n", "Type",
1390 "CpuVAddr", "CpuPAddr", "Bytes", "PID",
1391 "PrivateData", "Filename:Line");
1394 goto unlock_and_return;
1399 goto unlock_and_return;
1402 for (psRecord = g_MemoryRecords; --off && psRecord;
1403 psRecord = psRecord->psNext)
1407 goto unlock_and_return;
1410 if (psRecord->eAllocType != DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
1411 Ret = printAppend(buffer, count, 0,
1412 "%-16s %-8p %08x %-10d %-5d %-10s %s:%d\n",
1413 DebugMemAllocRecordTypeToString(psRecord->eAllocType),
1414 psRecord->pvCpuVAddr, psRecord->ulCpuPAddr,
1415 psRecord->ui32Bytes, psRecord->pid, "NULL",
1416 psRecord->pszFileName, psRecord->ui32Line);
1418 Ret = printAppend(buffer, count, 0,
1419 "%-16s %-8p %08x %-10d %-5d %-10s %s:%d\n",
1420 DebugMemAllocRecordTypeToString(psRecord->eAllocType),
1421 psRecord->pvCpuVAddr, psRecord->ulCpuPAddr,
1422 psRecord->ui32Bytes, psRecord->pid,
1423 KMemCacheNameWrapper(psRecord->pvPrivateData),
1424 psRecord->pszFileName, psRecord->ui32Line);
1427 mutex_unlock(&g_sDebugMutex);
1432 #if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MMAP_AREAS)
1433 const char *HAPFlagsToString(u32 ui32Flags)
1435 static char szFlags[50];
1437 u32 ui32CacheTypeIndex, ui32MapTypeIndex;
1438 char *apszCacheTypes[] = {
1444 char *apszMapType[] = {
1448 "FROM_EXISTING_PROCESS",
1453 if (ui32Flags & PVRSRV_HAP_UNCACHED) {
1454 ui32CacheTypeIndex = 0;
1455 } else if (ui32Flags & PVRSRV_HAP_CACHED) {
1456 ui32CacheTypeIndex = 1;
1457 } else if (ui32Flags & PVRSRV_HAP_WRITECOMBINE) {
1458 ui32CacheTypeIndex = 2;
1460 ui32CacheTypeIndex = 3;
1461 PVR_DPF(PVR_DBG_ERROR, "%s: unknown cache type (%u)",
1462 __func__, (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK));
1465 if (ui32Flags & PVRSRV_HAP_KERNEL_ONLY) {
1466 ui32MapTypeIndex = 0;
1467 } else if (ui32Flags & PVRSRV_HAP_SINGLE_PROCESS) {
1468 ui32MapTypeIndex = 1;
1469 } else if (ui32Flags & PVRSRV_HAP_MULTI_PROCESS) {
1470 ui32MapTypeIndex = 2;
1471 } else if (ui32Flags & PVRSRV_HAP_FROM_EXISTING_PROCESS) {
1472 ui32MapTypeIndex = 3;
1473 } else if (ui32Flags & PVRSRV_HAP_NO_CPU_VIRTUAL) {
1474 ui32MapTypeIndex = 4;
1476 ui32MapTypeIndex = 5;
1477 PVR_DPF(PVR_DBG_ERROR, "%s: unknown map type (%u)",
1478 __func__, (ui32Flags & PVRSRV_HAP_MAPTYPE_MASK));
1481 i32Pos = sprintf(szFlags, "%s|", apszCacheTypes[ui32CacheTypeIndex]);
1483 PVR_DPF(PVR_DBG_ERROR,
1484 "%s: sprintf for cache type %u failed (%d)", __func__,
1485 ui32CacheTypeIndex, i32Pos);
1488 sprintf(szFlags + i32Pos, "%s", apszMapType[ui32MapTypeIndex]);