aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/pvr/mm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/pvr/mm.c')
-rw-r--r--drivers/gpu/pvr/mm.c2012
1 files changed, 2012 insertions, 0 deletions
diff --git a/drivers/gpu/pvr/mm.c b/drivers/gpu/pvr/mm.c
new file mode 100644
index 00000000000..ecaba8e1015
--- /dev/null
+++ b/drivers/gpu/pvr/mm.c
@@ -0,0 +1,2012 @@
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#ifndef AUTOCONF_INCLUDED
28 #include <linux/config.h>
29#endif
30
31#include <linux/version.h>
32#include <linux/mm.h>
33#include <linux/vmalloc.h>
34#include <asm/io.h>
35#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
36#include <linux/wrapper.h>
37#endif
38#include <linux/slab.h>
39#include <linux/highmem.h>
40#include <linux/sched.h>
41
42#include "img_defs.h"
43#include "services.h"
44#include "servicesint.h"
45#include "syscommon.h"
46#include "mutils.h"
47#include "mm.h"
48#include "pvrmmap.h"
49#include "mmap.h"
50#include "osfunc.h"
51#include "pvr_debug.h"
52#include "proc.h"
53#include "mutex.h"
54#include "lock.h"
55
56#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
57 #include "lists.h"
58#endif
59
60#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
61typedef enum {
62 DEBUG_MEM_ALLOC_TYPE_KMALLOC,
63 DEBUG_MEM_ALLOC_TYPE_VMALLOC,
64 DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES,
65 DEBUG_MEM_ALLOC_TYPE_IOREMAP,
66 DEBUG_MEM_ALLOC_TYPE_IO,
67 DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE,
68 DEBUG_MEM_ALLOC_TYPE_COUNT
69}DEBUG_MEM_ALLOC_TYPE;
70
71typedef struct _DEBUG_MEM_ALLOC_REC
72{
73 DEBUG_MEM_ALLOC_TYPE eAllocType;
74 IMG_VOID *pvKey;
75 IMG_VOID *pvCpuVAddr;
76 IMG_UINT32 ulCpuPAddr;
77 IMG_VOID *pvPrivateData;
78 IMG_UINT32 ui32Bytes;
79 pid_t pid;
80 IMG_CHAR *pszFileName;
81 IMG_UINT32 ui32Line;
82
83 struct _DEBUG_MEM_ALLOC_REC *psNext;
84 struct _DEBUG_MEM_ALLOC_REC **ppsThis;
85}DEBUG_MEM_ALLOC_REC;
86
87static IMPLEMENT_LIST_ANY_VA_2(DEBUG_MEM_ALLOC_REC, IMG_BOOL, IMG_FALSE)
88static IMPLEMENT_LIST_ANY_VA(DEBUG_MEM_ALLOC_REC)
89static IMPLEMENT_LIST_FOR_EACH(DEBUG_MEM_ALLOC_REC)
90static IMPLEMENT_LIST_INSERT(DEBUG_MEM_ALLOC_REC)
91static IMPLEMENT_LIST_REMOVE(DEBUG_MEM_ALLOC_REC)
92
93
94static DEBUG_MEM_ALLOC_REC *g_MemoryRecords;
95
96static IMG_UINT32 g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_COUNT];
97static IMG_UINT32 g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_COUNT];
98
99static IMG_UINT32 g_SysRAMWaterMark;
100static IMG_UINT32 g_SysRAMHighWaterMark;
101
102static IMG_UINT32 g_IOMemWaterMark;
103static IMG_UINT32 g_IOMemHighWaterMark;
104
105static IMG_VOID DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE eAllocType,
106 IMG_VOID *pvKey,
107 IMG_VOID *pvCpuVAddr,
108 IMG_UINT32 ulCpuPAddr,
109 IMG_VOID *pvPrivateData,
110 IMG_UINT32 ui32Bytes,
111 IMG_CHAR *pszFileName,
112 IMG_UINT32 ui32Line);
113
114static IMG_VOID DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE eAllocType, IMG_VOID *pvKey, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
115
116static IMG_CHAR *DebugMemAllocRecordTypeToString(DEBUG_MEM_ALLOC_TYPE eAllocType);
117
118
119static struct proc_dir_entry *g_SeqFileMemoryRecords =0;
120static void* ProcSeqNextMemoryRecords(struct seq_file *sfile,void* el,loff_t off);
121static void ProcSeqShowMemoryRecords(struct seq_file *sfile,void* el);
122static void* ProcSeqOff2ElementMemoryRecords(struct seq_file * sfile, loff_t off);
123
124#endif
125
126
127#if defined(DEBUG_LINUX_MEM_AREAS)
128typedef struct _DEBUG_LINUX_MEM_AREA_REC
129{
130 LinuxMemArea *psLinuxMemArea;
131 IMG_UINT32 ui32Flags;
132 pid_t pid;
133
134 struct _DEBUG_LINUX_MEM_AREA_REC *psNext;
135 struct _DEBUG_LINUX_MEM_AREA_REC **ppsThis;
136}DEBUG_LINUX_MEM_AREA_REC;
137
138
139static IMPLEMENT_LIST_ANY_VA(DEBUG_LINUX_MEM_AREA_REC)
140static IMPLEMENT_LIST_FOR_EACH(DEBUG_LINUX_MEM_AREA_REC)
141static IMPLEMENT_LIST_INSERT(DEBUG_LINUX_MEM_AREA_REC)
142static IMPLEMENT_LIST_REMOVE(DEBUG_LINUX_MEM_AREA_REC)
143
144
145
146
147static DEBUG_LINUX_MEM_AREA_REC *g_LinuxMemAreaRecords;
148static IMG_UINT32 g_LinuxMemAreaCount;
149static IMG_UINT32 g_LinuxMemAreaWaterMark;
150static IMG_UINT32 g_LinuxMemAreaHighWaterMark;
151
152
153static struct proc_dir_entry *g_SeqFileMemArea=0;
154
155static void* ProcSeqNextMemArea(struct seq_file *sfile,void* el,loff_t off);
156static void ProcSeqShowMemArea(struct seq_file *sfile,void* el);
157static void* ProcSeqOff2ElementMemArea(struct seq_file *sfile, loff_t off);
158
159#endif
160
161#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
162static PVRSRV_LINUX_MUTEX g_sDebugMutex;
163#endif
164
165#if (defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS))
166static void ProcSeqStartstopDebugMutex(struct seq_file *sfile,IMG_BOOL start);
167#endif
168
169static LinuxKMemCache *psLinuxMemAreaCache;
170
171
172#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
173static IMG_VOID ReservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length);
174static IMG_VOID UnreservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length);
175#endif
176
177static LinuxMemArea *LinuxMemAreaStructAlloc(IMG_VOID);
178static IMG_VOID LinuxMemAreaStructFree(LinuxMemArea *psLinuxMemArea);
179#if defined(DEBUG_LINUX_MEM_AREAS)
180static IMG_VOID DebugLinuxMemAreaRecordAdd(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Flags);
181static DEBUG_LINUX_MEM_AREA_REC *DebugLinuxMemAreaRecordFind(LinuxMemArea *psLinuxMemArea);
182static IMG_VOID DebugLinuxMemAreaRecordRemove(LinuxMemArea *psLinuxMemArea);
183#endif
184
185PVRSRV_ERROR
186LinuxMMInit(IMG_VOID)
187{
188#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
189 LinuxInitMutex(&g_sDebugMutex);
190#endif
191
192#if defined(DEBUG_LINUX_MEM_AREAS)
193 {
194 g_SeqFileMemArea = CreateProcReadEntrySeq(
195 "mem_areas",
196 NULL,
197 ProcSeqNextMemArea,
198 ProcSeqShowMemArea,
199 ProcSeqOff2ElementMemArea,
200 ProcSeqStartstopDebugMutex
201 );
202 if(!g_SeqFileMemArea)
203 {
204 return PVRSRV_ERROR_OUT_OF_MEMORY;
205 }
206 }
207#endif
208
209
210#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
211 {
212 g_SeqFileMemoryRecords =CreateProcReadEntrySeq(
213 "meminfo",
214 NULL,
215 ProcSeqNextMemoryRecords,
216 ProcSeqShowMemoryRecords,
217 ProcSeqOff2ElementMemoryRecords,
218 ProcSeqStartstopDebugMutex
219 );
220 if(!g_SeqFileMemoryRecords)
221 {
222 return PVRSRV_ERROR_OUT_OF_MEMORY;
223 }
224 }
225#endif
226
227 psLinuxMemAreaCache = KMemCacheCreateWrapper("img-mm", sizeof(LinuxMemArea), 0, 0);
228 if(!psLinuxMemAreaCache)
229 {
230 PVR_DPF((PVR_DBG_ERROR,"%s: failed to allocate kmem_cache", __FUNCTION__));
231 return PVRSRV_ERROR_OUT_OF_MEMORY;
232 }
233
234 return PVRSRV_OK;
235}
236
237#if defined(DEBUG_LINUX_MEM_AREAS)
238static IMG_VOID LinuxMMCleanup_MemAreas_ForEachCb(DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord)
239{
240 LinuxMemArea *psLinuxMemArea;
241
242 psLinuxMemArea = psCurrentRecord->psLinuxMemArea;
243 PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: Cleaning up Linux memory area (%p), type=%s, size=%d bytes",
244 __FUNCTION__,
245 psCurrentRecord->psLinuxMemArea,
246 LinuxMemAreaTypeToString(psCurrentRecord->psLinuxMemArea->eAreaType),
247 psCurrentRecord->psLinuxMemArea->ui32ByteSize));
248
249 LinuxMemAreaDeepFree(psLinuxMemArea);
250}
251#endif
252
253#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
254static IMG_VOID LinuxMMCleanup_MemRecords_ForEachVa(DEBUG_MEM_ALLOC_REC *psCurrentRecord)
255
256{
257
258 PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: Cleaning up memory: "
259 "type=%s "
260 "CpuVAddr=%p "
261 "CpuPAddr=0x%08x, "
262 "allocated @ file=%s,line=%d",
263 __FUNCTION__,
264 DebugMemAllocRecordTypeToString(psCurrentRecord->eAllocType),
265 psCurrentRecord->pvCpuVAddr,
266 psCurrentRecord->ulCpuPAddr,
267 psCurrentRecord->pszFileName,
268 psCurrentRecord->ui32Line));
269 switch(psCurrentRecord->eAllocType)
270 {
271 case DEBUG_MEM_ALLOC_TYPE_KMALLOC:
272 KFreeWrapper(psCurrentRecord->pvCpuVAddr);
273 break;
274 case DEBUG_MEM_ALLOC_TYPE_IOREMAP:
275 IOUnmapWrapper(psCurrentRecord->pvCpuVAddr);
276 break;
277 case DEBUG_MEM_ALLOC_TYPE_IO:
278
279 DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IO, psCurrentRecord->pvKey, __FILE__, __LINE__);
280 break;
281 case DEBUG_MEM_ALLOC_TYPE_VMALLOC:
282 VFreeWrapper(psCurrentRecord->pvCpuVAddr);
283 break;
284 case DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES:
285
286 DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, psCurrentRecord->pvKey, __FILE__, __LINE__);
287 break;
288 case DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE:
289 KMemCacheFreeWrapper(psCurrentRecord->pvPrivateData, psCurrentRecord->pvCpuVAddr);
290 break;
291 default:
292 PVR_ASSERT(0);
293 }
294}
295#endif
296
297
298IMG_VOID
299LinuxMMCleanup(IMG_VOID)
300{
301
302#if defined(DEBUG_LINUX_MEM_AREAS)
303 {
304 if(g_LinuxMemAreaCount)
305 {
306 PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: There are %d LinuxMemArea allocation unfreed (%d bytes)",
307 __FUNCTION__, g_LinuxMemAreaCount, g_LinuxMemAreaWaterMark));
308 }
309
310 List_DEBUG_LINUX_MEM_AREA_REC_ForEach(g_LinuxMemAreaRecords,
311 LinuxMMCleanup_MemAreas_ForEachCb);
312
313 RemoveProcEntrySeq( g_SeqFileMemArea );
314 }
315#endif
316
317
318#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
319 {
320
321
322 List_DEBUG_MEM_ALLOC_REC_ForEach(g_MemoryRecords,
323 LinuxMMCleanup_MemRecords_ForEachVa);
324
325 RemoveProcEntrySeq( g_SeqFileMemoryRecords );
326 }
327#endif
328
329 if(psLinuxMemAreaCache)
330 {
331 KMemCacheDestroyWrapper(psLinuxMemAreaCache);
332 psLinuxMemAreaCache=NULL;
333 }
334}
335
336
337IMG_VOID *
338_KMallocWrapper(IMG_UINT32 ui32ByteSize, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
339{
340 IMG_VOID *pvRet;
341 pvRet = kmalloc(ui32ByteSize, GFP_KERNEL);
342#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
343 if(pvRet)
344 {
345 DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_KMALLOC,
346 pvRet,
347 pvRet,
348 0,
349 NULL,
350 ui32ByteSize,
351 pszFileName,
352 ui32Line
353 );
354 }
355#else
356 PVR_UNREFERENCED_PARAMETER(pszFileName);
357 PVR_UNREFERENCED_PARAMETER(ui32Line);
358#endif
359 return pvRet;
360}
361
362
363IMG_VOID
364_KFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
365{
366#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
367 DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_KMALLOC, pvCpuVAddr, pszFileName, ui32Line);
368#else
369 PVR_UNREFERENCED_PARAMETER(pszFileName);
370 PVR_UNREFERENCED_PARAMETER(ui32Line);
371#endif
372 kfree(pvCpuVAddr);
373}
374
375
376#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
377static IMG_VOID
378DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE eAllocType,
379 IMG_VOID *pvKey,
380 IMG_VOID *pvCpuVAddr,
381 IMG_UINT32 ulCpuPAddr,
382 IMG_VOID *pvPrivateData,
383 IMG_UINT32 ui32Bytes,
384 IMG_CHAR *pszFileName,
385 IMG_UINT32 ui32Line)
386{
387 DEBUG_MEM_ALLOC_REC *psRecord;
388
389 LinuxLockMutex(&g_sDebugMutex);
390
391 psRecord = kmalloc(sizeof(DEBUG_MEM_ALLOC_REC), GFP_KERNEL);
392
393 psRecord->eAllocType = eAllocType;
394 psRecord->pvKey = pvKey;
395 psRecord->pvCpuVAddr = pvCpuVAddr;
396 psRecord->ulCpuPAddr = ulCpuPAddr;
397 psRecord->pvPrivateData = pvPrivateData;
398 psRecord->pid = current->pid;
399 psRecord->ui32Bytes = ui32Bytes;
400 psRecord->pszFileName = pszFileName;
401 psRecord->ui32Line = ui32Line;
402
403 List_DEBUG_MEM_ALLOC_REC_Insert(&g_MemoryRecords, psRecord);
404
405 g_WaterMarkData[eAllocType] += ui32Bytes;
406 if(g_WaterMarkData[eAllocType] > g_HighWaterMarkData[eAllocType])
407 {
408 g_HighWaterMarkData[eAllocType] = g_WaterMarkData[eAllocType];
409 }
410
411 if(eAllocType == DEBUG_MEM_ALLOC_TYPE_KMALLOC
412 || eAllocType == DEBUG_MEM_ALLOC_TYPE_VMALLOC
413 || eAllocType == DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES
414 || eAllocType == DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
415 {
416 g_SysRAMWaterMark += ui32Bytes;
417 if(g_SysRAMWaterMark > g_SysRAMHighWaterMark)
418 {
419 g_SysRAMHighWaterMark = g_SysRAMWaterMark;
420 }
421 }
422 else if(eAllocType == DEBUG_MEM_ALLOC_TYPE_IOREMAP
423 || eAllocType == DEBUG_MEM_ALLOC_TYPE_IO)
424 {
425 g_IOMemWaterMark += ui32Bytes;
426 if(g_IOMemWaterMark > g_IOMemHighWaterMark)
427 {
428 g_IOMemHighWaterMark = g_IOMemWaterMark;
429 }
430 }
431
432 LinuxUnLockMutex(&g_sDebugMutex);
433}
434
435
436static IMG_BOOL DebugMemAllocRecordRemove_AnyVaCb(DEBUG_MEM_ALLOC_REC *psCurrentRecord, va_list va)
437{
438 DEBUG_MEM_ALLOC_TYPE eAllocType;
439 IMG_VOID *pvKey;
440
441 eAllocType = va_arg(va, DEBUG_MEM_ALLOC_TYPE);
442 pvKey = va_arg(va, IMG_VOID*);
443
444 if(psCurrentRecord->eAllocType == eAllocType
445 && psCurrentRecord->pvKey == pvKey)
446 {
447 eAllocType = psCurrentRecord->eAllocType;
448 g_WaterMarkData[eAllocType] -= psCurrentRecord->ui32Bytes;
449
450 if(eAllocType == DEBUG_MEM_ALLOC_TYPE_KMALLOC
451 || eAllocType == DEBUG_MEM_ALLOC_TYPE_VMALLOC
452 || eAllocType == DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES
453 || eAllocType == DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
454 {
455 g_SysRAMWaterMark -= psCurrentRecord->ui32Bytes;
456 }
457 else if(eAllocType == DEBUG_MEM_ALLOC_TYPE_IOREMAP
458 || eAllocType == DEBUG_MEM_ALLOC_TYPE_IO)
459 {
460 g_IOMemWaterMark -= psCurrentRecord->ui32Bytes;
461 }
462
463 List_DEBUG_MEM_ALLOC_REC_Remove(psCurrentRecord);
464 kfree(psCurrentRecord);
465
466 return IMG_TRUE;
467 }
468 else
469 {
470 return IMG_FALSE;
471 }
472}
473
474
475static IMG_VOID
476DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE eAllocType, IMG_VOID *pvKey, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
477{
478 LinuxLockMutex(&g_sDebugMutex);
479
480
481 if(!List_DEBUG_MEM_ALLOC_REC_IMG_BOOL_Any_va(g_MemoryRecords,
482 DebugMemAllocRecordRemove_AnyVaCb,
483 eAllocType,
484 pvKey))
485 {
486 PVR_DPF((PVR_DBG_ERROR, "%s: couldn't find an entry for type=%s with pvKey=%p (called from %s, line %d\n",
487 __FUNCTION__, DebugMemAllocRecordTypeToString(eAllocType), pvKey,
488 pszFileName, ui32Line));
489 }
490
491 LinuxUnLockMutex(&g_sDebugMutex);
492}
493
494
495static IMG_CHAR *
496DebugMemAllocRecordTypeToString(DEBUG_MEM_ALLOC_TYPE eAllocType)
497{
498 IMG_CHAR *apszDebugMemoryRecordTypes[] = {
499 "KMALLOC",
500 "VMALLOC",
501 "ALLOC_PAGES",
502 "IOREMAP",
503 "IO",
504 "KMEM_CACHE_ALLOC"
505 };
506 return apszDebugMemoryRecordTypes[eAllocType];
507}
508#endif
509
510
511
512IMG_VOID *
513_VMallocWrapper(IMG_UINT32 ui32Bytes,
514 IMG_UINT32 ui32AllocFlags,
515 IMG_CHAR *pszFileName,
516 IMG_UINT32 ui32Line)
517{
518 pgprot_t PGProtFlags;
519 IMG_VOID *pvRet;
520
521 switch(ui32AllocFlags & PVRSRV_HAP_CACHETYPE_MASK)
522 {
523 case PVRSRV_HAP_CACHED:
524 PGProtFlags = PAGE_KERNEL;
525 break;
526 case PVRSRV_HAP_WRITECOMBINE:
527 PGProtFlags = PGPROT_WC(PAGE_KERNEL);
528 break;
529 case PVRSRV_HAP_UNCACHED:
530 PGProtFlags = PGPROT_UC(PAGE_KERNEL);
531 break;
532 default:
533 PVR_DPF((PVR_DBG_ERROR,
534 "VMAllocWrapper: unknown mapping flags=0x%08x",
535 ui32AllocFlags));
536 dump_stack();
537 return NULL;
538 }
539
540
541 pvRet = __vmalloc(ui32Bytes, GFP_KERNEL | __GFP_HIGHMEM, PGProtFlags);
542
543#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
544 if(pvRet)
545 {
546 DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_VMALLOC,
547 pvRet,
548 pvRet,
549 0,
550 NULL,
551 PAGE_ALIGN(ui32Bytes),
552 pszFileName,
553 ui32Line
554 );
555 }
556#else
557 PVR_UNREFERENCED_PARAMETER(pszFileName);
558 PVR_UNREFERENCED_PARAMETER(ui32Line);
559#endif
560
561 return pvRet;
562}
563
564
565IMG_VOID
566_VFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
567{
568#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
569 DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_VMALLOC, pvCpuVAddr, pszFileName, ui32Line);
570#else
571 PVR_UNREFERENCED_PARAMETER(pszFileName);
572 PVR_UNREFERENCED_PARAMETER(ui32Line);
573#endif
574 vfree(pvCpuVAddr);
575}
576
577
578LinuxMemArea *
579NewVMallocLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags)
580{
581 LinuxMemArea *psLinuxMemArea;
582 IMG_VOID *pvCpuVAddr;
583
584 psLinuxMemArea = LinuxMemAreaStructAlloc();
585 if(!psLinuxMemArea)
586 {
587 goto failed;
588 }
589
590 pvCpuVAddr = VMallocWrapper(ui32Bytes, ui32AreaFlags);
591 if(!pvCpuVAddr)
592 {
593 goto failed;
594 }
595
596#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
597
598 ReservePages(pvCpuVAddr, ui32Bytes);
599#endif
600
601 psLinuxMemArea->eAreaType = LINUX_MEM_AREA_VMALLOC;
602 psLinuxMemArea->uData.sVmalloc.pvVmallocAddress = pvCpuVAddr;
603 psLinuxMemArea->ui32ByteSize = ui32Bytes;
604 psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
605 INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
606
607#if defined(DEBUG_LINUX_MEM_AREAS)
608 DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
609#endif
610
611
612 if(ui32AreaFlags & (PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_UNCACHED))
613 OSInvalidateCPUCacheRangeKM(psLinuxMemArea, pvCpuVAddr, ui32Bytes);
614
615 return psLinuxMemArea;
616
617failed:
618 PVR_DPF((PVR_DBG_ERROR, "%s: failed!", __FUNCTION__));
619 if(psLinuxMemArea)
620 LinuxMemAreaStructFree(psLinuxMemArea);
621 return NULL;
622}
623
624
625IMG_VOID
626FreeVMallocLinuxMemArea(LinuxMemArea *psLinuxMemArea)
627{
628 PVR_ASSERT(psLinuxMemArea);
629 PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_VMALLOC);
630 PVR_ASSERT(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress);
631
632#if defined(DEBUG_LINUX_MEM_AREAS)
633 DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
634#endif
635
636#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
637 UnreservePages(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress,
638 psLinuxMemArea->ui32ByteSize);
639#endif
640
641 PVR_DPF((PVR_DBG_MESSAGE,"%s: pvCpuVAddr: %p",
642 __FUNCTION__, psLinuxMemArea->uData.sVmalloc.pvVmallocAddress));
643 VFreeWrapper(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress);
644
645 LinuxMemAreaStructFree(psLinuxMemArea);
646}
647
648
649#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
650static IMG_VOID
651ReservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length)
652{
653 IMG_VOID *pvPage;
654 IMG_VOID *pvEnd = pvAddress + ui32Length;
655
656 for(pvPage = pvAddress; pvPage < pvEnd; pvPage += PAGE_SIZE)
657 {
658#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
659 SetPageReserved(vmalloc_to_page(pvPage));
660#else
661 mem_map_reserve(vmalloc_to_page(pvPage));
662#endif
663 }
664}
665
666
667static IMG_VOID
668UnreservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length)
669{
670 IMG_VOID *pvPage;
671 IMG_VOID *pvEnd = pvAddress + ui32Length;
672
673 for(pvPage = pvAddress; pvPage < pvEnd; pvPage += PAGE_SIZE)
674 {
675#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
676 ClearPageReserved(vmalloc_to_page(pvPage));
677#else
678 mem_map_unreserve(vmalloc_to_page(pvPage));
679#endif
680 }
681}
682#endif
683
684
685IMG_VOID *
686_IORemapWrapper(IMG_CPU_PHYADDR BasePAddr,
687 IMG_UINT32 ui32Bytes,
688 IMG_UINT32 ui32MappingFlags,
689 IMG_CHAR *pszFileName,
690 IMG_UINT32 ui32Line)
691{
692 IMG_VOID *pvIORemapCookie;
693
694 switch(ui32MappingFlags & PVRSRV_HAP_CACHETYPE_MASK)
695 {
696 case PVRSRV_HAP_CACHED:
697 pvIORemapCookie = (IMG_VOID *)IOREMAP(BasePAddr.uiAddr, ui32Bytes);
698 break;
699 case PVRSRV_HAP_WRITECOMBINE:
700 pvIORemapCookie = (IMG_VOID *)IOREMAP_WC(BasePAddr.uiAddr, ui32Bytes);
701 break;
702 case PVRSRV_HAP_UNCACHED:
703 pvIORemapCookie = (IMG_VOID *)IOREMAP_UC(BasePAddr.uiAddr, ui32Bytes);
704 break;
705 default:
706 PVR_DPF((PVR_DBG_ERROR, "IORemapWrapper: unknown mapping flags"));
707 return NULL;
708 }
709
710#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
711 if(pvIORemapCookie)
712 {
713 DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_IOREMAP,
714 pvIORemapCookie,
715 pvIORemapCookie,
716 BasePAddr.uiAddr,
717 NULL,
718 ui32Bytes,
719 pszFileName,
720 ui32Line
721 );
722 }
723#else
724 PVR_UNREFERENCED_PARAMETER(pszFileName);
725 PVR_UNREFERENCED_PARAMETER(ui32Line);
726#endif
727
728 return pvIORemapCookie;
729}
730
731
732IMG_VOID
733_IOUnmapWrapper(IMG_VOID *pvIORemapCookie, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
734{
735#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
736 DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IOREMAP, pvIORemapCookie, pszFileName, ui32Line);
737#else
738 PVR_UNREFERENCED_PARAMETER(pszFileName);
739 PVR_UNREFERENCED_PARAMETER(ui32Line);
740#endif
741 iounmap(pvIORemapCookie);
742}
743
744
745LinuxMemArea *
746NewIORemapLinuxMemArea(IMG_CPU_PHYADDR BasePAddr,
747 IMG_UINT32 ui32Bytes,
748 IMG_UINT32 ui32AreaFlags)
749{
750 LinuxMemArea *psLinuxMemArea;
751 IMG_VOID *pvIORemapCookie;
752
753 psLinuxMemArea = LinuxMemAreaStructAlloc();
754 if(!psLinuxMemArea)
755 {
756 return NULL;
757 }
758
759 pvIORemapCookie = IORemapWrapper(BasePAddr, ui32Bytes, ui32AreaFlags);
760 if(!pvIORemapCookie)
761 {
762 LinuxMemAreaStructFree(psLinuxMemArea);
763 return NULL;
764 }
765
766 psLinuxMemArea->eAreaType = LINUX_MEM_AREA_IOREMAP;
767 psLinuxMemArea->uData.sIORemap.pvIORemapCookie = pvIORemapCookie;
768 psLinuxMemArea->uData.sIORemap.CPUPhysAddr = BasePAddr;
769 psLinuxMemArea->ui32ByteSize = ui32Bytes;
770 psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
771 INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
772
773#if defined(DEBUG_LINUX_MEM_AREAS)
774 DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
775#endif
776
777 return psLinuxMemArea;
778}
779
780
781IMG_VOID
782FreeIORemapLinuxMemArea(LinuxMemArea *psLinuxMemArea)
783{
784 PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_IOREMAP);
785
786#if defined(DEBUG_LINUX_MEM_AREAS)
787 DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
788#endif
789
790 IOUnmapWrapper(psLinuxMemArea->uData.sIORemap.pvIORemapCookie);
791
792 LinuxMemAreaStructFree(psLinuxMemArea);
793}
794
795
796#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
797static IMG_BOOL
798TreatExternalPagesAsContiguous(IMG_SYS_PHYADDR *psSysPhysAddr, IMG_UINT32 ui32Bytes, IMG_BOOL bPhysContig)
799{
800 IMG_UINT32 ui32;
801 IMG_UINT32 ui32AddrChk;
802 IMG_UINT32 ui32NumPages = RANGE_TO_PAGES(ui32Bytes);
803
804
805 for (ui32 = 0, ui32AddrChk = psSysPhysAddr[0].uiAddr;
806 ui32 < ui32NumPages;
807 ui32++, ui32AddrChk = (bPhysContig) ? (ui32AddrChk + PAGE_SIZE) : psSysPhysAddr[ui32].uiAddr)
808 {
809 if (!pfn_valid(PHYS_TO_PFN(ui32AddrChk)))
810 {
811 break;
812 }
813 }
814 if (ui32 == ui32NumPages)
815 {
816 return IMG_FALSE;
817 }
818
819 if (!bPhysContig)
820 {
821 for (ui32 = 0, ui32AddrChk = psSysPhysAddr[0].uiAddr;
822 ui32 < ui32NumPages;
823 ui32++, ui32AddrChk += PAGE_SIZE)
824 {
825 if (psSysPhysAddr[ui32].uiAddr != ui32AddrChk)
826 {
827 return IMG_FALSE;
828 }
829 }
830 }
831
832 return IMG_TRUE;
833}
834#endif
835
836LinuxMemArea *NewExternalKVLinuxMemArea(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPUVAddr, IMG_UINT32 ui32Bytes, IMG_BOOL bPhysContig, IMG_UINT32 ui32AreaFlags)
837{
838 LinuxMemArea *psLinuxMemArea;
839
840 psLinuxMemArea = LinuxMemAreaStructAlloc();
841 if(!psLinuxMemArea)
842 {
843 return NULL;
844 }
845
846 psLinuxMemArea->eAreaType = LINUX_MEM_AREA_EXTERNAL_KV;
847 psLinuxMemArea->uData.sExternalKV.pvExternalKV = pvCPUVAddr;
848 psLinuxMemArea->uData.sExternalKV.bPhysContig =
849#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
850 (bPhysContig || TreatExternalPagesAsContiguous(pBasePAddr, ui32Bytes, bPhysContig))
851 ? IMG_TRUE : IMG_FALSE;
852#else
853 bPhysContig;
854#endif
855 if (psLinuxMemArea->uData.sExternalKV.bPhysContig)
856 {
857 psLinuxMemArea->uData.sExternalKV.uPhysAddr.SysPhysAddr = *pBasePAddr;
858 }
859 else
860 {
861 psLinuxMemArea->uData.sExternalKV.uPhysAddr.pSysPhysAddr = pBasePAddr;
862 }
863 psLinuxMemArea->ui32ByteSize = ui32Bytes;
864 psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
865 INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
866
867#if defined(DEBUG_LINUX_MEM_AREAS)
868 DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
869#endif
870
871 return psLinuxMemArea;
872}
873
874
875IMG_VOID
876FreeExternalKVLinuxMemArea(LinuxMemArea *psLinuxMemArea)
877{
878 PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_EXTERNAL_KV);
879
880#if defined(DEBUG_LINUX_MEM_AREAS)
881 DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
882#endif
883
884 LinuxMemAreaStructFree(psLinuxMemArea);
885}
886
887
888LinuxMemArea *
889NewIOLinuxMemArea(IMG_CPU_PHYADDR BasePAddr,
890 IMG_UINT32 ui32Bytes,
891 IMG_UINT32 ui32AreaFlags)
892{
893 LinuxMemArea *psLinuxMemArea = LinuxMemAreaStructAlloc();
894 if(!psLinuxMemArea)
895 {
896 return NULL;
897 }
898
899
900 psLinuxMemArea->eAreaType = LINUX_MEM_AREA_IO;
901 psLinuxMemArea->uData.sIO.CPUPhysAddr.uiAddr = BasePAddr.uiAddr;
902 psLinuxMemArea->ui32ByteSize = ui32Bytes;
903 psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
904 INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
905
906#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
907 DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_IO,
908 (IMG_VOID *)BasePAddr.uiAddr,
909 0,
910 BasePAddr.uiAddr,
911 NULL,
912 ui32Bytes,
913 "unknown",
914 0
915 );
916#endif
917
918#if defined(DEBUG_LINUX_MEM_AREAS)
919 DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
920#endif
921
922 return psLinuxMemArea;
923}
924
925
926IMG_VOID
927FreeIOLinuxMemArea(LinuxMemArea *psLinuxMemArea)
928{
929 PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_IO);
930
931#if defined(DEBUG_LINUX_MEM_AREAS)
932 DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
933#endif
934
935#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
936 DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IO,
937 (IMG_VOID *)psLinuxMemArea->uData.sIO.CPUPhysAddr.uiAddr, __FILE__, __LINE__);
938#endif
939
940
941
942 LinuxMemAreaStructFree(psLinuxMemArea);
943}
944
945
946LinuxMemArea *
947NewAllocPagesLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags)
948{
949 LinuxMemArea *psLinuxMemArea;
950 IMG_UINT32 ui32PageCount;
951 struct page **pvPageList;
952 IMG_HANDLE hBlockPageList;
953 IMG_INT32 i;
954 PVRSRV_ERROR eError;
955
956 psLinuxMemArea = LinuxMemAreaStructAlloc();
957 if(!psLinuxMemArea)
958 {
959 goto failed_area_alloc;
960 }
961
962 ui32PageCount = RANGE_TO_PAGES(ui32Bytes);
963 eError = OSAllocMem(0, sizeof(*pvPageList) * ui32PageCount, (IMG_VOID **)&pvPageList, &hBlockPageList,
964 "Array of pages");
965 if(eError != PVRSRV_OK)
966 {
967 goto failed_page_list_alloc;
968 }
969
970 for(i=0; i<(IMG_INT32)ui32PageCount; i++)
971 {
972 pvPageList[i] = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, 0);
973 if(!pvPageList[i])
974 {
975 goto failed_alloc_pages;
976 }
977#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
978
979#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
980 SetPageReserved(pvPageList[i]);
981#else
982 mem_map_reserve(pvPageList[i]);
983#endif
984#endif
985
986 }
987
988#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
989 DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES,
990 pvPageList,
991 0,
992 0,
993 NULL,
994 PAGE_ALIGN(ui32Bytes),
995 "unknown",
996 0
997 );
998#endif
999
1000 psLinuxMemArea->eAreaType = LINUX_MEM_AREA_ALLOC_PAGES;
1001 psLinuxMemArea->uData.sPageList.pvPageList = pvPageList;
1002 psLinuxMemArea->uData.sPageList.hBlockPageList = hBlockPageList;
1003 psLinuxMemArea->ui32ByteSize = ui32Bytes;
1004 psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
1005 INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
1006
1007
1008 if(ui32AreaFlags & (PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_UNCACHED))
1009 {
1010 psLinuxMemArea->bNeedsCacheInvalidate = IMG_TRUE;
1011 }
1012
1013#if defined(DEBUG_LINUX_MEM_AREAS)
1014 DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
1015#endif
1016
1017 return psLinuxMemArea;
1018
1019failed_alloc_pages:
1020 for(i--; i >= 0; i--)
1021 {
1022 __free_pages(pvPageList[i], 0);
1023 }
1024 (IMG_VOID) OSFreeMem(0, sizeof(*pvPageList) * ui32PageCount, pvPageList, hBlockPageList);
1025 psLinuxMemArea->uData.sPageList.pvPageList = IMG_NULL;
1026failed_page_list_alloc:
1027 LinuxMemAreaStructFree(psLinuxMemArea);
1028failed_area_alloc:
1029 PVR_DPF((PVR_DBG_ERROR, "%s: failed", __FUNCTION__));
1030
1031 return NULL;
1032}
1033
1034
1035IMG_VOID
1036FreeAllocPagesLinuxMemArea(LinuxMemArea *psLinuxMemArea)
1037{
1038 IMG_UINT32 ui32PageCount;
1039 struct page **pvPageList;
1040 IMG_HANDLE hBlockPageList;
1041 IMG_INT32 i;
1042
1043 PVR_ASSERT(psLinuxMemArea);
1044 PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_ALLOC_PAGES);
1045
1046#if defined(DEBUG_LINUX_MEM_AREAS)
1047 DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
1048#endif
1049
1050 ui32PageCount = RANGE_TO_PAGES(psLinuxMemArea->ui32ByteSize);
1051 pvPageList = psLinuxMemArea->uData.sPageList.pvPageList;
1052 hBlockPageList = psLinuxMemArea->uData.sPageList.hBlockPageList;
1053
1054#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
1055 DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, pvPageList, __FILE__, __LINE__);
1056#endif
1057
1058 for(i=0;i<(IMG_INT32)ui32PageCount;i++)
1059 {
1060#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
1061#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
1062 ClearPageReserved(pvPageList[i]);
1063#else
1064 mem_map_reserve(pvPageList[i]);
1065#endif
1066#endif
1067 __free_pages(pvPageList[i], 0);
1068 }
1069
1070 (IMG_VOID) OSFreeMem(0, sizeof(*pvPageList) * ui32PageCount, pvPageList, hBlockPageList);
1071 psLinuxMemArea->uData.sPageList.pvPageList = IMG_NULL;
1072
1073 LinuxMemAreaStructFree(psLinuxMemArea);
1074}
1075
1076
1077struct page*
1078LinuxMemAreaOffsetToPage(LinuxMemArea *psLinuxMemArea,
1079 IMG_UINT32 ui32ByteOffset)
1080{
1081 IMG_UINT32 ui32PageIndex;
1082 IMG_CHAR *pui8Addr;
1083
1084 switch(psLinuxMemArea->eAreaType)
1085 {
1086 case LINUX_MEM_AREA_ALLOC_PAGES:
1087 ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
1088 return psLinuxMemArea->uData.sPageList.pvPageList[ui32PageIndex];
1089
1090 case LINUX_MEM_AREA_VMALLOC:
1091 pui8Addr = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
1092 pui8Addr += ui32ByteOffset;
1093 return vmalloc_to_page(pui8Addr);
1094
1095 case LINUX_MEM_AREA_SUB_ALLOC:
1096
1097 return LinuxMemAreaOffsetToPage(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea,
1098 psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset
1099 + ui32ByteOffset);
1100 default:
1101 PVR_DPF((PVR_DBG_ERROR,
1102 "%s: Unsupported request for struct page from LinuxMemArea with type=%s",
1103 __FUNCTION__, LinuxMemAreaTypeToString(psLinuxMemArea->eAreaType)));
1104 return NULL;
1105 }
1106}
1107
1108
1109LinuxKMemCache *
1110KMemCacheCreateWrapper(IMG_CHAR *pszName,
1111 size_t Size,
1112 size_t Align,
1113 IMG_UINT32 ui32Flags)
1114{
1115#if defined(DEBUG_LINUX_SLAB_ALLOCATIONS)
1116 ui32Flags |= SLAB_POISON|SLAB_RED_ZONE;
1117#endif
1118 return kmem_cache_create(pszName, Size, Align, ui32Flags, NULL
1119#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
1120 , NULL
1121#endif
1122 );
1123}
1124
1125
1126IMG_VOID
1127KMemCacheDestroyWrapper(LinuxKMemCache *psCache)
1128{
1129 kmem_cache_destroy(psCache);
1130}
1131
1132
1133IMG_VOID *
1134_KMemCacheAllocWrapper(LinuxKMemCache *psCache,
1135#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14))
1136 gfp_t Flags,
1137#else
1138 IMG_INT Flags,
1139#endif
1140 IMG_CHAR *pszFileName,
1141 IMG_UINT32 ui32Line)
1142{
1143 IMG_VOID *pvRet;
1144
1145 pvRet = kmem_cache_zalloc(psCache, Flags);
1146
1147#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
1148 DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE,
1149 pvRet,
1150 pvRet,
1151 0,
1152 psCache,
1153 kmem_cache_size(psCache),
1154 pszFileName,
1155 ui32Line
1156 );
1157#else
1158 PVR_UNREFERENCED_PARAMETER(pszFileName);
1159 PVR_UNREFERENCED_PARAMETER(ui32Line);
1160#endif
1161
1162 return pvRet;
1163}
1164
1165
1166IMG_VOID
1167_KMemCacheFreeWrapper(LinuxKMemCache *psCache, IMG_VOID *pvObject, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
1168{
1169#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
1170 DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE, pvObject, pszFileName, ui32Line);
1171#else
1172 PVR_UNREFERENCED_PARAMETER(pszFileName);
1173 PVR_UNREFERENCED_PARAMETER(ui32Line);
1174#endif
1175
1176 kmem_cache_free(psCache, pvObject);
1177}
1178
1179
1180const IMG_CHAR *
1181KMemCacheNameWrapper(LinuxKMemCache *psCache)
1182{
1183 PVR_UNREFERENCED_PARAMETER(psCache);
1184
1185
1186 return "";
1187}
1188
1189
1190LinuxMemArea *
1191NewSubLinuxMemArea(LinuxMemArea *psParentLinuxMemArea,
1192 IMG_UINT32 ui32ByteOffset,
1193 IMG_UINT32 ui32Bytes)
1194{
1195 LinuxMemArea *psLinuxMemArea;
1196
1197 PVR_ASSERT((ui32ByteOffset+ui32Bytes) <= psParentLinuxMemArea->ui32ByteSize);
1198
1199 psLinuxMemArea = LinuxMemAreaStructAlloc();
1200 if(!psLinuxMemArea)
1201 {
1202 return NULL;
1203 }
1204
1205 psLinuxMemArea->eAreaType = LINUX_MEM_AREA_SUB_ALLOC;
1206 psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea = psParentLinuxMemArea;
1207 psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset = ui32ByteOffset;
1208 psLinuxMemArea->ui32ByteSize = ui32Bytes;
1209 psLinuxMemArea->ui32AreaFlags = psParentLinuxMemArea->ui32AreaFlags;
1210 psLinuxMemArea->bNeedsCacheInvalidate = psParentLinuxMemArea->bNeedsCacheInvalidate;
1211 INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
1212
1213#if defined(DEBUG_LINUX_MEM_AREAS)
1214 {
1215 DEBUG_LINUX_MEM_AREA_REC *psParentRecord;
1216 psParentRecord = DebugLinuxMemAreaRecordFind(psParentLinuxMemArea);
1217 DebugLinuxMemAreaRecordAdd(psLinuxMemArea, psParentRecord->ui32Flags);
1218 }
1219#endif
1220
1221 return psLinuxMemArea;
1222}
1223
1224
1225static IMG_VOID
1226FreeSubLinuxMemArea(LinuxMemArea *psLinuxMemArea)
1227{
1228 PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC);
1229
1230#if defined(DEBUG_LINUX_MEM_AREAS)
1231 DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
1232#endif
1233
1234
1235
1236 LinuxMemAreaStructFree(psLinuxMemArea);
1237}
1238
1239
1240static LinuxMemArea *
1241LinuxMemAreaStructAlloc(IMG_VOID)
1242{
1243#if 0
1244 LinuxMemArea *psLinuxMemArea;
1245 psLinuxMemArea = kmem_cache_alloc(psLinuxMemAreaCache, GFP_KERNEL);
1246 printk(KERN_ERR "%s: psLinuxMemArea=%p\n", __FUNCTION__, psLinuxMemArea);
1247 dump_stack();
1248 return psLinuxMemArea;
1249#else
1250 return KMemCacheAllocWrapper(psLinuxMemAreaCache, GFP_KERNEL);
1251#endif
1252}
1253
1254
1255static IMG_VOID
1256LinuxMemAreaStructFree(LinuxMemArea *psLinuxMemArea)
1257{
1258 KMemCacheFreeWrapper(psLinuxMemAreaCache, psLinuxMemArea);
1259
1260
1261}
1262
1263
1264IMG_VOID
1265LinuxMemAreaDeepFree(LinuxMemArea *psLinuxMemArea)
1266{
1267 switch(psLinuxMemArea->eAreaType)
1268 {
1269 case LINUX_MEM_AREA_VMALLOC:
1270 FreeVMallocLinuxMemArea(psLinuxMemArea);
1271 break;
1272 case LINUX_MEM_AREA_ALLOC_PAGES:
1273 FreeAllocPagesLinuxMemArea(psLinuxMemArea);
1274 break;
1275 case LINUX_MEM_AREA_IOREMAP:
1276 FreeIORemapLinuxMemArea(psLinuxMemArea);
1277 break;
1278 case LINUX_MEM_AREA_EXTERNAL_KV:
1279 FreeExternalKVLinuxMemArea(psLinuxMemArea);
1280 break;
1281 case LINUX_MEM_AREA_IO:
1282 FreeIOLinuxMemArea(psLinuxMemArea);
1283 break;
1284 case LINUX_MEM_AREA_SUB_ALLOC:
1285 FreeSubLinuxMemArea(psLinuxMemArea);
1286 break;
1287 default:
1288 PVR_DPF((PVR_DBG_ERROR, "%s: Unknown are type (%d)\n",
1289 __FUNCTION__, psLinuxMemArea->eAreaType));
1290 break;
1291 }
1292}
1293
1294
1295#if defined(DEBUG_LINUX_MEM_AREAS)
1296static IMG_VOID
1297DebugLinuxMemAreaRecordAdd(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Flags)
1298{
1299 DEBUG_LINUX_MEM_AREA_REC *psNewRecord;
1300 const IMG_CHAR *pi8FlagsString;
1301
1302 LinuxLockMutex(&g_sDebugMutex);
1303
1304 if(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
1305 {
1306 g_LinuxMemAreaWaterMark += psLinuxMemArea->ui32ByteSize;
1307 if(g_LinuxMemAreaWaterMark > g_LinuxMemAreaHighWaterMark)
1308 {
1309 g_LinuxMemAreaHighWaterMark = g_LinuxMemAreaWaterMark;
1310 }
1311 }
1312 g_LinuxMemAreaCount++;
1313
1314
1315 psNewRecord = kmalloc(sizeof(DEBUG_LINUX_MEM_AREA_REC), GFP_KERNEL);
1316 if(psNewRecord)
1317 {
1318
1319 psNewRecord->psLinuxMemArea = psLinuxMemArea;
1320 psNewRecord->ui32Flags = ui32Flags;
1321 psNewRecord->pid = current->pid;
1322
1323 List_DEBUG_LINUX_MEM_AREA_REC_Insert(&g_LinuxMemAreaRecords, psNewRecord);
1324 }
1325 else
1326 {
1327 PVR_DPF((PVR_DBG_ERROR,
1328 "%s: failed to allocate linux memory area record.",
1329 __FUNCTION__));
1330 }
1331
1332
1333 pi8FlagsString = HAPFlagsToString(ui32Flags);
1334 if(strstr(pi8FlagsString, "UNKNOWN"))
1335 {
1336 PVR_DPF((PVR_DBG_ERROR,
1337 "%s: Unexpected flags (0x%08x) associated with psLinuxMemArea @ %p",
1338 __FUNCTION__,
1339 ui32Flags,
1340 psLinuxMemArea));
1341
1342 }
1343
1344 LinuxUnLockMutex(&g_sDebugMutex);
1345}
1346
1347
1348
1349static IMG_VOID* MatchLinuxMemArea_AnyVaCb(DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord,
1350 va_list va)
1351{
1352 LinuxMemArea *psLinuxMemArea;
1353
1354 psLinuxMemArea = va_arg(va, LinuxMemArea*);
1355 if(psCurrentRecord->psLinuxMemArea == psLinuxMemArea)
1356 {
1357 return psCurrentRecord;
1358 }
1359 else
1360 {
1361 return IMG_NULL;
1362 }
1363}
1364
1365
1366static DEBUG_LINUX_MEM_AREA_REC *
1367DebugLinuxMemAreaRecordFind(LinuxMemArea *psLinuxMemArea)
1368{
1369 DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord;
1370
1371 LinuxLockMutex(&g_sDebugMutex);
1372 psCurrentRecord = List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
1373 MatchLinuxMemArea_AnyVaCb,
1374 psLinuxMemArea);
1375
1376 LinuxUnLockMutex(&g_sDebugMutex);
1377
1378 return psCurrentRecord;
1379}
1380
1381
1382static IMG_VOID
1383DebugLinuxMemAreaRecordRemove(LinuxMemArea *psLinuxMemArea)
1384{
1385 DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord;
1386
1387 LinuxLockMutex(&g_sDebugMutex);
1388
1389 if(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
1390 {
1391 g_LinuxMemAreaWaterMark -= psLinuxMemArea->ui32ByteSize;
1392 }
1393 g_LinuxMemAreaCount--;
1394
1395
1396 psCurrentRecord = List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
1397 MatchLinuxMemArea_AnyVaCb,
1398 psLinuxMemArea);
1399 if(psCurrentRecord)
1400 {
1401
1402 List_DEBUG_LINUX_MEM_AREA_REC_Remove(psCurrentRecord);
1403 kfree(psCurrentRecord);
1404 }
1405 else
1406 {
1407 PVR_DPF((PVR_DBG_ERROR, "%s: couldn't find an entry for psLinuxMemArea=%p\n",
1408 __FUNCTION__, psLinuxMemArea));
1409 }
1410
1411 LinuxUnLockMutex(&g_sDebugMutex);
1412}
1413#endif
1414
1415
1416IMG_VOID *
1417LinuxMemAreaToCpuVAddr(LinuxMemArea *psLinuxMemArea)
1418{
1419 switch(psLinuxMemArea->eAreaType)
1420 {
1421 case LINUX_MEM_AREA_VMALLOC:
1422 return psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
1423 case LINUX_MEM_AREA_IOREMAP:
1424 return psLinuxMemArea->uData.sIORemap.pvIORemapCookie;
1425 case LINUX_MEM_AREA_EXTERNAL_KV:
1426 return psLinuxMemArea->uData.sExternalKV.pvExternalKV;
1427 case LINUX_MEM_AREA_SUB_ALLOC:
1428 {
1429 IMG_CHAR *pAddr =
1430 LinuxMemAreaToCpuVAddr(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea);
1431 if(!pAddr)
1432 {
1433 return NULL;
1434 }
1435 return pAddr + psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset;
1436 }
1437 default:
1438 return NULL;
1439 }
1440}
1441
1442
1443IMG_CPU_PHYADDR
1444LinuxMemAreaToCpuPAddr(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset)
1445{
1446 IMG_CPU_PHYADDR CpuPAddr;
1447
1448 CpuPAddr.uiAddr = 0;
1449
1450 switch(psLinuxMemArea->eAreaType)
1451 {
1452 case LINUX_MEM_AREA_IOREMAP:
1453 {
1454 CpuPAddr = psLinuxMemArea->uData.sIORemap.CPUPhysAddr;
1455 CpuPAddr.uiAddr += ui32ByteOffset;
1456 break;
1457 }
1458 case LINUX_MEM_AREA_EXTERNAL_KV:
1459 {
1460 if (psLinuxMemArea->uData.sExternalKV.bPhysContig)
1461 {
1462 CpuPAddr = SysSysPAddrToCpuPAddr(psLinuxMemArea->uData.sExternalKV.uPhysAddr.SysPhysAddr);
1463 CpuPAddr.uiAddr += ui32ByteOffset;
1464 }
1465 else
1466 {
1467 IMG_UINT32 ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
1468 IMG_SYS_PHYADDR SysPAddr = psLinuxMemArea->uData.sExternalKV.uPhysAddr.pSysPhysAddr[ui32PageIndex];
1469
1470 CpuPAddr = SysSysPAddrToCpuPAddr(SysPAddr);
1471 CpuPAddr.uiAddr += ADDR_TO_PAGE_OFFSET(ui32ByteOffset);
1472 }
1473 break;
1474 }
1475 case LINUX_MEM_AREA_IO:
1476 {
1477 CpuPAddr = psLinuxMemArea->uData.sIO.CPUPhysAddr;
1478 CpuPAddr.uiAddr += ui32ByteOffset;
1479 break;
1480 }
1481 case LINUX_MEM_AREA_VMALLOC:
1482 {
1483 IMG_CHAR *pCpuVAddr;
1484 pCpuVAddr =
1485 (IMG_CHAR *)psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
1486 pCpuVAddr += ui32ByteOffset;
1487 CpuPAddr.uiAddr = VMallocToPhys(pCpuVAddr);
1488 break;
1489 }
1490 case LINUX_MEM_AREA_ALLOC_PAGES:
1491 {
1492 struct page *page;
1493 IMG_UINT32 ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
1494 page = psLinuxMemArea->uData.sPageList.pvPageList[ui32PageIndex];
1495 CpuPAddr.uiAddr = page_to_phys(page);
1496 CpuPAddr.uiAddr += ADDR_TO_PAGE_OFFSET(ui32ByteOffset);
1497 break;
1498 }
1499 case LINUX_MEM_AREA_SUB_ALLOC:
1500 {
1501 CpuPAddr =
1502 OSMemHandleToCpuPAddr(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea,
1503 psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset
1504 + ui32ByteOffset);
1505 break;
1506 }
1507 default:
1508 {
1509 PVR_DPF((PVR_DBG_ERROR, "%s: Unknown LinuxMemArea type (%d)\n",
1510 __FUNCTION__, psLinuxMemArea->eAreaType));
1511 PVR_ASSERT(CpuPAddr.uiAddr);
1512 break;
1513 }
1514 }
1515
1516 return CpuPAddr;
1517}
1518
1519
1520IMG_BOOL
1521LinuxMemAreaPhysIsContig(LinuxMemArea *psLinuxMemArea)
1522{
1523 switch(psLinuxMemArea->eAreaType)
1524 {
1525 case LINUX_MEM_AREA_IOREMAP:
1526 case LINUX_MEM_AREA_IO:
1527 return IMG_TRUE;
1528
1529 case LINUX_MEM_AREA_EXTERNAL_KV:
1530 return psLinuxMemArea->uData.sExternalKV.bPhysContig;
1531
1532 case LINUX_MEM_AREA_VMALLOC:
1533 case LINUX_MEM_AREA_ALLOC_PAGES:
1534 return IMG_FALSE;
1535
1536 case LINUX_MEM_AREA_SUB_ALLOC:
1537
1538 return LinuxMemAreaPhysIsContig(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea);
1539
1540 default:
1541 PVR_DPF((PVR_DBG_ERROR, "%s: Unknown LinuxMemArea type (%d)\n",
1542 __FUNCTION__, psLinuxMemArea->eAreaType));
1543 break;
1544 }
1545 return IMG_FALSE;
1546}
1547
1548
1549const IMG_CHAR *
1550LinuxMemAreaTypeToString(LINUX_MEM_AREA_TYPE eMemAreaType)
1551{
1552
1553 switch(eMemAreaType)
1554 {
1555 case LINUX_MEM_AREA_IOREMAP:
1556 return "LINUX_MEM_AREA_IOREMAP";
1557 case LINUX_MEM_AREA_EXTERNAL_KV:
1558 return "LINUX_MEM_AREA_EXTERNAL_KV";
1559 case LINUX_MEM_AREA_IO:
1560 return "LINUX_MEM_AREA_IO";
1561 case LINUX_MEM_AREA_VMALLOC:
1562 return "LINUX_MEM_AREA_VMALLOC";
1563 case LINUX_MEM_AREA_SUB_ALLOC:
1564 return "LINUX_MEM_AREA_SUB_ALLOC";
1565 case LINUX_MEM_AREA_ALLOC_PAGES:
1566 return "LINUX_MEM_AREA_ALLOC_PAGES";
1567 default:
1568 PVR_ASSERT(0);
1569 }
1570
1571 return "";
1572}
1573
1574
1575#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
1576static void ProcSeqStartstopDebugMutex(struct seq_file *sfile, IMG_BOOL start)
1577{
1578 if(start)
1579 {
1580 LinuxLockMutex(&g_sDebugMutex);
1581 }
1582 else
1583 {
1584 LinuxUnLockMutex(&g_sDebugMutex);
1585 }
1586}
1587#endif
1588
1589#if defined(DEBUG_LINUX_MEM_AREAS)
1590
1591static IMG_VOID* DecOffMemAreaRec_AnyVaCb(DEBUG_LINUX_MEM_AREA_REC *psNode, va_list va)
1592{
1593 off_t *pOff = va_arg(va, off_t*);
1594 if (--(*pOff))
1595 {
1596 return IMG_NULL;
1597 }
1598 else
1599 {
1600 return psNode;
1601 }
1602}
1603
1604
1605static void* ProcSeqNextMemArea(struct seq_file *sfile,void* el,loff_t off)
1606{
1607 DEBUG_LINUX_MEM_AREA_REC *psRecord;
1608 psRecord = (DEBUG_LINUX_MEM_AREA_REC*)
1609 List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
1610 DecOffMemAreaRec_AnyVaCb,
1611 &off);
1612 return (void*)psRecord;
1613}
1614
1615static void* ProcSeqOff2ElementMemArea(struct seq_file * sfile, loff_t off)
1616{
1617 DEBUG_LINUX_MEM_AREA_REC *psRecord;
1618 if(!off)
1619 {
1620 return PVR_PROC_SEQ_START_TOKEN;
1621 }
1622
1623 psRecord = (DEBUG_LINUX_MEM_AREA_REC*)
1624 List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
1625 DecOffMemAreaRec_AnyVaCb,
1626 &off);
1627 return (void*)psRecord;
1628}
1629
1630
1631static void ProcSeqShowMemArea(struct seq_file *sfile,void* el)
1632{
1633 DEBUG_LINUX_MEM_AREA_REC *psRecord = (DEBUG_LINUX_MEM_AREA_REC*)el;
1634 if(el == PVR_PROC_SEQ_START_TOKEN)
1635 {
1636
1637#if !defined(DEBUG_LINUX_XML_PROC_FILES)
1638 seq_printf( sfile,
1639 "Number of Linux Memory Areas: %u\n"
1640 "At the current water mark these areas correspond to %u bytes (excluding SUB areas)\n"
1641 "At the highest water mark these areas corresponded to %u bytes (excluding SUB areas)\n"
1642 "\nDetails for all Linux Memory Areas:\n"
1643 "%s %-24s %s %s %-8s %-5s %s\n",
1644 g_LinuxMemAreaCount,
1645 g_LinuxMemAreaWaterMark,
1646 g_LinuxMemAreaHighWaterMark,
1647 "psLinuxMemArea",
1648 "LinuxMemType",
1649 "CpuVAddr",
1650 "CpuPAddr",
1651 "Bytes",
1652 "Pid",
1653 "Flags"
1654 );
1655#else
1656 seq_printf( sfile,
1657 "<mem_areas_header>\n"
1658 "\t<count>%u</count>\n"
1659 "\t<watermark key=\"mar0\" description=\"current\" bytes=\"%u\"/>\n"
1660 "\t<watermark key=\"mar1\" description=\"high\" bytes=\"%u\"/>\n"
1661 "</mem_areas_header>\n",
1662 g_LinuxMemAreaCount,
1663 g_LinuxMemAreaWaterMark,
1664 g_LinuxMemAreaHighWaterMark
1665 );
1666#endif
1667 return;
1668 }
1669
1670 seq_printf( sfile,
1671#if !defined(DEBUG_LINUX_XML_PROC_FILES)
1672 "%8p %-24s %8p %08x %-8d %-5u %08x=(%s)\n",
1673#else
1674 "<linux_mem_area>\n"
1675 "\t<pointer>%8p</pointer>\n"
1676 "\t<type>%s</type>\n"
1677 "\t<cpu_virtual>%8p</cpu_virtual>\n"
1678 "\t<cpu_physical>%08x</cpu_physical>\n"
1679 "\t<bytes>%ld</bytes>\n"
1680 "\t<pid>%u</pid>\n"
1681 "\t<flags>%08lx</flags>\n"
1682 "\t<flags_string>%s</flags_string>\n"
1683 "</linux_mem_area>\n",
1684#endif
1685 psRecord->psLinuxMemArea,
1686 LinuxMemAreaTypeToString(psRecord->psLinuxMemArea->eAreaType),
1687 LinuxMemAreaToCpuVAddr(psRecord->psLinuxMemArea),
1688 LinuxMemAreaToCpuPAddr(psRecord->psLinuxMemArea,0).uiAddr,
1689 psRecord->psLinuxMemArea->ui32ByteSize,
1690 psRecord->pid,
1691 psRecord->ui32Flags,
1692 HAPFlagsToString(psRecord->ui32Flags)
1693 );
1694
1695}
1696
1697#endif
1698
1699
1700#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
1701
1702static IMG_VOID* DecOffMemAllocRec_AnyVaCb(DEBUG_MEM_ALLOC_REC *psNode, va_list va)
1703{
1704 off_t *pOff = va_arg(va, off_t*);
1705 if (--(*pOff))
1706 {
1707 return IMG_NULL;
1708 }
1709 else
1710 {
1711 return psNode;
1712 }
1713}
1714
1715
1716
1717static void* ProcSeqNextMemoryRecords(struct seq_file *sfile,void* el,loff_t off)
1718{
1719 DEBUG_MEM_ALLOC_REC *psRecord;
1720 psRecord = (DEBUG_MEM_ALLOC_REC*)
1721 List_DEBUG_MEM_ALLOC_REC_Any_va(g_MemoryRecords,
1722 DecOffMemAllocRec_AnyVaCb,
1723 &off);
1724#if defined(DEBUG_LINUX_XML_PROC_FILES)
1725 if(!psRecord)
1726 {
1727 seq_printf( sfile, "</meminfo>\n");
1728 }
1729#endif
1730
1731 return (void*)psRecord;
1732}
1733
1734static void* ProcSeqOff2ElementMemoryRecords(struct seq_file *sfile, loff_t off)
1735{
1736 DEBUG_MEM_ALLOC_REC *psRecord;
1737 if(!off)
1738 {
1739 return PVR_PROC_SEQ_START_TOKEN;
1740 }
1741
1742 psRecord = (DEBUG_MEM_ALLOC_REC*)
1743 List_DEBUG_MEM_ALLOC_REC_Any_va(g_MemoryRecords,
1744 DecOffMemAllocRec_AnyVaCb,
1745 &off);
1746
1747#if defined(DEBUG_LINUX_XML_PROC_FILES)
1748 if(!psRecord)
1749 {
1750 seq_printf( sfile, "</meminfo>\n");
1751 }
1752#endif
1753
1754 return (void*)psRecord;
1755}
1756
1757static void ProcSeqShowMemoryRecords(struct seq_file *sfile,void* el)
1758{
1759 DEBUG_MEM_ALLOC_REC *psRecord = (DEBUG_MEM_ALLOC_REC*)el;
1760 if(el == PVR_PROC_SEQ_START_TOKEN)
1761 {
1762#if !defined(DEBUG_LINUX_XML_PROC_FILES)
1763
1764 seq_printf( sfile, "%-60s: %d bytes\n",
1765 "Current Water Mark of bytes allocated via kmalloc",
1766 g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
1767 seq_printf( sfile, "%-60s: %d bytes\n",
1768 "Highest Water Mark of bytes allocated via kmalloc",
1769 g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
1770 seq_printf( sfile, "%-60s: %d bytes\n",
1771 "Current Water Mark of bytes allocated via vmalloc",
1772 g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
1773 seq_printf( sfile, "%-60s: %d bytes\n",
1774 "Highest Water Mark of bytes allocated via vmalloc",
1775 g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
1776 seq_printf( sfile, "%-60s: %d bytes\n",
1777 "Current Water Mark of bytes allocated via alloc_pages",
1778 g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
1779 seq_printf( sfile, "%-60s: %d bytes\n",
1780 "Highest Water Mark of bytes allocated via alloc_pages",
1781 g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
1782 seq_printf( sfile, "%-60s: %d bytes\n",
1783 "Current Water Mark of bytes allocated via ioremap",
1784 g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
1785 seq_printf( sfile, "%-60s: %d bytes\n",
1786 "Highest Water Mark of bytes allocated via ioremap",
1787 g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
1788 seq_printf( sfile, "%-60s: %d bytes\n",
1789 "Current Water Mark of bytes reserved for \"IO\" memory areas",
1790 g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
1791 seq_printf( sfile, "%-60s: %d bytes\n",
1792 "Highest Water Mark of bytes allocated for \"IO\" memory areas",
1793 g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
1794 seq_printf( sfile, "%-60s: %d bytes\n",
1795 "Current Water Mark of bytes allocated via kmem_cache_alloc",
1796 g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
1797 seq_printf( sfile, "%-60s: %d bytes\n",
1798 "Highest Water Mark of bytes allocated via kmem_cache_alloc",
1799 g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
1800 seq_printf( sfile, "\n");
1801
1802 seq_printf( sfile, "%-60s: %d bytes\n",
1803 "The Current Water Mark for memory allocated from system RAM",
1804 g_SysRAMWaterMark);
1805 seq_printf( sfile, "%-60s: %d bytes\n",
1806 "The Highest Water Mark for memory allocated from system RAM",
1807 g_SysRAMHighWaterMark);
1808 seq_printf( sfile, "%-60s: %d bytes\n",
1809 "The Current Water Mark for memory allocated from IO memory",
1810 g_IOMemWaterMark);
1811 seq_printf( sfile, "%-60s: %d bytes\n",
1812 "The Highest Water Mark for memory allocated from IO memory",
1813 g_IOMemHighWaterMark);
1814
1815 seq_printf( sfile, "\n");
1816
1817 seq_printf( sfile, "Details for all known allocations:\n"
1818 "%-16s %-8s %-8s %-10s %-5s %-10s %s\n",
1819 "Type",
1820 "CpuVAddr",
1821 "CpuPAddr",
1822 "Bytes",
1823 "PID",
1824 "PrivateData",
1825 "Filename:Line");
1826
1827#else
1828
1829
1830 seq_printf( sfile, "<meminfo>\n<meminfo_header>\n");
1831 seq_printf( sfile,
1832 "<watermark key=\"mr0\" description=\"kmalloc_current\" bytes=\"%d\"/>\n",
1833 g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
1834 seq_printf( sfile,
1835 "<watermark key=\"mr1\" description=\"kmalloc_high\" bytes=\"%d\"/>\n",
1836 g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
1837 seq_printf( sfile,
1838 "<watermark key=\"mr2\" description=\"vmalloc_current\" bytes=\"%d\"/>\n",
1839 g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
1840 seq_printf( sfile,
1841 "<watermark key=\"mr3\" description=\"vmalloc_high\" bytes=\"%d\"/>\n",
1842 g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
1843 seq_printf( sfile,
1844 "<watermark key=\"mr4\" description=\"alloc_pages_current\" bytes=\"%d\"/>\n",
1845 g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
1846 seq_printf( sfile,
1847 "<watermark key=\"mr5\" description=\"alloc_pages_high\" bytes=\"%d\"/>\n",
1848 g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
1849 seq_printf( sfile,
1850 "<watermark key=\"mr6\" description=\"ioremap_current\" bytes=\"%d\"/>\n",
1851 g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
1852 seq_printf( sfile,
1853 "<watermark key=\"mr7\" description=\"ioremap_high\" bytes=\"%d\"/>\n",
1854 g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
1855 seq_printf( sfile,
1856 "<watermark key=\"mr8\" description=\"io_current\" bytes=\"%d\"/>\n",
1857 g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
1858 seq_printf( sfile,
1859 "<watermark key=\"mr9\" description=\"io_high\" bytes=\"%d\"/>\n",
1860 g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
1861 seq_printf( sfile,
1862 "<watermark key=\"mr10\" description=\"kmem_cache_current\" bytes=\"%d\"/>\n",
1863 g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
1864 seq_printf( sfile,
1865 "<watermark key=\"mr11\" description=\"kmem_cache_high\" bytes=\"%d\"/>\n",
1866 g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
1867 seq_printf( sfile,"\n" );
1868
1869 seq_printf( sfile,
1870 "<watermark key=\"mr14\" description=\"system_ram_current\" bytes=\"%d\"/>\n",
1871 g_SysRAMWaterMark);
1872 seq_printf( sfile,
1873 "<watermark key=\"mr15\" description=\"system_ram_high\" bytes=\"%d\"/>\n",
1874 g_SysRAMHighWaterMark);
1875 seq_printf( sfile,
1876 "<watermark key=\"mr16\" description=\"system_io_current\" bytes=\"%d\"/>\n",
1877 g_IOMemWaterMark);
1878 seq_printf( sfile,
1879 "<watermark key=\"mr17\" description=\"system_io_high\" bytes=\"%d\"/>\n",
1880 g_IOMemHighWaterMark);
1881
1882 seq_printf( sfile, "</meminfo_header>\n");
1883
1884#endif
1885 return;
1886 }
1887
1888 if(psRecord->eAllocType != DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
1889 {
1890 seq_printf( sfile,
1891#if !defined(DEBUG_LINUX_XML_PROC_FILES)
1892 "%-16s %-8p %08x %-10d %-5d %-10s %s:%d\n",
1893#else
1894 "<allocation>\n"
1895 "\t<type>%s</type>\n"
1896 "\t<cpu_virtual>%-8p</cpu_virtual>\n"
1897 "\t<cpu_physical>%08x</cpu_physical>\n"
1898 "\t<bytes>%d</bytes>\n"
1899 "\t<pid>%d</pid>\n"
1900 "\t<private>%s</private>\n"
1901 "\t<filename>%s</filename>\n"
1902 "\t<line>%d</line>\n"
1903 "</allocation>\n",
1904#endif
1905 DebugMemAllocRecordTypeToString(psRecord->eAllocType),
1906 psRecord->pvCpuVAddr,
1907 psRecord->ulCpuPAddr,
1908 psRecord->ui32Bytes,
1909 psRecord->pid,
1910 "NULL",
1911 psRecord->pszFileName,
1912 psRecord->ui32Line);
1913 }
1914 else
1915 {
1916 seq_printf( sfile,
1917#if !defined(DEBUG_LINUX_XML_PROC_FILES)
1918 "%-16s %-8p %08x %-10d %-5d %-10s %s:%d\n",
1919#else
1920 "<allocation>\n"
1921 "\t<type>%s</type>\n"
1922 "\t<cpu_virtual>%-8p</cpu_virtual>\n"
1923 "\t<cpu_physical>%08x</cpu_physical>\n"
1924 "\t<bytes>%d</bytes>\n"
1925 "\t<pid>%d</pid>\n"
1926 "\t<private>%s</private>\n"
1927 "\t<filename>%s</filename>\n"
1928 "\t<line>%d</line>\n"
1929 "</allocation>\n",
1930#endif
1931 DebugMemAllocRecordTypeToString(psRecord->eAllocType),
1932 psRecord->pvCpuVAddr,
1933 psRecord->ulCpuPAddr,
1934 psRecord->ui32Bytes,
1935 psRecord->pid,
1936 KMemCacheNameWrapper(psRecord->pvPrivateData),
1937 psRecord->pszFileName,
1938 psRecord->ui32Line);
1939 }
1940}
1941
1942#endif
1943
1944
1945#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MMAP_AREAS)
1946const IMG_CHAR *
1947HAPFlagsToString(IMG_UINT32 ui32Flags)
1948{
1949 static IMG_CHAR szFlags[50];
1950 IMG_INT32 i32Pos = 0;
1951 IMG_UINT32 ui32CacheTypeIndex, ui32MapTypeIndex;
1952 IMG_CHAR *apszCacheTypes[] = {
1953 "UNCACHED",
1954 "CACHED",
1955 "WRITECOMBINE",
1956 "UNKNOWN"
1957 };
1958 IMG_CHAR *apszMapType[] = {
1959 "KERNEL_ONLY",
1960 "SINGLE_PROCESS",
1961 "MULTI_PROCESS",
1962 "FROM_EXISTING_PROCESS",
1963 "NO_CPU_VIRTUAL",
1964 "UNKNOWN"
1965 };
1966
1967
1968 if(ui32Flags & PVRSRV_HAP_UNCACHED){
1969 ui32CacheTypeIndex=0;
1970 }else if(ui32Flags & PVRSRV_HAP_CACHED){
1971 ui32CacheTypeIndex=1;
1972 }else if(ui32Flags & PVRSRV_HAP_WRITECOMBINE){
1973 ui32CacheTypeIndex=2;
1974 }else{
1975 ui32CacheTypeIndex=3;
1976 PVR_DPF((PVR_DBG_ERROR, "%s: unknown cache type (%u)",
1977 __FUNCTION__, (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)));
1978 }
1979
1980
1981 if(ui32Flags & PVRSRV_HAP_KERNEL_ONLY){
1982 ui32MapTypeIndex = 0;
1983 }else if(ui32Flags & PVRSRV_HAP_SINGLE_PROCESS){
1984 ui32MapTypeIndex = 1;
1985 }else if(ui32Flags & PVRSRV_HAP_MULTI_PROCESS){
1986 ui32MapTypeIndex = 2;
1987 }else if(ui32Flags & PVRSRV_HAP_FROM_EXISTING_PROCESS){
1988 ui32MapTypeIndex = 3;
1989 }else if(ui32Flags & PVRSRV_HAP_NO_CPU_VIRTUAL){
1990 ui32MapTypeIndex = 4;
1991 }else{
1992 ui32MapTypeIndex = 5;
1993 PVR_DPF((PVR_DBG_ERROR, "%s: unknown map type (%u)",
1994 __FUNCTION__, (ui32Flags & PVRSRV_HAP_MAPTYPE_MASK)));
1995 }
1996
1997 i32Pos = sprintf(szFlags, "%s|", apszCacheTypes[ui32CacheTypeIndex]);
1998 if (i32Pos <= 0)
1999 {
2000 PVR_DPF((PVR_DBG_ERROR, "%s: sprintf for cache type %u failed (%d)",
2001 __FUNCTION__, ui32CacheTypeIndex, i32Pos));
2002 szFlags[0] = 0;
2003 }
2004 else
2005 {
2006 sprintf(szFlags + i32Pos, "%s", apszMapType[ui32MapTypeIndex]);
2007 }
2008
2009 return szFlags;
2010}
2011#endif
2012