RK3368 GPU version Rogue M 1.28
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / rogue_m / services / server / common / process_stats.c
1 /*************************************************************************/ /*!
2 @File
3 @Title          Process based statistics
4 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
5 @Description    Manages a collection of statistics based around a process
6                 and referenced via OS agnostic methods.
7 @License        Dual MIT/GPLv2
8
9 The contents of this file are subject to the MIT license as set out below.
10
11 Permission is hereby granted, free of charge, to any person obtaining a copy
12 of this software and associated documentation files (the "Software"), to deal
13 in the Software without restriction, including without limitation the rights
14 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 copies of the Software, and to permit persons to whom the Software is
16 furnished to do so, subject to the following conditions:
17
18 The above copyright notice and this permission notice shall be included in
19 all copies or substantial portions of the Software.
20
21 Alternatively, the contents of this file may be used under the terms of
22 the GNU General Public License Version 2 ("GPL") in which case the provisions
23 of GPL are applicable instead of those above.
24
25 If you wish to allow use of your version of this file only under the terms of
26 GPL, and not to allow others to use your version of this file under the terms
27 of the MIT license, indicate your decision by deleting the provisions above
28 and replace them with the notice and other provisions required by GPL as set
29 out in the file called "GPL-COPYING" included in this distribution. If you do
30 not delete the provisions above, a recipient may use your version of this file
31 under the terms of either the MIT license or GPL.
32
33 This License is also included in this distribution in the file called
34 "MIT-COPYING".
35
36 EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
37 PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
38 BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
39 PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
40 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
41 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
42 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
43 */ /**************************************************************************/
44
45 #include <stddef.h>
46
47 #include "img_defs.h"
48 #include "img_types.h"
49 #include "pvr_debug.h"
50 #include "lock.h"
51 #include "allocmem.h"
52 #include "osfunc.h"
53 #include "lists.h"
54 #include "process_stats.h"
55 #include "ri_server.h"
56 #include "hash.h"
57 #include "connection_server.h"
58 #include "pvrsrv.h"
59
60 #define DBGTIMEDIFF(T0, T1)  ((IMG_UINT64) ( (T0) <= (T1) ? (T1) - (T0): IMG_UINT64_MAX - (T0) + (T1) ))
61 #define MEAN_TIME(A, B)     ( ((3*(A))/4) + ((1 * (B))/4) )
62
63
64 /*
65  *  Maximum history of process statistics that will be kept.
66  */
67 #define MAX_DEAD_LIST_PROCESSES  (10)
68
69 void *pvOSPowerStatsEntryData=NULL;
70
71
72 /*
73  * Definition of all process based statistics and the strings used to
74  * format them.
75  */
76 typedef enum
77 {
78     /* Stats that are per process... */
79     PVRSRV_PROCESS_STAT_TYPE_CONNECTIONS,
80     PVRSRV_PROCESS_STAT_TYPE_MAX_CONNECTIONS,
81
82     PVRSRV_PROCESS_STAT_TYPE_RC_OOMS,
83     PVRSRV_PROCESS_STAT_TYPE_RC_PRS,
84     PVRSRV_PROCESS_STAT_TYPE_RC_GROWS,
85     PVRSRV_PROCESS_STAT_TYPE_RC_PUSH_GROWS,
86     PVRSRV_PROCESS_STAT_TYPE_RC_TA_STORES,
87     PVRSRV_PROCESS_STAT_TYPE_RC_3D_STORES,
88     PVRSRV_PROCESS_STAT_TYPE_RC_SH_STORES,
89     PVRSRV_PROCESS_STAT_TYPE_RC_CDM_STORES,
90     PVRSRV_PROCESS_STAT_TYPE_ZSBUFFER_REQS_BY_APP,
91     PVRSRV_PROCESS_STAT_TYPE_ZSBUFFER_REQS_BY_FW,
92     PVRSRV_PROCESS_STAT_TYPE_FREELIST_GROW_REQS_BY_APP,
93     PVRSRV_PROCESS_STAT_TYPE_FREELIST_GROW_REQS_BY_FW,
94     PVRSRV_PROCESS_STAT_TYPE_FREELIST_PAGES_INIT,
95     PVRSRV_PROCESS_STAT_TYPE_FREELIST_MAX_PAGES,
96     PVRSRV_PROCESS_STAT_TYPE_KMALLOC,
97     PVRSRV_PROCESS_STAT_TYPE_KMALLOC_MAX,
98     PVRSRV_PROCESS_STAT_TYPE_VMALLOC,
99     PVRSRV_PROCESS_STAT_TYPE_VMALLOC_MAX,
100     PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA,
101     PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA_MAX,
102     PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA,
103     PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA_MAX,
104     PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA,
105     PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA_MAX,
106     PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA,
107     PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA_MAX,
108     PVRSRV_PROCESS_STAT_TYPE_ALLOC_LMA_PAGES,
109     PVRSRV_PROCESS_STAT_TYPE_ALLOC_LMA_PAGES_MAX,
110     PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES,
111     PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES_MAX,
112     PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES,
113     PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES_MAX,
114
115     //zxl: count total data
116         PVRSRV_PROCESS_STAT_TYPE_TOTAL_ALLOC,
117         PVRSRV_PROCESS_STAT_TYPE_MAX_TOTAL_ALLOC,
118         PVRSRV_PROCESS_STAT_TYPE_TOTAL_MAP,
119         PVRSRV_PROCESS_STAT_TYPE_MAX_TOTAL_MAP,
120
121         /* Must be the last enum...*/
122         PVRSRV_PROCESS_STAT_TYPE_COUNT
123 } PVRSRV_PROCESS_STAT_TYPE;
124
125
126 typedef enum
127 {
128     PVRSRV_POWER_TIMING_STAT_FORCED_POWER_TRANSITION=0,
129     PVRSRV_POWER_TIMING_STAT_PRE_DEVICE,
130     PVRSRV_POWER_TIMING_STAT_PRE_SYSTEM,
131     PVRSRV_POWER_TIMING_STAT_POST_DEVICE,
132     PVRSRV_POWER_TIMING_STAT_POST_SYSTEM,
133     PVRSRV_POWER_TIMING_STAT_NEWLINE1,
134     PVRSRV_POWER_TIMING_STAT_NOT_FORCED_POWER_TRANSITION,
135     PVRSRV_POWER_TIMING_STAT_NON_PRE_DEVICE,
136     PVRSRV_POWER_TIMING_STAT_NON_PRE_SYSTEM,
137     PVRSRV_POWER_TIMING_STAT_NON_POST_DEVICE,
138     PVRSRV_POWER_TIMING_STAT_NON_POST_SYSTEM,
139     PVRSRV_POWER_TIMING_STAT_NEWLINE2,
140     PVRSRV_POWER_TIMING_STAT_FW_BOOTUP_TIME,
141     PVRSRV_POWER_TIMING_STAT_HOST_ACK
142 } PVR_SRV_OTHER_STAT_TYPE;
143
144
145 static IMG_CHAR*  pszProcessStatFmt[PVRSRV_PROCESS_STAT_TYPE_COUNT] = {
146         "Connections                       %10d\n", /* PVRSRV_STAT_TYPE_CONNECTIONS */
147         "ConnectionsMax                    %10d\n", /* PVRSRV_STAT_TYPE_MAXCONNECTIONS */
148
149     "RenderContextOutOfMemoryEvents    %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_RC_OOMS */
150     "RenderContextPartialRenders       %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_RC_PRS */
151     "RenderContextGrows                %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_RC_GROWS */
152     "RenderContextPushGrows            %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_RC_PUSH_GROWS */
153     "RenderContextTAStores             %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_RC_TA_STORES */
154     "RenderContext3DStores             %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_RC_3D_STORES */
155     "RenderContextSHStores             %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_RC_SH_STORES */
156     "RenderContextCDMStores            %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_RC_CDM_STORES */
157     "ZSBufferRequestsByApp             %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_ZSBUFFER_REQS_BY_APP */
158     "ZSBufferRequestsByFirmware        %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_ZSBUFFER_REQS_BY_FW */
159     "FreeListGrowRequestsByApp         %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_FREELIST_GROW_REQS_BY_APP */
160     "FreeListGrowRequestsByFirmware    %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_FREELIST_GROW_REQS_BY_FW */
161     "FreeListInitialPages              %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_FREELIST_PAGES_INIT */
162     "FreeListMaxPages                  %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_FREELIST_MAX_PAGES */
163     "MemoryUsageKMalloc                %10d\n", /* PVRSRV_STAT_TYPE_KMALLOC */
164     "MemoryUsageKMallocMax             %10d\n", /* PVRSRV_STAT_TYPE_MAX_KMALLOC */
165     "MemoryUsageVMalloc                %10d\n", /* PVRSRV_STAT_TYPE_VMALLOC */
166     "MemoryUsageVMallocMax             %10d\n", /* PVRSRV_STAT_TYPE_MAX_VMALLOC */
167     "MemoryUsageAllocPTMemoryUMA       %10d\n", /* PVRSRV_STAT_TYPE_ALLOC_PAGES_PT_UMA */
168     "MemoryUsageAllocPTMemoryUMAMax    %10d\n", /* PVRSRV_STAT_TYPE_MAX_ALLOC_PAGES_PT_UMA */
169     "MemoryUsageVMapPTUMA              %10d\n", /* PVRSRV_STAT_TYPE_VMAP_PT_UMA */
170     "MemoryUsageVMapPTUMAMax           %10d\n", /* PVRSRV_STAT_TYPE_MAX_VMAP_PT_UMA */
171     "MemoryUsageAllocPTMemoryLMA       %10d\n", /* PVRSRV_STAT_TYPE_ALLOC_PAGES_PT_LMA */
172     "MemoryUsageAllocPTMemoryLMAMax    %10d\n", /* PVRSRV_STAT_TYPE_MAX_ALLOC_PAGES_PT_LMA */
173     "MemoryUsageIORemapPTLMA           %10d\n", /* PVRSRV_STAT_TYPE_IOREMAP_PT_LMA */
174     "MemoryUsageIORemapPTLMAMax        %10d\n", /* PVRSRV_STAT_TYPE_MAX_IOREMAP_PT_LMA */
175     "MemoryUsageAllocGPUMemLMA         %10d\n", /* PVRSRV_STAT_TYPE_ALLOC_LMA_PAGES */
176     "MemoryUsageAllocGPUMemLMAMax      %10d\n", /* PVRSRV_STAT_TYPE_MAX_ALLOC_LMA_PAGES */
177     "MemoryUsageAllocGPUMemUMA         %10d\n", /* PVRSRV_STAT_TYPE_ALLOC_UMA_PAGES */
178     "MemoryUsageAllocGPUMemUMAMax      %10d\n", /* PVRSRV_STAT_TYPE_MAX_ALLOC_UMA_PAGES */
179     "MemoryUsageMappedGPUMemUMA/LMA    %10d\n", /* PVRSRV_STAT_TYPE_MAP_UMA_LMA_PAGES */
180     "MemoryUsageMappedGPUMemUMA/LMAMax %10d\n", /* PVRSRV_STAT_TYPE_MAX_MAP_UMA_LMA_PAGES */
181
182     //zxl: count total data
183     "MemoryUsageTotalAlloc             %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_TOTAL_ALLOC */
184     "MemoryUsageTotalAllocMax          %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_MAX_TOTAL_ALLOC */
185     "MemoryUsageTotalMap               %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_TOTAL_MAP */
186     "MemoryUsageTotalMapMax            %10d\n", /* PVRSRV_PROCESS_STAT_TYPE_MAX_TOTAL_MAP */
187 };
188
189
190 /*
191  *  Functions for printing the information stored...
192  */
193 IMG_VOID  ProcessStatsPrintElements(IMG_PVOID pvFilePtr, IMG_PVOID pvStatPtr,
194                                     OS_STATS_PRINTF_FUNC* pfnOSGetStatsPrintf);
195
196 IMG_VOID  MemStatsPrintElements(IMG_PVOID pvFilePtr, IMG_PVOID pvStatPtr,
197                                 OS_STATS_PRINTF_FUNC* pfnOSGetStatsPrintf);
198
199 IMG_VOID  RIMemStatsPrintElements(IMG_PVOID pvFilePtr, IMG_PVOID pvStatPtr,
200                                   OS_STATS_PRINTF_FUNC* pfnOSGetStatsPrintf);
201
202 IMG_VOID  PowerStatsPrintElements(IMG_PVOID pvFilePtr, IMG_PVOID pvStatPtr,
203                                   OS_STATS_PRINTF_FUNC* pfnOSGetStatsPrintf);
204
205 IMG_VOID  GlobalStatsPrintElements(IMG_PVOID pvFilePtr, IMG_PVOID pvStatPtr,
206                                                                    OS_STATS_PRINTF_FUNC* pfnOSGetStatsPrintf);
207
208
209
210 /*
211  *  Macros for updating stat values.
212  */
213 #define UPDATE_MAX_VALUE(a,b)                  do { if ((b) > (a)) {(a) = (b);} } while(0)
214 #define INCREASE_STAT_VALUE(ptr,var,val)       do { (ptr)->i32StatValue[(var)] += (val); if ((ptr)->i32StatValue[(var)] > (ptr)->i32StatValue[(var##_MAX)]) {(ptr)->i32StatValue[(var##_MAX)] = (ptr)->i32StatValue[(var)];} } while(0)
215 #define DECREASE_STAT_VALUE(ptr,var,val)       do { if ((IMG_SIZE_T)(ptr)->i32StatValue[(var)] >= (val)) { (ptr)->i32StatValue[(var)] -= (val); } else { (ptr)->i32StatValue[(var)] = 0; } } while(0)
216 #define INCREASE_GLOBAL_STAT_VALUE(var,val)    do { (var) += (val); if ((var) > (var##Max)) {(var##Max) = (var);} } while(0)
217 #define DECREASE_GLOBAL_STAT_VALUE(var,val)    do { if ((var) >= (val)) { (var) -= (val); } else { (var) = 0; } } while(0)
218
219
220 /*
221  * Structures for holding statistics...
222  */
223 typedef enum
224 {
225         PVRSRV_STAT_STRUCTURE_PROCESS = 1,
226         PVRSRV_STAT_STRUCTURE_RENDER_CONTEXT = 2,
227         PVRSRV_STAT_STRUCTURE_MEMORY = 3,
228         PVRSRV_STAT_STRUCTURE_RIMEMORY = 4
229 } PVRSRV_STAT_STRUCTURE_TYPE;
230
231 #define MAX_PROC_NAME_LENGTH   (32)
232
233 typedef struct _PVRSRV_PROCESS_STATS_ {
234         /* Structure type (must be first!) */
235         PVRSRV_STAT_STRUCTURE_TYPE        eStructureType;
236
237         /* Linked list pointers */
238         struct _PVRSRV_PROCESS_STATS_*    psNext;
239         struct _PVRSRV_PROCESS_STATS_*    psPrev;
240
241         /* OS level process ID */
242         IMG_PID                           pid;
243         IMG_UINT32                        ui32RefCount;
244         IMG_UINT32                        ui32MemRefCount;
245
246         /* Folder name used to store the statistic */
247         IMG_CHAR                                          szFolderName[MAX_PROC_NAME_LENGTH];
248
249         /* OS specific data */
250         IMG_PVOID                         pvOSPidFolderData;
251         IMG_PVOID                         pvOSPidEntryData;
252
253         /* Stats... */
254         IMG_INT32                         i32StatValue[PVRSRV_PROCESS_STAT_TYPE_COUNT];
255
256         /* Other statistics structures */
257         struct _PVRSRV_RENDER_STATS_*     psRenderLiveList;
258         struct _PVRSRV_RENDER_STATS_*     psRenderDeadList;
259
260         struct _PVRSRV_MEMORY_STATS_*     psMemoryStats;
261         struct _PVRSRV_RI_MEMORY_STATS_*  psRIMemoryStats;
262 } PVRSRV_PROCESS_STATS;
263
264 typedef struct _PVRSRV_RENDER_STATS_ {
265         /* Structure type (must be first!) */
266         PVRSRV_STAT_STRUCTURE_TYPE     eStructureType;
267
268         /* Linked list pointers */
269         struct _PVRSRV_RENDER_STATS_*  psNext;
270         struct _PVRSRV_RENDER_STATS_*  psPrev;
271
272         /* OS specific data */
273         IMG_PVOID                      pvOSData;
274
275         /* Stats... */
276         IMG_INT32                      i32StatValue[4];
277 } PVRSRV_RENDER_STATS;
278
279 typedef struct _PVRSRV_MEM_ALLOC_REC_
280 {
281     PVRSRV_MEM_ALLOC_TYPE  eAllocType;
282     IMG_UINT64                  ui64Key;
283     IMG_VOID               *pvCpuVAddr;
284     IMG_CPU_PHYADDR        sCpuPAddr;
285         IMG_SIZE_T                         uiBytes;
286     IMG_PVOID              pvPrivateData;
287
288     struct _PVRSRV_MEM_ALLOC_REC_  *psNext;
289         struct _PVRSRV_MEM_ALLOC_REC_  **ppsThis;
290 } PVRSRV_MEM_ALLOC_REC;
291
292 typedef struct _PVRSRV_MEMORY_STATS_ {
293         /* Structure type (must be first!) */
294         PVRSRV_STAT_STRUCTURE_TYPE  eStructureType;
295
296         /* OS specific data */
297         IMG_PVOID                   pvOSMemEntryData;
298
299         /* Stats... */
300         PVRSRV_MEM_ALLOC_REC        *psMemoryRecords;
301 } PVRSRV_MEMORY_STATS;
302
303 typedef struct _PVRSRV_RI_MEMORY_STATS_ {
304         /* Structure type (must be first!) */
305         PVRSRV_STAT_STRUCTURE_TYPE  eStructureType;
306
307         /* OS level process ID */
308         IMG_PID                         pid;
309
310         /* OS specific data */
311         IMG_PVOID                   pvOSRIMemEntryData;
312 } PVRSRV_RI_MEMORY_STATS;
313
314 #if defined(PVRSRV_ENABLE_MEMORY_STATS)
315 static IMPLEMENT_LIST_INSERT(PVRSRV_MEM_ALLOC_REC)
316 static IMPLEMENT_LIST_REMOVE(PVRSRV_MEM_ALLOC_REC)
317 #endif
318
319
320 /*
321  *  Global Boolean to flag when the statistics are ready to monitor
322  *  memory allocations.
323  */
324 static  IMG_BOOL  bProcessStatsInitialised = IMG_FALSE;
325
326 /*
327  * Linked lists for process stats. Live stats are for processes which are still running
328  * and the dead list holds those that have exited.
329  */
330 static PVRSRV_PROCESS_STATS*  psLiveList = IMG_NULL;
331 static PVRSRV_PROCESS_STATS*  psDeadList = IMG_NULL;
332
333 POS_LOCK  psLinkedListLock = IMG_NULL;
334
335
336 /*
337  * Pointer to OS folder to hold PID folders.
338  */
339 IMG_CHAR*  pszOSLivePidFolderName = "pid";
340 IMG_CHAR*  pszOSDeadPidFolderName = "pids_retired";
341 IMG_PVOID  pvOSLivePidFolder      = IMG_NULL;
342 IMG_PVOID  pvOSDeadPidFolder      = IMG_NULL;
343
344 /* global driver-data folders */
345 typedef struct _GLOBAL_STATS_
346 {
347         IMG_UINT32 ui32MemoryUsageKMalloc;
348         IMG_UINT32 ui32MemoryUsageKMallocMax;
349         IMG_UINT32 ui32MemoryUsageVMalloc;
350         IMG_UINT32 ui32MemoryUsageVMallocMax;
351         IMG_UINT32 ui32MemoryUsageAllocPTMemoryUMA;
352         IMG_UINT32 ui32MemoryUsageAllocPTMemoryUMAMax;
353         IMG_UINT32 ui32MemoryUsageVMapPTUMA;
354         IMG_UINT32 ui32MemoryUsageVMapPTUMAMax;
355         IMG_UINT32 ui32MemoryUsageAllocPTMemoryLMA;
356         IMG_UINT32 ui32MemoryUsageAllocPTMemoryLMAMax;
357         IMG_UINT32 ui32MemoryUsageIORemapPTLMA;
358         IMG_UINT32 ui32MemoryUsageIORemapPTLMAMax;
359         IMG_UINT32 ui32MemoryUsageAllocGPUMemLMA;
360         IMG_UINT32 ui32MemoryUsageAllocGPUMemLMAMax;
361         IMG_UINT32 ui32MemoryUsageAllocGPUMemUMA;
362         IMG_UINT32 ui32MemoryUsageAllocGPUMemUMAMax;
363         IMG_UINT32 ui32MemoryUsageAllocGPUMemUMAPool;
364         IMG_UINT32 ui32MemoryUsageAllocGPUMemUMAPoolMax;
365         IMG_UINT32 ui32MemoryUsageMappedGPUMemUMA_LMA;
366         IMG_UINT32 ui32MemoryUsageMappedGPUMemUMA_LMAMax;
367
368         //zxl: count total data
369         IMG_UINT32 ui32MemoryUsageTotalAlloc;
370         IMG_UINT32 ui32MemoryUsageTotalAllocMax;
371         IMG_UINT32 ui32MemoryUsageTotalMap;
372     IMG_UINT32 ui32MemoryUsageTotalMapMax;
373 } GLOBAL_STATS;
374
375 static IMG_PVOID  pvOSGlobalMemEntryRef = IMG_NULL;
376 static IMG_CHAR* const pszDriverStatFilename = "driver_stats";
377 static GLOBAL_STATS gsGlobalStats;
378
379 #define HASH_INITIAL_SIZE 5
380 /* A hash table used to store the size of any vmalloc'd allocation
381  * against its address (not needed for kmallocs as we can use ksize()) */
382 static HASH_TABLE* gpsVmallocSizeHashTable;
383 static POS_LOCK  gpsVmallocSizeHashTableLock;
384
385 /*Power Statistics List */
386
387 static IMG_UINT64 ui64TotalForcedEntries=0,ui64TotalNotForcedEntries=0;
388
389 static IMG_UINT64 ui64ForcedPreDevice=0, ui64ForcedPreSystem=0, ui64ForcedPostDevice=0, ui64ForcedPostSystem=0;
390 static IMG_UINT64 ui64NotForcedPreDevice=0, ui64NotForcedPreSystem=0, ui64NotForcedPostDevice=0, ui64NotForcedPostSystem=0;
391
392 static IMG_UINT32 _PVRSRVIncrMemStatRefCount(IMG_PVOID pvStatPtr);
393 static IMG_UINT32 _PVRSRVDecrMemStatRefCount(IMG_PVOID pvStatPtr);
394
395 IMG_VOID InsertPowerTimeStatistic(PVRSRV_POWER_ENTRY_TYPE bType,
396                 IMG_INT32 i32CurrentState, IMG_INT32 i32NextState,
397         IMG_UINT64 ui64SysStartTime, IMG_UINT64 ui64SysEndTime,
398                 IMG_UINT64 ui64DevStartTime, IMG_UINT64 ui64DevEndTime,
399                 IMG_BOOL bForced)
400 {
401     IMG_UINT64 ui64Device;
402     IMG_UINT64 ui64System;
403
404         if (i32CurrentState==i32NextState) return ;
405
406     ui64Device=ui64DevEndTime-ui64DevStartTime;
407     ui64System=ui64SysEndTime-ui64SysStartTime;
408
409     if (bForced)
410     {
411         ui64TotalForcedEntries++;
412         if (bType==PVRSRV_POWER_ENTRY_TYPE_POST)
413         {
414             ui64ForcedPostDevice+=ui64Device;
415             ui64ForcedPostSystem+=ui64System;
416         }
417         else
418         {
419             ui64ForcedPreDevice+=ui64Device;
420             ui64ForcedPreSystem+=ui64System;
421         }
422     }
423     else
424     {
425         ui64TotalNotForcedEntries++;
426         if (bType==PVRSRV_POWER_ENTRY_TYPE_POST)
427         {
428             ui64NotForcedPostDevice+=ui64Device;
429             ui64NotForcedPostSystem+=ui64System;
430         }
431         else
432         {
433             ui64NotForcedPreDevice+=ui64Device;
434             ui64NotForcedPreSystem+=ui64System;
435         }
436     }
437
438         return;
439 }
440
441 typedef struct _EXTRA_POWER_STATS_
442 {
443         IMG_UINT64      ui64PreClockSpeedChangeDuration;
444         IMG_UINT64      ui64BetweenPreEndingAndPostStartingDuration;
445         IMG_UINT64      ui64PostClockSpeedChangeDuration;
446 } EXTRA_POWER_STATS;
447
448 #define NUM_EXTRA_POWER_STATS   10
449
450 static EXTRA_POWER_STATS asClockSpeedChanges[NUM_EXTRA_POWER_STATS];
451 static IMG_UINT32       ui32ClockSpeedIndexStart = 0, ui32ClockSpeedIndexEnd = 0;
452
453 static IMG_UINT64 ui64PreClockSpeedChangeMark = 0;
454
455 IMG_VOID InsertPowerTimeStatisticExtraPre(IMG_UINT64 ui64StartTimer, IMG_UINT64 ui64Stoptimer)
456 {
457         asClockSpeedChanges[ui32ClockSpeedIndexEnd].ui64PreClockSpeedChangeDuration = ui64Stoptimer - ui64StartTimer;
458
459         ui64PreClockSpeedChangeMark = OSClockus();
460
461         return ;
462 }
463
464 IMG_VOID InsertPowerTimeStatisticExtraPost(IMG_UINT64 ui64StartTimer, IMG_UINT64 ui64StopTimer)
465 {
466         IMG_UINT64 ui64Duration = ui64StartTimer - ui64PreClockSpeedChangeMark;
467
468         PVR_ASSERT(ui64PreClockSpeedChangeMark > 0);
469
470         asClockSpeedChanges[ui32ClockSpeedIndexEnd].ui64BetweenPreEndingAndPostStartingDuration = ui64Duration;
471         asClockSpeedChanges[ui32ClockSpeedIndexEnd].ui64PostClockSpeedChangeDuration = ui64StopTimer - ui64StartTimer;
472
473         ui32ClockSpeedIndexEnd = (ui32ClockSpeedIndexEnd + 1) % NUM_EXTRA_POWER_STATS;
474
475         if (ui32ClockSpeedIndexEnd == ui32ClockSpeedIndexStart)
476         {
477                 ui32ClockSpeedIndexStart = (ui32ClockSpeedIndexStart + 1) % NUM_EXTRA_POWER_STATS;
478         }
479
480         ui64PreClockSpeedChangeMark = 0;
481
482         return;
483 }
484
485 /*************************************************************************/ /*!
486 @Function       _RemoveRenderStatsFromList
487 @Description    Detaches a process from either the live or dead list.
488 @Input          psProcessStats  Process to remove the stats from.
489 @Input          psRenderStats   Render stats to remove.
490 */ /**************************************************************************/
491 static IMG_VOID
492 _RemoveRenderStatsFromList(PVRSRV_PROCESS_STATS* psProcessStats,
493                            PVRSRV_RENDER_STATS* psRenderStats)
494 {
495         PVR_ASSERT(psProcessStats != IMG_NULL);
496         PVR_ASSERT(psRenderStats != IMG_NULL);
497
498         /* Remove the item from the linked lists... */
499         if (psProcessStats->psRenderLiveList == psRenderStats)
500         {
501                 psProcessStats->psRenderLiveList = psRenderStats->psNext;
502
503                 if (psProcessStats->psRenderLiveList != IMG_NULL)
504                 {
505                         psProcessStats->psRenderLiveList->psPrev = IMG_NULL;
506                 }
507         }
508         else if (psProcessStats->psRenderDeadList == psRenderStats)
509         {
510                 psProcessStats->psRenderDeadList = psRenderStats->psNext;
511
512                 if (psProcessStats->psRenderDeadList != IMG_NULL)
513                 {
514                         psProcessStats->psRenderDeadList->psPrev = IMG_NULL;
515                 }
516         }
517         else
518         {
519                 PVRSRV_RENDER_STATS*  psNext = psRenderStats->psNext;
520                 PVRSRV_RENDER_STATS*  psPrev = psRenderStats->psPrev;
521
522                 if (psRenderStats->psNext != IMG_NULL)
523                 {
524                         psRenderStats->psNext->psPrev = psPrev;
525                 }
526                 if (psRenderStats->psPrev != IMG_NULL)
527                 {
528                         psRenderStats->psPrev->psNext = psNext;
529                 }
530         }
531
532         /* Reset the pointers in this cell, as it is not attached to anything */
533         psRenderStats->psNext = IMG_NULL;
534         psRenderStats->psPrev = IMG_NULL;
535 } /* _RemoveRenderStatsFromList */
536
537
538 /*************************************************************************/ /*!
539 @Function       _DestoryRenderStat
540 @Description    Frees memory and resources held by a render statistic.
541 @Input          psRenderStats  Render stats to destroy.
542 */ /**************************************************************************/
543 static IMG_VOID
544 _DestoryRenderStat(PVRSRV_RENDER_STATS* psRenderStats)
545 {
546         PVR_ASSERT(psRenderStats != IMG_NULL);
547
548         /* Remove the statistic from the OS... */
549 //      OSRemoveStatisticEntry(psRenderStats->pvOSData);
550
551         /* Free the memory... */
552         OSFreeMem(psRenderStats);
553 } /* _DestoryRenderStat */
554
555
556 /*************************************************************************/ /*!
557 @Function       _FindProcessStatsInLiveList
558 @Description    Searches the Live Process List for a statistics structure that
559                 matches the PID given.
560 @Input          pid  Process to search for.
561 @Return         Pointer to stats structure for the process.
562 */ /**************************************************************************/
563 static PVRSRV_PROCESS_STATS*
564 _FindProcessStatsInLiveList(IMG_PID pid)
565 {
566         PVRSRV_PROCESS_STATS*  psProcessStats = psLiveList;
567
568         while (psProcessStats != IMG_NULL)
569         {
570                 if (psProcessStats->pid == pid)
571                 {
572                         return psProcessStats;
573                 }
574
575                 psProcessStats = psProcessStats->psNext;
576         }
577
578         return IMG_NULL;
579 } /* _FindProcessStatsInLiveList */
580
581
582 /*************************************************************************/ /*!
583 @Function       _FindProcessStatsInDeadList
584 @Description    Searches the Dead Process List for a statistics structure that
585                 matches the PID given.
586 @Input          pid  Process to search for.
587 @Return         Pointer to stats structure for the process.
588 */ /**************************************************************************/
589 static PVRSRV_PROCESS_STATS*
590 _FindProcessStatsInDeadList(IMG_PID pid)
591 {
592         PVRSRV_PROCESS_STATS*  psProcessStats = psDeadList;
593
594         while (psProcessStats != IMG_NULL)
595         {
596                 if (psProcessStats->pid == pid)
597                 {
598                         return psProcessStats;
599                 }
600
601                 psProcessStats = psProcessStats->psNext;
602         }
603
604         return IMG_NULL;
605 } /* _FindProcessStatsInDeadList */
606
607
608 /*************************************************************************/ /*!
609 @Function       _FindProcessStats
610 @Description    Searches the Live and Dead Process Lists for a statistics
611                 structure that matches the PID given.
612 @Input          pid  Process to search for.
613 @Return         Pointer to stats structure for the process.
614 */ /**************************************************************************/
615 static PVRSRV_PROCESS_STATS*
616 _FindProcessStats(IMG_PID pid)
617 {
618         PVRSRV_PROCESS_STATS*  psProcessStats = _FindProcessStatsInLiveList(pid);
619
620         if (psProcessStats == IMG_NULL)
621         {
622                 psProcessStats = _FindProcessStatsInDeadList(pid);
623         }
624
625         return psProcessStats;
626 } /* _FindProcessStats */
627
628
629 /*************************************************************************/ /*!
630 @Function       _AddProcessStatsToFrontOfLiveList
631 @Description    Add a statistic to the live list head.
632 @Input          psProcessStats  Process stats to add.
633 */ /**************************************************************************/
634 static IMG_VOID
635 _AddProcessStatsToFrontOfLiveList(PVRSRV_PROCESS_STATS* psProcessStats)
636 {
637         PVR_ASSERT(psProcessStats != IMG_NULL);
638
639         if (psLiveList != IMG_NULL)
640         {
641                 psLiveList->psPrev     = psProcessStats;
642                 psProcessStats->psNext = psLiveList;
643         }
644
645         psLiveList = psProcessStats;
646 } /* _AddProcessStatsToFrontOfLiveList */
647
648
649 /*************************************************************************/ /*!
650 @Function       _AddProcessStatsToFrontOfDeadList
651 @Description    Add a statistic to the dead list head.
652 @Input          psProcessStats  Process stats to add.
653 */ /**************************************************************************/
654 static IMG_VOID
655 _AddProcessStatsToFrontOfDeadList(PVRSRV_PROCESS_STATS* psProcessStats)
656 {
657         PVR_ASSERT(psProcessStats != IMG_NULL);
658
659         if (psDeadList != IMG_NULL)
660         {
661                 psDeadList->psPrev     = psProcessStats;
662                 psProcessStats->psNext = psDeadList;
663         }
664
665         psDeadList = psProcessStats;
666 } /* _AddProcessStatsToFrontOfDeadList */
667
668
669 /*************************************************************************/ /*!
670 @Function       _RemoveProcessStatsFromList
671 @Description    Detaches a process from either the live or dead list.
672 @Input          psProcessStats  Process stats to remove.
673 */ /**************************************************************************/
674 static IMG_VOID
675 _RemoveProcessStatsFromList(PVRSRV_PROCESS_STATS* psProcessStats)
676 {
677         PVR_ASSERT(psProcessStats != IMG_NULL);
678
679         /* Remove the item from the linked lists... */
680         if (psLiveList == psProcessStats)
681         {
682                 psLiveList = psProcessStats->psNext;
683
684                 if (psLiveList != IMG_NULL)
685                 {
686                         psLiveList->psPrev = IMG_NULL;
687                 }
688         }
689         else if (psDeadList == psProcessStats)
690         {
691                 psDeadList = psProcessStats->psNext;
692
693                 if (psDeadList != IMG_NULL)
694                 {
695                         psDeadList->psPrev = IMG_NULL;
696                 }
697         }
698         else
699         {
700                 PVRSRV_PROCESS_STATS*  psNext = psProcessStats->psNext;
701                 PVRSRV_PROCESS_STATS*  psPrev = psProcessStats->psPrev;
702
703                 if (psProcessStats->psNext != IMG_NULL)
704                 {
705                         psProcessStats->psNext->psPrev = psPrev;
706                 }
707                 if (psProcessStats->psPrev != IMG_NULL)
708                 {
709                         psProcessStats->psPrev->psNext = psNext;
710                 }
711         }
712
713         /* Reset the pointers in this cell, as it is not attached to anything */
714         psProcessStats->psNext = IMG_NULL;
715         psProcessStats->psPrev = IMG_NULL;
716 } /* _RemoveProcessStatsFromList */
717
718
719 /*************************************************************************/ /*!
720 @Function       _CreateOSStatisticEntries
721 @Description    Create all OS entries for this statistic.
722 @Input          psProcessStats  Process stats to destroy.
723 @Input          pvOSPidFolder   Pointer to OS folder to place the entrys in.
724 */ /**************************************************************************/
725 static IMG_VOID
726 _CreateOSStatisticEntries(PVRSRV_PROCESS_STATS* psProcessStats,
727                           IMG_PVOID pvOSPidFolder)
728 {
729         PVR_ASSERT(psProcessStats != IMG_NULL);
730
731         psProcessStats->pvOSPidFolderData = OSCreateStatisticFolder(psProcessStats->szFolderName, pvOSPidFolder);
732         psProcessStats->pvOSPidEntryData  = OSCreateStatisticEntry("process_stats",
733                                                                    psProcessStats->pvOSPidFolderData,
734                                                                    ProcessStatsPrintElements,
735                                                                                                                            _PVRSRVIncrMemStatRefCount,
736                                                                                                                            _PVRSRVDecrMemStatRefCount,
737                                                                    (IMG_PVOID) psProcessStats);
738
739 #if defined(PVRSRV_ENABLE_MEMORY_STATS)
740         psProcessStats->psMemoryStats->pvOSMemEntryData = OSCreateStatisticEntry("mem_area",
741                                                                    psProcessStats->pvOSPidFolderData,
742                                                                    MemStatsPrintElements,
743                                                                                                                            IMG_NULL,
744                                                                                                                            IMG_NULL,
745                                                                    (IMG_PVOID) psProcessStats->psMemoryStats);
746 #endif
747
748 #if defined(PVR_RI_DEBUG)
749         psProcessStats->psRIMemoryStats->pvOSRIMemEntryData = OSCreateStatisticEntry("ri_mem_area",
750                                                                    psProcessStats->pvOSPidFolderData,
751                                                                    RIMemStatsPrintElements,
752                                                                                                                            IMG_NULL,
753                                                                                                                            IMG_NULL,
754                                                                    (IMG_PVOID) psProcessStats->psRIMemoryStats);
755 #endif
756 } /* _CreateOSStatisticEntries */
757
758
759 /*************************************************************************/ /*!
760 @Function       _RemoveOSStatisticEntries
761 @Description    Removed all OS entries used by this statistic.
762 @Input          psProcessStats  Process stats to destroy.
763 */ /**************************************************************************/
764 static IMG_VOID
765 _RemoveOSStatisticEntries(PVRSRV_PROCESS_STATS* psProcessStats)
766 {
767         PVR_ASSERT(psProcessStats != IMG_NULL);
768
769 #if defined(PVR_RI_DEBUG)
770         OSRemoveStatisticEntry(psProcessStats->psRIMemoryStats->pvOSRIMemEntryData);
771 #endif
772
773 #if defined(PVRSRV_ENABLE_MEMORY_STATS)
774         OSRemoveStatisticEntry(psProcessStats->psMemoryStats->pvOSMemEntryData);
775 #endif
776
777         if( psProcessStats->pvOSPidEntryData != IMG_NULL)
778         {
779                 OSRemoveStatisticEntry(psProcessStats->pvOSPidEntryData);
780         }
781         if( psProcessStats->pvOSPidFolderData != IMG_NULL)
782         {
783                 OSRemoveStatisticFolder(psProcessStats->pvOSPidFolderData);
784         }
785 } /* _RemoveOSStatisticEntries */
786
787
788 /*************************************************************************/ /*!
789 @Function       _DestoryProcessStat
790 @Description    Frees memory and resources held by a process statistic.
791 @Input          psProcessStats  Process stats to destroy.
792 */ /**************************************************************************/
793 static IMG_VOID
794 _DestoryProcessStat(PVRSRV_PROCESS_STATS* psProcessStats)
795 {
796         PVR_ASSERT(psProcessStats != IMG_NULL);
797
798         /* Remove this statistic from the OS... */
799         //_RemoveOSStatisticEntries(psProcessStats);
800
801         /* Free the live and dead render statistic lists... */
802         while (psProcessStats->psRenderLiveList != IMG_NULL)
803         {
804                 PVRSRV_RENDER_STATS*  psRenderStats = psProcessStats->psRenderLiveList;
805
806                 _RemoveRenderStatsFromList(psProcessStats, psRenderStats);
807                 _DestoryRenderStat(psRenderStats);
808         }
809
810         while (psProcessStats->psRenderDeadList != IMG_NULL)
811         {
812                 PVRSRV_RENDER_STATS*  psRenderStats = psProcessStats->psRenderDeadList;
813
814                 _RemoveRenderStatsFromList(psProcessStats, psRenderStats);
815                 _DestoryRenderStat(psRenderStats);
816         }
817
818         /* Free the memory statistics... */
819 #if defined(PVRSRV_ENABLE_MEMORY_STATS)
820         while (psProcessStats->psMemoryStats->psMemoryRecords)
821         {
822                 List_PVRSRV_MEM_ALLOC_REC_Remove(psProcessStats->psMemoryStats->psMemoryRecords);
823         }
824         OSFreeMem(psProcessStats->psMemoryStats);
825 #endif
826
827         /* Free the memory... */
828         OSFreeMem(psProcessStats);
829 } /* _DestoryProcessStat */
830
831 static IMG_UINT32 _PVRSRVIncrMemStatRefCount(IMG_PVOID pvStatPtr)
832 {
833         PVRSRV_STAT_STRUCTURE_TYPE*  peStructureType = (PVRSRV_STAT_STRUCTURE_TYPE*) pvStatPtr;
834         PVRSRV_PROCESS_STATS*  psProcessStats = (PVRSRV_PROCESS_STATS*) pvStatPtr;
835         IMG_UINT32 ui32Res = 7777;
836
837     switch (*peStructureType)
838         {
839                 case PVRSRV_STAT_STRUCTURE_PROCESS:
840                 {
841                         /* Increment stat memory refCount */
842                         ui32Res = ++psProcessStats->ui32MemRefCount;
843                         break;
844                 }
845                 default:
846                 {
847                         break;
848                 }
849         }
850         return ui32Res;
851 }
852
853 static IMG_UINT32 _PVRSRVDecrMemStatRefCount(IMG_PVOID pvStatPtr)
854 {
855         PVRSRV_STAT_STRUCTURE_TYPE*  peStructureType = (PVRSRV_STAT_STRUCTURE_TYPE*) pvStatPtr;
856         PVRSRV_PROCESS_STATS*  psProcessStats = (PVRSRV_PROCESS_STATS*) pvStatPtr;
857         IMG_UINT32 ui32Res = 7777;
858
859     switch (*peStructureType)
860         {
861                 case PVRSRV_STAT_STRUCTURE_PROCESS:
862                 {
863                         /* Decrement stat memory refCount and free if now zero */
864                         ui32Res = --psProcessStats->ui32MemRefCount;
865                         if (ui32Res == 0)
866                         {
867                                 _DestoryProcessStat(psProcessStats);
868                         }
869                         break;
870                 }
871                 default:
872                 {
873                         break;
874                 }
875         }
876         return ui32Res;
877 }
878
879 /*************************************************************************/ /*!
880 @Function       _CompressMemoryUsage
881 @Description    Reduces memory usage by deleting old statistics data.
882                 This function requires that the list lock is not held!
883 */ /**************************************************************************/
884 static IMG_VOID
885 _CompressMemoryUsage(IMG_VOID)
886 {
887         PVRSRV_PROCESS_STATS*  psProcessStats;
888         PVRSRV_PROCESS_STATS*  psProcessStatsToBeFreed;
889         IMG_UINT32  ui32ItemsRemaining;
890
891         /*
892          *  We hold the lock whilst checking the list, but we'll release it
893          *  before freeing memory (as that will require the lock too)!
894          */
895     OSLockAcquire(psLinkedListLock);
896
897         /* Check that the dead list is not bigger than the max size... */
898         psProcessStats          = psDeadList;
899         psProcessStatsToBeFreed = IMG_NULL;
900         ui32ItemsRemaining      = MAX_DEAD_LIST_PROCESSES;
901
902         while (psProcessStats != IMG_NULL  &&  ui32ItemsRemaining > 0)
903     {
904                 ui32ItemsRemaining--;
905                 if (ui32ItemsRemaining == 0)
906                 {
907                         /* This is the last allowed process, cut the linked list here! */
908                         psProcessStatsToBeFreed = psProcessStats->psNext;
909                         psProcessStats->psNext  = IMG_NULL;
910                 }
911                 else
912                 {
913                         psProcessStats = psProcessStats->psNext;
914                 }
915         }
916
917         OSLockRelease(psLinkedListLock);
918
919         /* Any processes stats remaining will need to be destroyed... */
920         while (psProcessStatsToBeFreed != IMG_NULL)
921     {
922                 PVRSRV_PROCESS_STATS*  psNextProcessStats = psProcessStatsToBeFreed->psNext;
923
924                 psProcessStatsToBeFreed->psNext = IMG_NULL;
925                 _RemoveOSStatisticEntries(psProcessStatsToBeFreed);
926                 _PVRSRVDecrMemStatRefCount((void*)psProcessStatsToBeFreed);
927                 //_DestoryProcessStat(psProcessStatsToBeFreed);
928
929                 psProcessStatsToBeFreed = psNextProcessStats;
930         }
931 } /* _CompressMemoryUsage */
932
933 /* These functions move the process stats from the living to the dead list.
934  * _MoveProcessToDeadList moves the entry in the global lists and
935  * it needs to be protected by psLinkedListLock.
936  * _MoveProcessToDeadListDebugFS performs the OS calls and it
937  * shouldn't be used under psLinkedListLock because this could generate a
938  * lockdep warning. */
939 static IMG_VOID
940 _MoveProcessToDeadList(PVRSRV_PROCESS_STATS* psProcessStats)
941 {
942         /* Take the element out of the live list and append to the dead list... */
943         _RemoveProcessStatsFromList(psProcessStats);
944         _AddProcessStatsToFrontOfDeadList(psProcessStats);
945 } /* _MoveProcessToDeadList */
946
947 static IMG_VOID
948 _MoveProcessToDeadListDebugFS(PVRSRV_PROCESS_STATS* psProcessStats)
949 {
950         /* Transfer the OS entries to the folder for dead processes... */
951         _RemoveOSStatisticEntries(psProcessStats);
952         _CreateOSStatisticEntries(psProcessStats, pvOSDeadPidFolder);
953 } /* _MoveProcessToDeadListDebugFS */
954
955
956 /*************************************************************************/ /*!
957 @Function       PVRSRVStatsInitialise
958 @Description    Entry point for initialising the statistics module.
959 @Return         Standard PVRSRV_ERROR error code.
960 */ /**************************************************************************/
961 PVRSRV_ERROR
962 PVRSRVStatsInitialise(IMG_VOID)
963 {
964     PVRSRV_ERROR error;
965
966     PVR_ASSERT(psLiveList == IMG_NULL);
967     PVR_ASSERT(psDeadList == IMG_NULL);
968     PVR_ASSERT(psLinkedListLock == IMG_NULL);
969         PVR_ASSERT(gpsVmallocSizeHashTable == NULL);
970         PVR_ASSERT(bProcessStatsInitialised == IMG_FALSE);
971
972         /* We need a lock to protect the linked lists... */
973         error = OSLockCreate(&psLinkedListLock, LOCK_TYPE_NONE);
974         if (error == PVRSRV_OK)
975         {
976                 /* We also need a lock to protect the hash table used for vmalloc size tracking.. */
977                 error = OSLockCreate(&gpsVmallocSizeHashTableLock, LOCK_TYPE_NONE);
978
979                 if (error != PVRSRV_OK)
980                 {
981                         goto e0;
982                 }
983                 /* Create a pid folders for putting the PID files in... */
984                 pvOSLivePidFolder = OSCreateStatisticFolder(pszOSLivePidFolderName, IMG_NULL);
985                 pvOSDeadPidFolder = OSCreateStatisticFolder(pszOSDeadPidFolderName, IMG_NULL);
986
987                 /* Create power stats entry... */
988                 pvOSPowerStatsEntryData = OSCreateStatisticEntry("power_timing_stats",
989                                                                                                                  IMG_NULL,
990                                                                                                                  PowerStatsPrintElements,
991                                                                                                              IMG_NULL,
992                                                                                                              IMG_NULL,
993                                                                                                              IMG_NULL);
994
995                 pvOSGlobalMemEntryRef = OSCreateStatisticEntry(pszDriverStatFilename,
996                                                                                                            IMG_NULL,
997                                                                                                            GlobalStatsPrintElements,
998                                                                                                        IMG_NULL,
999                                                                                                            IMG_NULL,
1000                                                                                                            IMG_NULL);
1001
1002                 /* Flag that we are ready to start monitoring memory allocations. */
1003
1004                 gpsVmallocSizeHashTable = HASH_Create(HASH_INITIAL_SIZE);
1005
1006                 OSMemSet(&gsGlobalStats, 0, sizeof(gsGlobalStats));
1007
1008                 OSMemSet(asClockSpeedChanges, 0, sizeof(asClockSpeedChanges));
1009         
1010                 bProcessStatsInitialised = IMG_TRUE;
1011         }
1012         return error;
1013 e0:
1014         OSLockDestroy(psLinkedListLock);
1015         psLinkedListLock = NULL;
1016         return error;
1017
1018 } /* PVRSRVStatsInitialise */
1019
1020
1021 /*************************************************************************/ /*!
1022 @Function       PVRSRVStatsDestroy
1023 @Description    Method for destroying the statistics module data.
1024 */ /**************************************************************************/
1025 IMG_VOID
1026 PVRSRVStatsDestroy(IMG_VOID)
1027 {
1028         PVR_ASSERT(bProcessStatsInitialised == IMG_TRUE);
1029
1030         /* Stop monitoring memory allocations... */
1031         bProcessStatsInitialised = IMG_FALSE;
1032
1033         /* Destroy the power stats entry... */
1034         if (pvOSPowerStatsEntryData!=NULL)
1035         {
1036                 OSRemoveStatisticEntry(pvOSPowerStatsEntryData);
1037                 pvOSPowerStatsEntryData=NULL;
1038         }
1039
1040         /* Destroy the global data entry */
1041         if (pvOSGlobalMemEntryRef!=NULL)
1042         {
1043                 OSRemoveStatisticEntry(pvOSGlobalMemEntryRef);
1044                 pvOSGlobalMemEntryRef=NULL;
1045         }
1046         
1047         /* Destroy the lock... */
1048         if (psLinkedListLock != IMG_NULL)
1049         {
1050                 OSLockDestroy(psLinkedListLock);
1051                 psLinkedListLock = IMG_NULL;
1052         }
1053
1054         /* Free the live and dead lists... */
1055     while (psLiveList != IMG_NULL)
1056     {
1057                 PVRSRV_PROCESS_STATS*  psProcessStats = psLiveList;
1058
1059                 _RemoveProcessStatsFromList(psProcessStats);
1060                 _RemoveOSStatisticEntries(psProcessStats);
1061         }
1062
1063     while (psDeadList != IMG_NULL)
1064     {
1065                 PVRSRV_PROCESS_STATS*  psProcessStats = psDeadList;
1066
1067                 _RemoveProcessStatsFromList(psProcessStats);
1068                 _RemoveOSStatisticEntries(psProcessStats);
1069         }
1070
1071         /* Remove the OS folders used by the PID folders... */
1072     OSRemoveStatisticFolder(pvOSLivePidFolder);
1073     pvOSLivePidFolder = IMG_NULL;
1074     OSRemoveStatisticFolder(pvOSDeadPidFolder);
1075     pvOSDeadPidFolder = IMG_NULL;
1076
1077         if (gpsVmallocSizeHashTable != IMG_NULL)
1078         {
1079                 HASH_Delete(gpsVmallocSizeHashTable);
1080         }
1081         if (gpsVmallocSizeHashTableLock != IMG_NULL)
1082         {
1083                 OSLockDestroy(gpsVmallocSizeHashTableLock);
1084                 gpsVmallocSizeHashTableLock = IMG_NULL;
1085         }
1086
1087 } /* PVRSRVStatsDestroy */
1088
1089
1090
1091 static void _decrease_global_stat(PVRSRV_MEM_ALLOC_TYPE eAllocType,
1092                                                                   IMG_SIZE_T uiBytes)
1093 {
1094         switch (eAllocType)
1095         {
1096                 case PVRSRV_MEM_ALLOC_TYPE_KMALLOC:
1097                         DECREASE_GLOBAL_STAT_VALUE(gsGlobalStats.ui32MemoryUsageKMalloc, uiBytes);
1098                         break;
1099
1100                 case PVRSRV_MEM_ALLOC_TYPE_VMALLOC:
1101                         DECREASE_GLOBAL_STAT_VALUE(gsGlobalStats.ui32MemoryUsageVMalloc, uiBytes);
1102                         break;
1103
1104                 case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_UMA:
1105                         DECREASE_GLOBAL_STAT_VALUE(gsGlobalStats.ui32MemoryUsageAllocPTMemoryUMA, uiBytes);
1106                         break;
1107
1108                 case PVRSRV_MEM_ALLOC_TYPE_VMAP_PT_UMA:
1109                         DECREASE_GLOBAL_STAT_VALUE(gsGlobalStats.ui32MemoryUsageVMapPTUMA, uiBytes);
1110                         break;
1111
1112                 case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA:
1113                         DECREASE_GLOBAL_STAT_VALUE(gsGlobalStats.ui32MemoryUsageAllocPTMemoryLMA, uiBytes);
1114                         break;
1115
1116                 case PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA:
1117                         DECREASE_GLOBAL_STAT_VALUE(gsGlobalStats.ui32MemoryUsageIORemapPTLMA, uiBytes);
1118                         break;
1119
1120                 case PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES:
1121                         DECREASE_GLOBAL_STAT_VALUE(gsGlobalStats.ui32MemoryUsageAllocGPUMemLMA, uiBytes);
1122                         break;
1123
1124                 case PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES:     
1125                         DECREASE_GLOBAL_STAT_VALUE(gsGlobalStats.ui32MemoryUsageAllocGPUMemUMA, uiBytes);
1126                         break;
1127
1128                 case PVRSRV_MEM_ALLOC_TYPE_MAP_UMA_LMA_PAGES:
1129                         DECREASE_GLOBAL_STAT_VALUE(gsGlobalStats.ui32MemoryUsageMappedGPUMemUMA_LMA, uiBytes);
1130                         break;
1131
1132                 case PVRSRV_MEM_ALLOC_TYPE_UMA_POOL_PAGES:
1133                         DECREASE_GLOBAL_STAT_VALUE(gsGlobalStats.ui32MemoryUsageAllocGPUMemUMAPool, uiBytes);
1134                         break;
1135
1136                 default:
1137                         PVR_ASSERT(0);
1138                         break;
1139         }
1140 }
1141
1142 static void _increase_global_stat(PVRSRV_MEM_ALLOC_TYPE eAllocType,
1143                                                                   IMG_SIZE_T uiBytes)
1144 {
1145         switch (eAllocType)
1146         {
1147                 case PVRSRV_MEM_ALLOC_TYPE_KMALLOC:
1148                         INCREASE_GLOBAL_STAT_VALUE(gsGlobalStats.ui32MemoryUsageKMalloc, uiBytes);
1149                         break;
1150
1151                 case PVRSRV_MEM_ALLOC_TYPE_VMALLOC:
1152                         INCREASE_GLOBAL_STAT_VALUE(gsGlobalStats.ui32MemoryUsageVMalloc, uiBytes);
1153                         break;
1154
1155                 case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_UMA:
1156                         INCREASE_GLOBAL_STAT_VALUE(gsGlobalStats.ui32MemoryUsageAllocPTMemoryUMA, uiBytes);
1157                         break;
1158
1159                 case PVRSRV_MEM_ALLOC_TYPE_VMAP_PT_UMA:
1160                         INCREASE_GLOBAL_STAT_VALUE(gsGlobalStats.ui32MemoryUsageVMapPTUMA, uiBytes);
1161                         break;
1162
1163                 case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA:
1164                         INCREASE_GLOBAL_STAT_VALUE(gsGlobalStats.ui32MemoryUsageAllocPTMemoryLMA, uiBytes);
1165                         break;
1166
1167                 case PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA:
1168                         INCREASE_GLOBAL_STAT_VALUE(gsGlobalStats.ui32MemoryUsageIORemapPTLMA, uiBytes);
1169                         break;
1170
1171                 case PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES:
1172                         INCREASE_GLOBAL_STAT_VALUE(gsGlobalStats.ui32MemoryUsageAllocGPUMemLMA, uiBytes);
1173                         break;
1174
1175                 case PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES:     
1176                         INCREASE_GLOBAL_STAT_VALUE(gsGlobalStats.ui32MemoryUsageAllocGPUMemUMA, uiBytes);
1177                         break;
1178
1179                 case PVRSRV_MEM_ALLOC_TYPE_MAP_UMA_LMA_PAGES:
1180                         INCREASE_GLOBAL_STAT_VALUE(gsGlobalStats.ui32MemoryUsageMappedGPUMemUMA_LMA, uiBytes);
1181                         break;
1182
1183                 case PVRSRV_MEM_ALLOC_TYPE_UMA_POOL_PAGES:
1184                         INCREASE_GLOBAL_STAT_VALUE(gsGlobalStats.ui32MemoryUsageAllocGPUMemUMAPool, uiBytes);
1185                         break;
1186
1187                 default:
1188                         PVR_ASSERT(0);
1189                         break;
1190         }
1191         //Count total data
1192     gsGlobalStats.ui32MemoryUsageTotalAlloc = gsGlobalStats.ui32MemoryUsageKMalloc + gsGlobalStats.ui32MemoryUsageVMalloc +\
1193         gsGlobalStats.ui32MemoryUsageAllocPTMemoryUMA + gsGlobalStats.ui32MemoryUsageAllocPTMemoryLMA +\
1194         gsGlobalStats.ui32MemoryUsageAllocGPUMemLMA + gsGlobalStats.ui32MemoryUsageAllocGPUMemUMA;
1195
1196     gsGlobalStats.ui32MemoryUsageTotalMap = gsGlobalStats.ui32MemoryUsageVMapPTUMA + gsGlobalStats.ui32MemoryUsageIORemapPTLMA +\
1197         gsGlobalStats.ui32MemoryUsageMappedGPUMemUMA_LMA;
1198         //Count total data
1199         gsGlobalStats.ui32MemoryUsageTotalAlloc = gsGlobalStats.ui32MemoryUsageKMalloc + gsGlobalStats.ui32MemoryUsageVMalloc +\
1200         gsGlobalStats.ui32MemoryUsageAllocPTMemoryUMA + gsGlobalStats.ui32MemoryUsageAllocPTMemoryLMA +\
1201         gsGlobalStats.ui32MemoryUsageAllocGPUMemLMA + gsGlobalStats.ui32MemoryUsageAllocGPUMemUMA;
1202     UPDATE_MAX_VALUE(gsGlobalStats.ui32MemoryUsageTotalAllocMax,gsGlobalStats.ui32MemoryUsageTotalAlloc);
1203
1204     gsGlobalStats.ui32MemoryUsageTotalMap = gsGlobalStats.ui32MemoryUsageVMapPTUMA + gsGlobalStats.ui32MemoryUsageIORemapPTLMA +\
1205         gsGlobalStats.ui32MemoryUsageMappedGPUMemUMA_LMA;
1206     UPDATE_MAX_VALUE(gsGlobalStats.ui32MemoryUsageTotalMapMax,gsGlobalStats.ui32MemoryUsageTotalMap);
1207 }
1208
1209
1210 /*************************************************************************/ /*!
1211 @Function       PVRSRVStatsRegisterProcess
1212 @Description    Register a process into the list statistics list.
1213 @Output         phProcessStats  Handle to the process to be used to deregister.
1214 @Return         Standard PVRSRV_ERROR error code.
1215 */ /**************************************************************************/
1216 PVRSRV_ERROR
1217 PVRSRVStatsRegisterProcess(IMG_HANDLE* phProcessStats)
1218 {
1219     PVRSRV_PROCESS_STATS*  psProcessStats;
1220     IMG_PID                currentPid = OSGetCurrentProcessID();
1221         IMG_BOOL               bMoveProcess = IMG_FALSE;
1222
1223     PVR_ASSERT(phProcessStats != IMG_NULL);
1224
1225     /* Check the PID has not already moved to the dead list... */
1226         OSLockAcquire(psLinkedListLock);
1227         psProcessStats = _FindProcessStatsInDeadList(currentPid);
1228     if (psProcessStats != IMG_NULL)
1229     {
1230                 /* Move it back onto the live list! */
1231                 _RemoveProcessStatsFromList(psProcessStats);
1232                 _AddProcessStatsToFrontOfLiveList(psProcessStats);
1233
1234                 /* we can perform the OS operation out of lock */
1235                 bMoveProcess = IMG_TRUE;
1236         }
1237         else
1238         {
1239                 /* Check the PID is not already registered in the live list... */
1240                 psProcessStats = _FindProcessStatsInLiveList(currentPid);
1241         }
1242
1243         /* If the PID is on the live list then just increment the ref count and return... */
1244     if (psProcessStats != IMG_NULL)
1245     {
1246                 psProcessStats->ui32RefCount++;
1247                 psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_CONNECTIONS] = psProcessStats->ui32RefCount;
1248                 UPDATE_MAX_VALUE(psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_CONNECTIONS],
1249                                  psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_CONNECTIONS]);
1250                 OSLockRelease(psLinkedListLock);
1251
1252                 *phProcessStats = psProcessStats;
1253
1254                 /* Check if we need to perform any OS operation */
1255                 if (bMoveProcess)
1256                 {
1257                         /* Transfer the OS entries back to the folder for live processes... */
1258                         _RemoveOSStatisticEntries(psProcessStats);
1259                         _CreateOSStatisticEntries(psProcessStats, pvOSLivePidFolder);
1260                 }
1261
1262                 return PVRSRV_OK;
1263         }
1264         OSLockRelease(psLinkedListLock);
1265
1266         /* Allocate a new node structure and initialise it... */
1267         psProcessStats = OSAllocMem(sizeof(PVRSRV_PROCESS_STATS));
1268         if (psProcessStats == IMG_NULL)
1269         {
1270                 *phProcessStats = 0;
1271                 return PVRSRV_ERROR_OUT_OF_MEMORY;
1272         }
1273
1274         OSMemSet(psProcessStats, 0, sizeof(PVRSRV_PROCESS_STATS));
1275
1276         psProcessStats->eStructureType  = PVRSRV_STAT_STRUCTURE_PROCESS;
1277         psProcessStats->pid             = currentPid;
1278         psProcessStats->ui32RefCount    = 1;
1279         psProcessStats->ui32MemRefCount = 1;
1280
1281         psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_CONNECTIONS]     = 1;
1282         psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_CONNECTIONS] = 1;
1283
1284 #if defined(PVRSRV_ENABLE_MEMORY_STATS)
1285         psProcessStats->psMemoryStats = OSAllocMem(sizeof(PVRSRV_MEMORY_STATS));
1286         if (psProcessStats->psMemoryStats == IMG_NULL)
1287         {
1288                 OSFreeMem(psProcessStats);
1289                 *phProcessStats = 0;
1290                 return PVRSRV_ERROR_OUT_OF_MEMORY;
1291         }
1292
1293         OSMemSet(psProcessStats->psMemoryStats, 0, sizeof(PVRSRV_MEMORY_STATS));
1294         psProcessStats->psMemoryStats->eStructureType = PVRSRV_STAT_STRUCTURE_MEMORY;
1295 #endif
1296
1297 #if defined(PVR_RI_DEBUG)
1298         psProcessStats->psRIMemoryStats = OSAllocMem(sizeof(PVRSRV_RI_MEMORY_STATS));
1299         if (psProcessStats->psRIMemoryStats == IMG_NULL)
1300         {
1301                 OSFreeMem(psProcessStats->psMemoryStats);
1302                 OSFreeMem(psProcessStats);
1303                 *phProcessStats = 0;
1304                 return PVRSRV_ERROR_OUT_OF_MEMORY;
1305         }
1306
1307         OSMemSet(psProcessStats->psRIMemoryStats, 0, sizeof(PVRSRV_RI_MEMORY_STATS));
1308         psProcessStats->psRIMemoryStats->eStructureType = PVRSRV_STAT_STRUCTURE_RIMEMORY;
1309         psProcessStats->psRIMemoryStats->pid            = currentPid;
1310 #endif
1311
1312         /* Add it to the live list... */
1313     OSLockAcquire(psLinkedListLock);
1314         _AddProcessStatsToFrontOfLiveList(psProcessStats);
1315         OSLockRelease(psLinkedListLock);
1316
1317         /* Create the process stat in the OS... */
1318         OSSNPrintf(psProcessStats->szFolderName, sizeof(psProcessStats->szFolderName),
1319                    "%d", currentPid);
1320         _CreateOSStatisticEntries(psProcessStats, pvOSLivePidFolder);
1321
1322         /* Done */
1323         *phProcessStats = (IMG_HANDLE) psProcessStats;
1324
1325         return PVRSRV_OK;
1326 } /* PVRSRVStatsRegisterProcess */
1327
1328
1329 /*************************************************************************/ /*!
1330 @Function       PVRSRVStatsDeregisterProcess
1331 @Input          hProcessStats  Handle to the process returned when registered.
1332 @Description    Method for destroying the statistics module data.
1333 */ /**************************************************************************/
1334 IMG_VOID
1335 PVRSRVStatsDeregisterProcess(IMG_HANDLE hProcessStats)
1336 {
1337         IMG_BOOL    bMoveProcess = IMG_FALSE;
1338
1339         if (hProcessStats != 0)
1340         {
1341                 PVRSRV_PROCESS_STATS*  psProcessStats = (PVRSRV_PROCESS_STATS*) hProcessStats;
1342
1343                 /* Lower the reference count, if zero then move it to the dead list */
1344                 OSLockAcquire(psLinkedListLock);
1345                 if (psProcessStats->ui32RefCount > 0)
1346                 {
1347                         psProcessStats->ui32RefCount--;
1348                         psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_CONNECTIONS] = psProcessStats->ui32RefCount;
1349
1350                         if (psProcessStats->ui32RefCount == 0)
1351                         {
1352                                 _MoveProcessToDeadList(psProcessStats);
1353                                 bMoveProcess = IMG_TRUE;
1354                         }
1355                 }
1356                 OSLockRelease(psLinkedListLock);
1357
1358                 /* The OS calls need to be performed without psLinkedListLock */
1359                 if (bMoveProcess == IMG_TRUE)
1360                 {
1361                         _MoveProcessToDeadListDebugFS(psProcessStats);
1362                 }
1363
1364                 /* Check if the dead list needs to be reduced */
1365                 _CompressMemoryUsage();
1366         }
1367 } /* PVRSRVStatsDeregisterProcess */
1368
1369
1370 IMG_VOID
1371 PVRSRVStatsAddMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE eAllocType,
1372                              IMG_VOID *pvCpuVAddr,
1373                              IMG_CPU_PHYADDR sCpuPAddr,
1374                              IMG_SIZE_T uiBytes,
1375                              IMG_PVOID pvPrivateData)
1376 {
1377 #if defined(PVRSRV_ENABLE_MEMORY_STATS)
1378         IMG_PID                currentPid = OSGetCurrentProcessID();
1379         IMG_PID                            currentCleanupPid = PVRSRVGetPurgeConnectionPid();
1380     PVRSRV_DATA*                   psPVRSRVData = PVRSRVGetPVRSRVData();
1381     PVRSRV_MEM_ALLOC_REC*  psRecord   = IMG_NULL;
1382     PVRSRV_PROCESS_STATS*  psProcessStats;
1383     PVRSRV_MEMORY_STATS*   psMemoryStats;
1384
1385     /* Don't do anything if we are not initialised or we are shutting down! */
1386     if (!bProcessStatsInitialised)
1387     {
1388                 return;
1389         }
1390
1391         /*
1392          *  To prevent a recursive loop, we make the memory allocations
1393          *  for our memstat records via OSAllocMemstatMem(), which does not try to
1394          *  create a memstat record entry..
1395          */
1396
1397     /* Allocate the memory record... */
1398         psRecord = OSAllocMemstatMem(sizeof(PVRSRV_MEM_ALLOC_REC));
1399         if (psRecord == IMG_NULL)
1400         {
1401                 return;
1402         }
1403
1404         OSMemSet(psRecord, 0, sizeof(PVRSRV_MEM_ALLOC_REC));
1405         psRecord->eAllocType       = eAllocType;
1406         psRecord->pvCpuVAddr       = pvCpuVAddr;
1407         psRecord->sCpuPAddr.uiAddr = sCpuPAddr.uiAddr;
1408         psRecord->uiBytes          = uiBytes;
1409         psRecord->pvPrivateData    = pvPrivateData;
1410
1411         /* Lock while we find the correct process... */
1412         OSLockAcquire(psLinkedListLock);
1413
1414         _increase_global_stat(eAllocType, uiBytes);
1415         
1416         if (psPVRSRVData)
1417         {
1418                 if ( (currentPid == psPVRSRVData->cleanupThreadPid) &&
1419                            (currentCleanupPid != 0))
1420                 {
1421                         psProcessStats = _FindProcessStats(currentCleanupPid);
1422                 }
1423             else
1424             {
1425                 psProcessStats = _FindProcessStats(currentPid);
1426             }
1427         }
1428     else
1429     {
1430         psProcessStats = _FindProcessStats(currentPid);
1431     }
1432     if (psProcessStats == IMG_NULL)
1433     {
1434                 OSLockRelease(psLinkedListLock);
1435                 if (psRecord != IMG_NULL)
1436                 {
1437                         OSFreeMemstatMem(psRecord);
1438                 }
1439                 return;
1440         }
1441         psMemoryStats = psProcessStats->psMemoryStats;
1442
1443         /* Insert the memory record... */
1444         if (psRecord != IMG_NULL)
1445         {
1446                 List_PVRSRV_MEM_ALLOC_REC_Insert(&psMemoryStats->psMemoryRecords, psRecord);
1447         }
1448
1449         /* Update the memory watermarks... */
1450         switch (eAllocType)
1451         {
1452                 case PVRSRV_MEM_ALLOC_TYPE_KMALLOC:
1453                 {
1454                         if (psRecord != IMG_NULL)
1455                         {
1456                                 if (pvCpuVAddr == IMG_NULL)
1457                                 {
1458                                         return;
1459                                 }
1460                                 psRecord->ui64Key = (IMG_UINT64)(IMG_UINTPTR_T)pvCpuVAddr;
1461                         }
1462                         INCREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_KMALLOC, uiBytes);
1463                 }
1464                 break;
1465
1466                 case PVRSRV_MEM_ALLOC_TYPE_VMALLOC:
1467                 {
1468                         if (psRecord != IMG_NULL)
1469                         {
1470                                 if (pvCpuVAddr == IMG_NULL)
1471                                 {
1472                                         return;
1473                                 }
1474                                 psRecord->ui64Key = (IMG_UINT64)(IMG_UINTPTR_T)pvCpuVAddr;
1475                         }
1476                         INCREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_VMALLOC, uiBytes);
1477                 }
1478                 break;
1479
1480                 case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_UMA:
1481                 {
1482                         if (psRecord != IMG_NULL)
1483                         {
1484                                 if (pvCpuVAddr == IMG_NULL)
1485                                 {
1486                                         return;
1487                                 }
1488                                 psRecord->ui64Key = (IMG_UINT64)(IMG_UINTPTR_T)pvCpuVAddr;
1489                         }
1490                         INCREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA, uiBytes);
1491                 }
1492                 break;
1493
1494                 case PVRSRV_MEM_ALLOC_TYPE_VMAP_PT_UMA:
1495                 {
1496                         if (psRecord != IMG_NULL)
1497                         {
1498                                 if (pvCpuVAddr == IMG_NULL)
1499                                 {
1500                                         return;
1501                                 }
1502                                 psRecord->ui64Key = (IMG_UINT64)(IMG_UINTPTR_T)pvCpuVAddr;
1503                         }
1504                         INCREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA, uiBytes);
1505                 }
1506                 break;
1507
1508                 case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA:
1509                 {
1510                         if (psRecord != IMG_NULL)
1511                         {
1512                                 psRecord->ui64Key = sCpuPAddr.uiAddr;
1513                         }
1514                         INCREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA, uiBytes);
1515                 }
1516                 break;
1517
1518                 case PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA:
1519                 {
1520                         if (psRecord != IMG_NULL)
1521                         {
1522                                 if (pvCpuVAddr == IMG_NULL)
1523                                 {
1524                                         return;
1525                                 }
1526                                 psRecord->ui64Key = (IMG_UINT64)(IMG_UINTPTR_T)pvCpuVAddr;
1527                         }
1528                         INCREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA, uiBytes);
1529                 }
1530                 break;
1531
1532                 case PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES:
1533                 {
1534                         if (psRecord != IMG_NULL)
1535                         {
1536                                 psRecord->ui64Key = sCpuPAddr.uiAddr;
1537                         }
1538                         INCREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_ALLOC_LMA_PAGES, uiBytes);
1539                 }
1540                 break;
1541
1542                 case PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES:
1543                 {
1544                         if (psRecord != IMG_NULL)
1545                         {
1546                                 psRecord->ui64Key = sCpuPAddr.uiAddr;
1547                         }
1548                         INCREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES, uiBytes);
1549                 }
1550                 break;
1551
1552                 case PVRSRV_MEM_ALLOC_TYPE_MAP_UMA_LMA_PAGES:
1553                 {
1554                         if (psRecord != IMG_NULL)
1555                         {
1556                                 if (pvCpuVAddr == IMG_NULL)
1557                                 {
1558                                         return;
1559                                 }
1560                                 psRecord->ui64Key = (IMG_UINT64)(IMG_UINTPTR_T)pvCpuVAddr;
1561                         }
1562                         INCREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES, uiBytes);
1563                 }
1564                 break;
1565
1566                 default:
1567                 {
1568                         PVR_ASSERT(0);
1569                 }
1570                 break;
1571         }
1572
1573 //Count total data
1574 psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_TOTAL_ALLOC] += psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_KMALLOC] +\
1575     psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMALLOC] + psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA] +\
1576     psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA] + PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES +\
1577     psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES] + psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES];
1578 UPDATE_MAX_VALUE(psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_TOTAL_ALLOC],
1579                                  psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_TOTAL_ALLOC]);
1580
1581 psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_TOTAL_MAP] += psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA] +\
1582     psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA];
1583 UPDATE_MAX_VALUE(psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_TOTAL_MAP],
1584                                  psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_TOTAL_MAP]);
1585
1586         OSLockRelease(psLinkedListLock);
1587 #else
1588 PVR_UNREFERENCED_PARAMETER(eAllocType);
1589 PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
1590 PVR_UNREFERENCED_PARAMETER(sCpuPAddr);
1591 PVR_UNREFERENCED_PARAMETER(uiBytes);
1592 PVR_UNREFERENCED_PARAMETER(pvPrivateData);
1593 #endif
1594 } /* PVRSRVStatsAddMemAllocRecord */
1595
1596
1597 IMG_VOID
1598 PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE eAllocType,
1599                                                                 IMG_UINT64 ui64Key)
1600 {
1601 #if defined(PVRSRV_ENABLE_MEMORY_STATS)
1602         IMG_PID                currentPid     = OSGetCurrentProcessID();
1603         IMG_PID                            currentCleanupPid = PVRSRVGetPurgeConnectionPid();
1604     PVRSRV_DATA*                   psPVRSRVData = PVRSRVGetPVRSRVData();
1605     PVRSRV_PROCESS_STATS*  psProcessStats = IMG_NULL;
1606         PVRSRV_MEMORY_STATS*   psMemoryStats  = IMG_NULL;
1607         PVRSRV_MEM_ALLOC_REC*  psRecord       = IMG_NULL;
1608     IMG_BOOL               bFound         = IMG_FALSE;
1609
1610     /* Don't do anything if we are not initialised or we are shutting down! */
1611     if (!bProcessStatsInitialised)
1612     {
1613                 return;
1614         }
1615
1616         /* Lock while we find the correct process and remove this record... */
1617         OSLockAcquire(psLinkedListLock);
1618
1619         if (psPVRSRVData)
1620         {
1621                 if ( (currentPid == psPVRSRVData->cleanupThreadPid) &&
1622                          (currentCleanupPid != 0))
1623                 {
1624                         psProcessStats = _FindProcessStats(currentCleanupPid);
1625                 }
1626             else
1627             {
1628                 psProcessStats = _FindProcessStats(currentPid);
1629             }
1630         }
1631     else
1632     {
1633         psProcessStats = _FindProcessStats(currentPid);
1634     }
1635     if (psProcessStats != IMG_NULL)
1636     {
1637                 psMemoryStats = psProcessStats->psMemoryStats;
1638                 psRecord      = psMemoryStats->psMemoryRecords;
1639                 while (psRecord != IMG_NULL)
1640                 {
1641                         if (psRecord->ui64Key == ui64Key  &&  psRecord->eAllocType == eAllocType)
1642                         {
1643                                 bFound = IMG_TRUE;
1644                                 break;
1645                         }
1646
1647                         psRecord = psRecord->psNext;
1648                 }
1649         }
1650
1651         /* If not found, we need to do a full search in case it was allocated to a different PID... */
1652         if (!bFound)
1653         {
1654                 PVRSRV_PROCESS_STATS*  psProcessStatsAlreadyChecked = psProcessStats;
1655
1656                 /* Search all live lists first... */
1657                 psProcessStats = psLiveList;
1658                 while (psProcessStats != IMG_NULL)
1659                 {
1660                         if (psProcessStats != psProcessStatsAlreadyChecked)
1661                         {
1662                                 psMemoryStats = psProcessStats->psMemoryStats;
1663                                 psRecord      = psMemoryStats->psMemoryRecords;
1664                                 while (psRecord != IMG_NULL)
1665                                 {
1666                                         if (psRecord->ui64Key == ui64Key  &&  psRecord->eAllocType == eAllocType)
1667                                         {
1668                                                 bFound = IMG_TRUE;
1669                                                 break;
1670                                         }
1671
1672                                         psRecord = psRecord->psNext;
1673                                 }
1674                         }
1675
1676                         if (bFound)
1677                         {
1678                                 break;
1679                         }
1680
1681                         psProcessStats = psProcessStats->psNext;
1682                 }
1683
1684                 /* If not found, then search all dead lists next... */
1685                 if (!bFound)
1686                 {
1687                         psProcessStats = psDeadList;
1688                         while (psProcessStats != IMG_NULL)
1689                         {
1690                                 if (psProcessStats != psProcessStatsAlreadyChecked)
1691                                 {
1692                                         psMemoryStats = psProcessStats->psMemoryStats;
1693                                         psRecord      = psMemoryStats->psMemoryRecords;
1694                                         while (psRecord != IMG_NULL)
1695                                         {
1696                                                 if (psRecord->ui64Key == ui64Key  &&  psRecord->eAllocType == eAllocType)
1697                                                 {
1698                                                         bFound = IMG_TRUE;
1699                                                         break;
1700                                                 }
1701
1702                                                 psRecord = psRecord->psNext;
1703                                         }
1704                                 }
1705
1706                                 if (bFound)
1707                                 {
1708                                         break;
1709                                 }
1710
1711                                 psProcessStats = psProcessStats->psNext;
1712                         }
1713                 }
1714         }
1715
1716         /* Update the watermark and remove this record...*/
1717         if (bFound)
1718         {
1719                 _decrease_global_stat(eAllocType, psRecord->uiBytes);
1720         
1721                 switch (eAllocType)
1722                 {
1723                         case PVRSRV_MEM_ALLOC_TYPE_KMALLOC:
1724                         {
1725                                 DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_KMALLOC, psRecord->uiBytes);
1726                         }
1727                         break;
1728
1729                         case PVRSRV_MEM_ALLOC_TYPE_VMALLOC:
1730                         {
1731                                 DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_VMALLOC, psRecord->uiBytes);
1732                         }
1733                         break;
1734
1735                         case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_UMA:
1736                         {
1737                                 DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA, psRecord->uiBytes);
1738                         }
1739                         break;
1740
1741                         case PVRSRV_MEM_ALLOC_TYPE_VMAP_PT_UMA:
1742                         {
1743                                 DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA, psRecord->uiBytes);
1744                         }
1745                         break;
1746
1747                         case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA:
1748                         {
1749                                 DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA, psRecord->uiBytes);
1750                         }
1751                         break;
1752
1753                         case PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA:
1754                         {
1755                                 DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA, psRecord->uiBytes);
1756                         }
1757                         break;
1758
1759                         case PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES:
1760                         {
1761                                 DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_ALLOC_LMA_PAGES, psRecord->uiBytes);
1762                         }
1763                         break;
1764
1765                         case PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES:
1766                         {
1767                                 DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES, psRecord->uiBytes);
1768                         }
1769                         break;
1770
1771                         case PVRSRV_MEM_ALLOC_TYPE_MAP_UMA_LMA_PAGES:
1772                         {
1773                                 DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES, psRecord->uiBytes);
1774                         }
1775                         break;
1776
1777                         default:
1778                         {
1779                                 PVR_ASSERT(0);
1780                         }
1781                         break;
1782                 }
1783
1784                 List_PVRSRV_MEM_ALLOC_REC_Remove(psRecord);
1785         }
1786 //Count total data
1787 psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_TOTAL_ALLOC] = psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_KMALLOC] +\
1788     psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMALLOC] + psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA] +\
1789     psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA] + PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES +\
1790     psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES] + psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES];
1791
1792 psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_TOTAL_MAP] = psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA] +\
1793     psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA];
1794
1795         OSLockRelease(psLinkedListLock);
1796
1797         /*
1798          * Free the record outside the lock so we don't deadlock and so we
1799          * reduce the time the lock is held.
1800          */
1801         if (psRecord != IMG_NULL)
1802         {
1803                 OSFreeMemstatMem(psRecord);
1804         }
1805 #else
1806 PVR_UNREFERENCED_PARAMETER(eAllocType);
1807 PVR_UNREFERENCED_PARAMETER(ui64Key);
1808 #endif
1809 } /* PVRSRVStatsRemoveMemAllocRecord */
1810
1811 IMG_VOID
1812 PVRSRVStatsIncrMemAllocStatAndTrack(PVRSRV_MEM_ALLOC_TYPE eAllocType,
1813                                                                 IMG_SIZE_T uiBytes,
1814                                                                 IMG_UINT64 uiCpuVAddr)
1815 {
1816         IMG_BOOL bRes;
1817
1818         if (!bProcessStatsInitialised || (gpsVmallocSizeHashTable == NULL) )
1819         {
1820                 return;
1821         }
1822
1823         OSLockAcquire(gpsVmallocSizeHashTableLock);
1824         bRes = HASH_Insert(gpsVmallocSizeHashTable, uiCpuVAddr, uiBytes);
1825         OSLockRelease(gpsVmallocSizeHashTableLock);
1826         if (bRes)
1827         {
1828                 PVRSRVStatsIncrMemAllocStat(eAllocType, uiBytes);
1829         }
1830         else
1831         {
1832                 PVR_DPF((PVR_DBG_ERROR, "*** %s : @ line %d HASH_Insert() failed!!", __FUNCTION__, __LINE__));
1833         }
1834 }
1835
1836 IMG_VOID
1837 PVRSRVStatsIncrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE eAllocType,
1838                                                                 IMG_SIZE_T uiBytes)
1839 {
1840         IMG_PID                currentPid = OSGetCurrentProcessID();
1841         IMG_PID                            currentCleanupPid = PVRSRVGetPurgeConnectionPid();
1842     PVRSRV_DATA*                   psPVRSRVData = PVRSRVGetPVRSRVData();
1843     PVRSRV_PROCESS_STATS*  psProcessStats;
1844
1845     /* Don't do anything if we are not initialised or we are shutting down! */
1846     if (!bProcessStatsInitialised)
1847     {
1848                 return;
1849         }
1850
1851         _increase_global_stat(eAllocType, uiBytes);
1852
1853         OSLockAcquire(psLinkedListLock);
1854
1855         if (psPVRSRVData)
1856         {
1857                 if ( (currentPid == psPVRSRVData->cleanupThreadPid) &&
1858                          (currentCleanupPid != 0))
1859                 {
1860                         psProcessStats = _FindProcessStats(currentCleanupPid);
1861                 }
1862             else
1863             {
1864                 psProcessStats = _FindProcessStats(currentPid);
1865             }
1866         }
1867     else
1868     {
1869         psProcessStats = _FindProcessStats(currentPid);
1870     }
1871
1872     if (psProcessStats != IMG_NULL)
1873     {
1874                 /* Update the memory watermarks... */
1875                 switch (eAllocType)
1876                 {
1877                         case PVRSRV_MEM_ALLOC_TYPE_KMALLOC:
1878                         {
1879                                 INCREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_KMALLOC, uiBytes);
1880                         }
1881                         break;
1882
1883                         case PVRSRV_MEM_ALLOC_TYPE_VMALLOC:
1884                         {
1885                                 INCREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_VMALLOC, uiBytes);
1886                         }
1887                         break;
1888
1889                         case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_UMA:
1890                         {
1891                                 INCREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA, uiBytes);
1892                         }
1893                         break;
1894
1895                         case PVRSRV_MEM_ALLOC_TYPE_VMAP_PT_UMA:
1896                         {
1897                                 INCREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA, uiBytes);
1898                         }
1899                         break;
1900
1901                         case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA:
1902                         {
1903                                 INCREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA, uiBytes);
1904                         }
1905                         break;
1906
1907                         case PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA:
1908                         {
1909                                 INCREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA, uiBytes);
1910                         }
1911                         break;
1912
1913                         case PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES:
1914                         {
1915                                 INCREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_ALLOC_LMA_PAGES, uiBytes);
1916                         }
1917                         break;
1918
1919                         case PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES:
1920                         {
1921                                 INCREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES, uiBytes);
1922                         }
1923                         break;
1924
1925                         case PVRSRV_MEM_ALLOC_TYPE_MAP_UMA_LMA_PAGES:
1926                         {
1927                                 INCREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES, uiBytes);
1928                         }
1929                         break;
1930
1931                         default:
1932                         {
1933                                 PVR_ASSERT(0);
1934                         }
1935                         break;
1936                 }
1937         //Count total data
1938         psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_TOTAL_ALLOC] = psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_KMALLOC] +\
1939             psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMALLOC] + psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA] +\
1940             psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA] + PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES +\
1941             psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES] + psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES];
1942         UPDATE_MAX_VALUE(psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_TOTAL_ALLOC],
1943                         psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_TOTAL_ALLOC]);
1944
1945         psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_TOTAL_MAP] = psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA] +\
1946             psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA];
1947         UPDATE_MAX_VALUE(psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAX_TOTAL_MAP],
1948                         psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_TOTAL_MAP]);
1949     }
1950
1951         OSLockRelease(psLinkedListLock);
1952 }
1953
1954 IMG_VOID
1955 PVRSRVStatsDecrMemAllocStatAndUntrack(PVRSRV_MEM_ALLOC_TYPE eAllocType,
1956                                       IMG_UINT64 uiCpuVAddr)
1957 {
1958         IMG_SIZE_T uiBytes;
1959
1960         if (!bProcessStatsInitialised || (gpsVmallocSizeHashTable == NULL) )
1961         {
1962                 return;
1963         }
1964
1965         OSLockAcquire(gpsVmallocSizeHashTableLock);
1966         uiBytes = HASH_Remove(gpsVmallocSizeHashTable, uiCpuVAddr);
1967         OSLockRelease(gpsVmallocSizeHashTableLock);
1968
1969         PVRSRVStatsDecrMemAllocStat(eAllocType, uiBytes);
1970 }
1971
1972 IMG_VOID
1973 PVRSRVStatsDecrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE eAllocType,
1974                             IMG_SIZE_T uiBytes)
1975 {
1976         IMG_PID                currentPid = OSGetCurrentProcessID();
1977         IMG_PID                            currentCleanupPid = PVRSRVGetPurgeConnectionPid();
1978     PVRSRV_DATA*                   psPVRSRVData = PVRSRVGetPVRSRVData();
1979     PVRSRV_PROCESS_STATS*  psProcessStats;
1980
1981     /* Don't do anything if we are not initialised or we are shutting down! */
1982     if (!bProcessStatsInitialised)
1983     {
1984                 return;
1985         }
1986
1987         _decrease_global_stat(eAllocType, uiBytes);
1988
1989         OSLockAcquire(psLinkedListLock);
1990
1991         if (psPVRSRVData)
1992         {
1993                 if ( (currentPid == psPVRSRVData->cleanupThreadPid) &&
1994                          (currentCleanupPid != 0))
1995                 {
1996                         psProcessStats = _FindProcessStats(currentCleanupPid);
1997                 }
1998             else
1999             {
2000                 psProcessStats = _FindProcessStats(currentPid);
2001                 }
2002         }
2003     else
2004     {
2005         psProcessStats = _FindProcessStats(currentPid);
2006         }
2007     if (psProcessStats != IMG_NULL)
2008     {
2009                 /* Update the memory watermarks... */
2010                 switch (eAllocType)
2011                 {
2012                         case PVRSRV_MEM_ALLOC_TYPE_KMALLOC:
2013                         {
2014                                 DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_KMALLOC, uiBytes);
2015                         }
2016                         break;
2017
2018                         case PVRSRV_MEM_ALLOC_TYPE_VMALLOC:
2019                         {
2020                                 DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_VMALLOC, uiBytes);
2021                         }
2022                         break;
2023
2024                         case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_UMA:
2025                         {
2026                                 DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA, uiBytes);
2027                         }
2028                         break;
2029
2030                         case PVRSRV_MEM_ALLOC_TYPE_VMAP_PT_UMA:
2031                         {
2032                                 DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA, uiBytes);
2033                         }
2034                         break;
2035
2036                         case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA:
2037                         {
2038                                 DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA, uiBytes);
2039                         }
2040                         break;
2041
2042                         case PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA:
2043                         {
2044                                 DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA, uiBytes);
2045                         }
2046                         break;
2047
2048                         case PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES:
2049                         {
2050                                 DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_ALLOC_LMA_PAGES, uiBytes);
2051                         }
2052                         break;
2053
2054                         case PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES:
2055                         {
2056                                 DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES, uiBytes);
2057                         }
2058                         break;
2059
2060                         case PVRSRV_MEM_ALLOC_TYPE_MAP_UMA_LMA_PAGES:
2061                         {
2062                                 DECREASE_STAT_VALUE(psProcessStats, PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES, uiBytes);
2063                         }
2064                         break;
2065
2066                         default:
2067                         {
2068                                 PVR_ASSERT(0);
2069                         }
2070                         break;
2071                 }
2072                 //Count total data
2073         psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_TOTAL_ALLOC] = psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_KMALLOC] +\
2074             psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMALLOC] + psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA] +\
2075             psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA] + PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES +\
2076             psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES] + psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_MAP_UMA_LMA_PAGES];
2077
2078         psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_TOTAL_MAP] = psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_VMAP_PT_UMA] +\
2079             psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_IOREMAP_PT_LMA];
2080         }
2081
2082         OSLockRelease(psLinkedListLock);
2083 }
2084
2085 /* For now we do not want to expose the global stats API
2086  * so we wrap it into this specific function for pooled pages.
2087  * As soon as we need to modify the global stats directly somewhere else
2088  * we want to replace these functions with more general ones.
2089  */
2090 IMG_VOID
2091 PVRSRVStatsIncrMemAllocPoolStat(IMG_SIZE_T uiBytes)
2092 {
2093         _increase_global_stat(PVRSRV_MEM_ALLOC_TYPE_UMA_POOL_PAGES, uiBytes);
2094 }
2095
2096 IMG_VOID
2097 PVRSRVStatsDecrMemAllocPoolStat(IMG_SIZE_T uiBytes)
2098 {
2099         _decrease_global_stat(PVRSRV_MEM_ALLOC_TYPE_UMA_POOL_PAGES, uiBytes);
2100 }
2101
2102 IMG_VOID
2103 PVRSRVStatsUpdateRenderContextStats(IMG_UINT32 ui32TotalNumPartialRenders,
2104                                     IMG_UINT32 ui32TotalNumOutOfMemory,
2105                                     IMG_UINT32 ui32NumTAStores,
2106                                     IMG_UINT32 ui32Num3DStores,
2107                                     IMG_UINT32 ui32NumSHStores,
2108                                     IMG_UINT32 ui32NumCDMStores,
2109                                     IMG_PID pidOwner)
2110 {
2111         //IMG_PID                currentPid = OSGetCurrentProcessID();
2112         IMG_PID pidCurrent=pidOwner;
2113
2114     PVRSRV_PROCESS_STATS*  psProcessStats;
2115
2116     /* Don't do anything if we are not initialised or we are shutting down! */
2117     if (!bProcessStatsInitialised)
2118     {
2119                 return;
2120         }
2121
2122         /* Lock while we find the correct process and update the record... */
2123         OSLockAcquire(psLinkedListLock);
2124
2125     psProcessStats = _FindProcessStats(pidCurrent);
2126     if (psProcessStats != IMG_NULL)
2127     {
2128                 psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_RC_PRS]       += ui32TotalNumPartialRenders;
2129                 psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_RC_OOMS]      += ui32TotalNumOutOfMemory;
2130                 psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_RC_TA_STORES] += ui32NumTAStores;
2131                 psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_RC_3D_STORES] += ui32Num3DStores;
2132                 psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_RC_SH_STORES] += ui32NumSHStores;
2133                 psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_RC_CDM_STORES]+= ui32NumCDMStores;
2134         }
2135     else
2136     {
2137         PVR_DPF((PVR_DBG_WARNING, "PVRSRVStatsUpdateRenderContextStats: Null process. Pid=%d", pidCurrent));
2138     }
2139
2140         OSLockRelease(psLinkedListLock);
2141 } /* PVRSRVStatsUpdateRenderContextStats */
2142
2143
2144 IMG_VOID
2145 PVRSRVStatsUpdateZSBufferStats(IMG_UINT32 ui32NumReqByApp,
2146                                IMG_UINT32 ui32NumReqByFW,
2147                                IMG_PID owner)
2148 {
2149         IMG_PID                currentPid = (owner==0)?OSGetCurrentProcessID():owner;
2150     PVRSRV_PROCESS_STATS*  psProcessStats;
2151
2152
2153     /* Don't do anything if we are not initialised or we are shutting down! */
2154     if (!bProcessStatsInitialised)
2155     {
2156                 return;
2157         }
2158
2159         /* Lock while we find the correct process and update the record... */
2160         OSLockAcquire(psLinkedListLock);
2161
2162     psProcessStats = _FindProcessStats(currentPid);
2163     if (psProcessStats != IMG_NULL)
2164     {
2165                 psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ZSBUFFER_REQS_BY_APP] += ui32NumReqByApp;
2166                 psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ZSBUFFER_REQS_BY_FW]  += ui32NumReqByFW;
2167         }
2168
2169         OSLockRelease(psLinkedListLock);
2170 } /* PVRSRVStatsUpdateZSBufferStats */
2171
2172
2173 IMG_VOID
2174 PVRSRVStatsUpdateFreelistStats(IMG_UINT32 ui32NumGrowReqByApp,
2175                                IMG_UINT32 ui32NumGrowReqByFW,
2176                                IMG_UINT32 ui32InitFLPages,
2177                                IMG_UINT32 ui32NumHighPages,
2178                                IMG_PID ownerPid)
2179 {
2180         IMG_PID                currentPid = (ownerPid!=0)?ownerPid:OSGetCurrentProcessID();
2181     PVRSRV_PROCESS_STATS*  psProcessStats;
2182
2183     /* Don't do anything if we are not initialised or we are shutting down! */
2184     if (!bProcessStatsInitialised)
2185     {
2186                 return;
2187         }
2188
2189         /* Lock while we find the correct process and update the record... */
2190         OSLockAcquire(psLinkedListLock);
2191
2192         psProcessStats = _FindProcessStats(currentPid);
2193
2194     if (psProcessStats != IMG_NULL)
2195     {
2196                 /* Avoid signed / unsigned mismatch which is flagged by some compilers */
2197                 IMG_INT32 a, b;
2198
2199                 psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_FREELIST_GROW_REQS_BY_APP] += ui32NumGrowReqByApp;
2200                 psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_FREELIST_GROW_REQS_BY_FW]  += ui32NumGrowReqByFW;
2201
2202                 a=psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_FREELIST_PAGES_INIT];
2203                 b=(IMG_INT32)(ui32InitFLPages);
2204                 UPDATE_MAX_VALUE(a, b);
2205
2206
2207                 psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_FREELIST_PAGES_INIT]=a;
2208                 ui32InitFLPages=(IMG_UINT32)b;
2209
2210                 a=psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_FREELIST_MAX_PAGES];
2211                 b=(IMG_INT32)ui32NumHighPages;
2212
2213                 UPDATE_MAX_VALUE(a, b);
2214                 psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_FREELIST_PAGES_INIT]=a;
2215                 ui32InitFLPages=(IMG_UINT32)b;
2216
2217         }
2218
2219         OSLockRelease(psLinkedListLock);
2220 } /* PVRSRVStatsUpdateFreelistStats */
2221
2222
2223 /*************************************************************************/ /*!
2224 @Function       ProcessStatsPrintElements
2225 @Description    Prints all elements for this process statistic record.
2226 @Input          pvFilePtr         Pointer to seq_file.
2227 @Input          pvStatPtr         Pointer to statistics structure.
2228 @Input          pfnOSStatsPrintf  Printf function to use for output.
2229 */ /**************************************************************************/
2230 IMG_VOID
2231 ProcessStatsPrintElements(IMG_PVOID pvFilePtr,
2232                                                   IMG_PVOID pvStatPtr,
2233                           OS_STATS_PRINTF_FUNC* pfnOSStatsPrintf)
2234 {
2235         PVRSRV_STAT_STRUCTURE_TYPE*  peStructureType = (PVRSRV_STAT_STRUCTURE_TYPE*) pvStatPtr;
2236         PVRSRV_PROCESS_STATS*        psProcessStats  = (PVRSRV_PROCESS_STATS*) pvStatPtr;
2237         IMG_UINT32                   ui32StatNumber = 0;
2238
2239         if (peStructureType == IMG_NULL  ||  *peStructureType != PVRSRV_STAT_STRUCTURE_PROCESS)
2240         {
2241                 PVR_ASSERT(peStructureType != IMG_NULL  &&  *peStructureType == PVRSRV_STAT_STRUCTURE_PROCESS);
2242                 return;
2243         }
2244
2245         if (pfnOSStatsPrintf == NULL)
2246         {
2247                 return;
2248         }
2249
2250         /* Loop through all the values and print them... */
2251     while (ui32StatNumber < PVRSRV_PROCESS_STAT_TYPE_COUNT)
2252     {
2253         if (psProcessStats->ui32MemRefCount > 0)
2254         {
2255             pfnOSStatsPrintf(pvFilePtr, pszProcessStatFmt[ui32StatNumber], psProcessStats->i32StatValue[ui32StatNumber]);
2256         }
2257         else
2258         {
2259             PVR_DPF((PVR_DBG_ERROR, "%s: Called with psProcessStats->ui32MemRefCount=%d", __FUNCTION__, psProcessStats->ui32MemRefCount));
2260         }
2261         ui32StatNumber++;
2262     }
2263 } /* ProcessStatsPrintElements */
2264
2265
2266 #if defined(PVRSRV_ENABLE_MEMORY_STATS)
2267 /*************************************************************************/ /*!
2268 @Function       MemStatsPrintElements
2269 @Description    Prints all elements for the memory statistic record.
2270 @Input          pvFilePtr         Pointer to seq_file.
2271 @Input          pvStatPtr         Pointer to statistics structure.
2272 @Input          pfnOSStatsPrintf  Printf function to use for output.
2273 */ /**************************************************************************/
2274 IMG_VOID
2275 MemStatsPrintElements(IMG_PVOID pvFilePtr,
2276                                           IMG_PVOID pvStatPtr,
2277                       OS_STATS_PRINTF_FUNC* pfnOSStatsPrintf)
2278 {
2279         PVRSRV_STAT_STRUCTURE_TYPE*  peStructureType = (PVRSRV_STAT_STRUCTURE_TYPE*) pvStatPtr;
2280         PVRSRV_MEMORY_STATS*         psMemoryStats   = (PVRSRV_MEMORY_STATS*) pvStatPtr;
2281         IMG_UINT32      ui32VAddrFields = sizeof(IMG_VOID*)/sizeof(IMG_UINT32);
2282         IMG_UINT32      ui32PAddrFields = sizeof(IMG_CPU_PHYADDR)/sizeof(IMG_UINT32);
2283         PVRSRV_MEM_ALLOC_REC  *psRecord;
2284         IMG_UINT32  ui32ItemNumber;
2285
2286         if (peStructureType == IMG_NULL  ||  *peStructureType != PVRSRV_STAT_STRUCTURE_MEMORY)
2287         {
2288                 PVR_ASSERT(peStructureType != IMG_NULL  &&  *peStructureType == PVRSRV_STAT_STRUCTURE_MEMORY);
2289                 return;
2290         }
2291
2292         if (pfnOSStatsPrintf == NULL)
2293         {
2294                 return;
2295         }
2296
2297         /* Write the header... */
2298     pfnOSStatsPrintf(pvFilePtr, "Type                VAddress");
2299         for (ui32ItemNumber = 1;  ui32ItemNumber < ui32VAddrFields;  ui32ItemNumber++)
2300         {
2301         pfnOSStatsPrintf(pvFilePtr, "        ");
2302         }
2303
2304     pfnOSStatsPrintf(pvFilePtr, "  PAddress");
2305         for (ui32ItemNumber = 1;  ui32ItemNumber < ui32PAddrFields;  ui32ItemNumber++)
2306         {
2307         pfnOSStatsPrintf(pvFilePtr, "        ");
2308         }
2309
2310     pfnOSStatsPrintf(pvFilePtr, "  Size(bytes)\n");
2311
2312         /* The lock has to be held whilst moving through the memory list... */
2313         OSLockAcquire(psLinkedListLock);
2314         psRecord = psMemoryStats->psMemoryRecords;
2315
2316         while (psRecord != IMG_NULL)
2317         {
2318                 switch (psRecord->eAllocType)
2319                 {
2320             case PVRSRV_MEM_ALLOC_TYPE_KMALLOC:                 pfnOSStatsPrintf(pvFilePtr, "KMALLOC             "); break;
2321             case PVRSRV_MEM_ALLOC_TYPE_VMALLOC:                 pfnOSStatsPrintf(pvFilePtr, "VMALLOC             "); break;
2322             case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA:  pfnOSStatsPrintf(pvFilePtr, "ALLOC_PAGES_PT_LMA  "); break;
2323             case PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_UMA:  pfnOSStatsPrintf(pvFilePtr, "ALLOC_PAGES_PT_UMA  "); break;
2324             case PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA:      pfnOSStatsPrintf(pvFilePtr, "IOREMAP_PT_LMA      "); break;
2325             case PVRSRV_MEM_ALLOC_TYPE_VMAP_PT_UMA:         pfnOSStatsPrintf(pvFilePtr, "VMAP_PT_UMA         "); break;
2326             case PVRSRV_MEM_ALLOC_TYPE_ALLOC_LMA_PAGES:         pfnOSStatsPrintf(pvFilePtr, "ALLOC_LMA_PAGES     "); break;
2327             case PVRSRV_MEM_ALLOC_TYPE_ALLOC_UMA_PAGES:         pfnOSStatsPrintf(pvFilePtr, "ALLOC_UMA_PAGES     "); break;
2328             case PVRSRV_MEM_ALLOC_TYPE_MAP_UMA_LMA_PAGES:       pfnOSStatsPrintf(pvFilePtr, "MAP_UMA_LMA_PAGES   "); break;
2329             default:                                            pfnOSStatsPrintf(pvFilePtr, "INVALID             "); break;
2330                 }
2331
2332                 for (ui32ItemNumber = 0;  ui32ItemNumber < ui32VAddrFields;  ui32ItemNumber++)
2333                 {
2334             pfnOSStatsPrintf(pvFilePtr, "%08x", *(((IMG_UINT32*) &psRecord->pvCpuVAddr) + ui32VAddrFields - ui32ItemNumber - 1));
2335                 }
2336         pfnOSStatsPrintf(pvFilePtr, "  ");
2337
2338                 for (ui32ItemNumber = 0;  ui32ItemNumber < ui32PAddrFields;  ui32ItemNumber++)
2339                 {
2340             pfnOSStatsPrintf(pvFilePtr, "%08x", *(((IMG_UINT32*) &psRecord->sCpuPAddr.uiAddr) + ui32PAddrFields - ui32ItemNumber - 1));
2341                 }
2342
2343         pfnOSStatsPrintf(pvFilePtr, "  %u\n", psRecord->uiBytes);
2344
2345                 /* Move to next record... */
2346                 psRecord = psRecord->psNext;
2347         }
2348
2349         OSLockRelease(psLinkedListLock);
2350 } /* MemStatsPrintElements */
2351 #endif
2352
2353
2354 #if defined(PVR_RI_DEBUG)
2355 /*************************************************************************/ /*!
2356 @Function       RIMemStatsPrintElements
2357 @Description    Prints all elements for the RI Memory record.
2358 @Input          pvFilePtr         Pointer to seq_file.
2359 @Input          pvStatPtr         Pointer to statistics structure.
2360 @Input          pfnOSStatsPrintf  Printf function to use for output.
2361 */ /**************************************************************************/
2362 IMG_VOID
2363 RIMemStatsPrintElements(IMG_PVOID pvFilePtr,
2364                                                 IMG_PVOID pvStatPtr,
2365                         OS_STATS_PRINTF_FUNC* pfnOSStatsPrintf)
2366 {
2367         PVRSRV_STAT_STRUCTURE_TYPE  *peStructureType = (PVRSRV_STAT_STRUCTURE_TYPE*) pvStatPtr;
2368         PVRSRV_RI_MEMORY_STATS      *psRIMemoryStats = (PVRSRV_RI_MEMORY_STATS*) pvStatPtr;
2369         IMG_CHAR                    *pszStatFmtText  = IMG_NULL;
2370         IMG_HANDLE                  *pRIHandle       = IMG_NULL;
2371
2372         if (peStructureType == IMG_NULL  ||  *peStructureType != PVRSRV_STAT_STRUCTURE_RIMEMORY)
2373         {
2374                 PVR_ASSERT(peStructureType != IMG_NULL  &&  *peStructureType == PVRSRV_STAT_STRUCTURE_RIMEMORY);
2375                 return;
2376         }
2377
2378         if (pfnOSStatsPrintf == NULL)
2379         {
2380                 return;
2381         }
2382
2383         /*
2384          *  Loop through the RI system to get each line of text.
2385          */
2386         while (RIGetListEntryKM(psRIMemoryStats->pid,
2387                                                         &pRIHandle,
2388                                                         &pszStatFmtText))
2389         {
2390         pfnOSStatsPrintf(pvFilePtr, "%s", pszStatFmtText);
2391         }
2392 } /* RIMemStatsPrintElements */
2393 #endif
2394
2395
2396 static IMG_UINT32       ui32FirmwareStartTimestamp=0;
2397 static IMG_UINT64       ui64FirmwareIdleDuration=0;
2398
2399 /* Averaging each new value with the previous accumulated knowledge. There are many coefficients for that
2400  * (e.g.) 50 / 50 but i chose 75 / 25 meaning that previous knowledge affects the weighted average more
2401  * than any new knowledge. As time goes by though eventually the number converges to the most commonly used
2402  */
2403
2404 IMG_VOID SetFirmwareStartTime(IMG_UINT32 ui32Time)
2405 {
2406     if (ui32FirmwareStartTimestamp > 0)
2407     {
2408         ui32FirmwareStartTimestamp = MEAN_TIME(ui32FirmwareStartTimestamp, ui32Time);
2409     }
2410     else
2411     {
2412         ui32FirmwareStartTimestamp = ui32Time;
2413     }
2414 }
2415
2416 IMG_VOID SetFirmwareHandshakeIdleTime(IMG_UINT64 ui64Duration)
2417 {
2418     if (ui64FirmwareIdleDuration > 0)
2419         {
2420         ui64FirmwareIdleDuration = MEAN_TIME(ui64FirmwareIdleDuration, ui64Duration);
2421         }
2422         else
2423         {
2424                 ui64FirmwareIdleDuration = ui64Duration;
2425         }
2426 }
2427
2428
2429 IMG_VOID PowerStatsPrintElements(IMG_PVOID pvFilePtr,
2430                                  IMG_PVOID pvStatPtr,
2431                                  OS_STATS_PRINTF_FUNC* pfnOSStatsPrintf)
2432 {
2433         IMG_UINT32                      ui32Idx;
2434
2435         PVR_UNREFERENCED_PARAMETER(pvStatPtr);
2436
2437         if (pfnOSStatsPrintf == NULL)
2438         {
2439                 return;
2440         }
2441
2442         if (ui64TotalForcedEntries > 0)
2443         {
2444         pfnOSStatsPrintf(pvFilePtr, "Forced Power Transition (nanoseconds):\n");
2445         pfnOSStatsPrintf(pvFilePtr, "Pre-Device:  %u\n", (IMG_UINT32)(ui64ForcedPreDevice)  / (IMG_UINT32)(ui64TotalForcedEntries));
2446         pfnOSStatsPrintf(pvFilePtr, "Pre-System:  %u\n", (IMG_UINT32)(ui64ForcedPreSystem)  / (IMG_UINT32)(ui64TotalForcedEntries));
2447         pfnOSStatsPrintf(pvFilePtr, "Post-Device: %u\n", (IMG_UINT32)(ui64ForcedPostDevice) / (IMG_UINT32)(ui64TotalForcedEntries));
2448         pfnOSStatsPrintf(pvFilePtr, "Post-System: %u\n", (IMG_UINT32)(ui64ForcedPostSystem) / (IMG_UINT32)(ui64TotalForcedEntries));
2449         pfnOSStatsPrintf(pvFilePtr, "\n");
2450         }
2451
2452         if (ui64TotalNotForcedEntries > 0)
2453         {
2454         pfnOSStatsPrintf(pvFilePtr, "Not Forced Power Transition (nanoseconds):\n");
2455         pfnOSStatsPrintf(pvFilePtr, "Pre-Device:  %u\n", (IMG_UINT32)(ui64NotForcedPreDevice)  / (IMG_UINT32)(ui64TotalNotForcedEntries));
2456         pfnOSStatsPrintf(pvFilePtr, "Pre-System:  %u\n", (IMG_UINT32)(ui64NotForcedPreSystem)  / (IMG_UINT32)(ui64TotalNotForcedEntries));
2457         pfnOSStatsPrintf(pvFilePtr, "Post-Device: %u\n", (IMG_UINT32)(ui64NotForcedPostDevice) / (IMG_UINT32)(ui64TotalNotForcedEntries));
2458         pfnOSStatsPrintf(pvFilePtr, "Post-System: %u\n", (IMG_UINT32)(ui64NotForcedPostSystem) / (IMG_UINT32)(ui64TotalNotForcedEntries));
2459         pfnOSStatsPrintf(pvFilePtr, "\n");
2460         }
2461
2462     pfnOSStatsPrintf(pvFilePtr, "FW bootup time (timer ticks): %u\n", ui32FirmwareStartTimestamp);
2463     pfnOSStatsPrintf(pvFilePtr, "Host Acknowledge Time for FW Idle Signal (timer ticks): %u\n", (IMG_UINT32)(ui64FirmwareIdleDuration));
2464     pfnOSStatsPrintf(pvFilePtr, "\n");
2465
2466     pfnOSStatsPrintf(pvFilePtr, "Last %d Clock Speed Change Timers (nanoseconds):\n", NUM_EXTRA_POWER_STATS);
2467     pfnOSStatsPrintf(pvFilePtr, "Prepare DVFS\tDVFS Change\tPost DVFS\n");
2468
2469         for (ui32Idx = ui32ClockSpeedIndexStart; ui32Idx !=ui32ClockSpeedIndexEnd; ui32Idx = (ui32Idx + 1) % NUM_EXTRA_POWER_STATS)
2470         {
2471         pfnOSStatsPrintf(pvFilePtr, "%12llu\t%11llu\t%9llu\n",asClockSpeedChanges[ui32Idx].ui64PreClockSpeedChangeDuration,
2472                                                                                                  asClockSpeedChanges[ui32Idx].ui64BetweenPreEndingAndPostStartingDuration,
2473                                                                                                  asClockSpeedChanges[ui32Idx].ui64PostClockSpeedChangeDuration);
2474         }
2475
2476
2477 } /* PowerStatsPrintElements */
2478
2479
2480 IMG_VOID GlobalStatsPrintElements(IMG_PVOID pvFilePtr,
2481                                   IMG_PVOID pvStatPtr,
2482                                   OS_STATS_PRINTF_FUNC* pfnOSGetStatsPrintf)
2483 {
2484         PVR_UNREFERENCED_PARAMETER(pvStatPtr);
2485
2486         if (pfnOSGetStatsPrintf != IMG_NULL)
2487         {
2488         pfnOSGetStatsPrintf(pvFilePtr, "MemoryUsageKMalloc                %10d\n", gsGlobalStats.ui32MemoryUsageKMalloc);
2489         pfnOSGetStatsPrintf(pvFilePtr, "MemoryUsageKMallocMax             %10d\n", gsGlobalStats.ui32MemoryUsageKMallocMax);
2490         pfnOSGetStatsPrintf(pvFilePtr, "MemoryUsageVMalloc                %10d\n", gsGlobalStats.ui32MemoryUsageVMalloc);
2491         pfnOSGetStatsPrintf(pvFilePtr, "MemoryUsageVMallocMax             %10d\n", gsGlobalStats.ui32MemoryUsageVMallocMax);
2492         pfnOSGetStatsPrintf(pvFilePtr, "MemoryUsageAllocPTMemoryUMA       %10d\n", gsGlobalStats.ui32MemoryUsageAllocPTMemoryUMA);
2493         pfnOSGetStatsPrintf(pvFilePtr, "MemoryUsageAllocPTMemoryUMAMax    %10d\n", gsGlobalStats.ui32MemoryUsageAllocPTMemoryUMAMax);
2494         pfnOSGetStatsPrintf(pvFilePtr, "MemoryUsageVMapPTUMA              %10d\n", gsGlobalStats.ui32MemoryUsageVMapPTUMA);
2495         pfnOSGetStatsPrintf(pvFilePtr, "MemoryUsageVMapPTUMAMax           %10d\n", gsGlobalStats.ui32MemoryUsageVMapPTUMAMax);
2496         pfnOSGetStatsPrintf(pvFilePtr, "MemoryUsageAllocPTMemoryLMA       %10d\n", gsGlobalStats.ui32MemoryUsageAllocPTMemoryLMA);
2497         pfnOSGetStatsPrintf(pvFilePtr, "MemoryUsageAllocPTMemoryLMAMax    %10d\n", gsGlobalStats.ui32MemoryUsageAllocPTMemoryLMAMax);
2498         pfnOSGetStatsPrintf(pvFilePtr, "MemoryUsageIORemapPTLMA           %10d\n", gsGlobalStats.ui32MemoryUsageIORemapPTLMA);
2499         pfnOSGetStatsPrintf(pvFilePtr, "MemoryUsageIORemapPTLMAMax        %10d\n", gsGlobalStats.ui32MemoryUsageIORemapPTLMAMax);
2500         pfnOSGetStatsPrintf(pvFilePtr, "MemoryUsageAllocGPUMemLMA         %10d\n", gsGlobalStats.ui32MemoryUsageAllocGPUMemLMA);
2501         pfnOSGetStatsPrintf(pvFilePtr, "MemoryUsageAllocGPUMemLMAMax      %10d\n", gsGlobalStats.ui32MemoryUsageAllocGPUMemLMAMax);
2502         pfnOSGetStatsPrintf(pvFilePtr, "MemoryUsageAllocGPUMemUMA         %10d\n", gsGlobalStats.ui32MemoryUsageAllocGPUMemUMA);
2503         pfnOSGetStatsPrintf(pvFilePtr, "MemoryUsageAllocGPUMemUMAMax      %10d\n", gsGlobalStats.ui32MemoryUsageAllocGPUMemUMAMax);
2504         pfnOSGetStatsPrintf(pvFilePtr, "MemoryUsageAllocGPUMemUMAPool     %10d\n", gsGlobalStats.ui32MemoryUsageAllocGPUMemUMAPool);
2505         pfnOSGetStatsPrintf(pvFilePtr, "MemoryUsageAllocGPUMemUMAPoolMax  %10d\n", gsGlobalStats.ui32MemoryUsageAllocGPUMemUMAPoolMax);
2506         pfnOSGetStatsPrintf(pvFilePtr, "MemoryUsageMappedGPUMemUMA/LMA    %10d\n", gsGlobalStats.ui32MemoryUsageMappedGPUMemUMA_LMA);
2507         pfnOSGetStatsPrintf(pvFilePtr, "MemoryUsageMappedGPUMemUMA/LMAMax %10d\n", gsGlobalStats.ui32MemoryUsageMappedGPUMemUMA_LMAMax);
2508
2509                 //zxl: count total data 
2510                 pfnOSGetStatsPrintf(pvFilePtr, "MemoryUsageTotalAlloc             %10d\n",gsGlobalStats.ui32MemoryUsageTotalAlloc);
2511                 pfnOSGetStatsPrintf(pvFilePtr, "MemoryUsageTotalAllocMax          %10d\n",gsGlobalStats.ui32MemoryUsageTotalAllocMax);
2512                 pfnOSGetStatsPrintf(pvFilePtr, "MemoryUsageTotalMap               %10d\n",gsGlobalStats.ui32MemoryUsageTotalMap);
2513                 pfnOSGetStatsPrintf(pvFilePtr, "ui32MemoryUsageTotalMapMax        %10d\n",gsGlobalStats.ui32MemoryUsageTotalMapMax);
2514         }
2515 }