RK3368 GPU version Rogue M 1.28
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / rogue_m / services / server / common / devicemem_history_server.c
1 /*************************************************************************/ /*!
2 @File
3 @Title          Devicemem history functions
4 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
5 @Description    Devicemem history functions
6 @License        Dual MIT/GPLv2
7
8 The contents of this file are subject to the MIT license as set out below.
9
10 Permission is hereby granted, free of charge, to any person obtaining a copy
11 of this software and associated documentation files (the "Software"), to deal
12 in the Software without restriction, including without limitation the rights
13 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 copies of the Software, and to permit persons to whom the Software is
15 furnished to do so, subject to the following conditions:
16
17 The above copyright notice and this permission notice shall be included in
18 all copies or substantial portions of the Software.
19
20 Alternatively, the contents of this file may be used under the terms of
21 the GNU General Public License Version 2 ("GPL") in which case the provisions
22 of GPL are applicable instead of those above.
23
24 If you wish to allow use of your version of this file only under the terms of
25 GPL, and not to allow others to use your version of this file under the terms
26 of the MIT license, indicate your decision by deleting the provisions above
27 and replace them with the notice and other provisions required by GPL as set
28 out in the file called "GPL-COPYING" included in this distribution. If you do
29 not delete the provisions above, a recipient may use your version of this file
30 under the terms of either the MIT license or GPL.
31
32 This License is also included in this distribution in the file called
33 "MIT-COPYING".
34
35 EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
36 PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
37 BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
38 PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
39 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
40 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
41 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
42 */ /**************************************************************************/
43
44 #include "allocmem.h"
45 #include "pmr.h"
46 #include "pvrsrv.h"
47 #include "pvrsrv_device.h"
48 #include "pvr_debug.h"
49 #include "dllist.h"
50 #include "syscommon.h"
51 #include "devicemem_server.h"
52 #include "lock.h"
53 #include "devicemem_history_server.h"
54
55 /* a device memory allocation */
56 typedef struct _DEVICEMEM_HISTORY_ALLOCATION_
57 {
58         IMG_DEV_VIRTADDR sDevVAddr;
59         IMG_DEVMEM_SIZE_T uiSize;
60         IMG_CHAR szString[DEVICEMEM_HISTORY_TEXT_BUFSZ];
61         IMG_UINT64 ui64Time;
62         /* FALSE if this allocation has been freed */
63         IMG_BOOL bAllocated;
64         IMG_PID uiPID;
65 } DEVICEMEM_HISTORY_ALLOCATION;
66
67 /* this number of entries makes the history buffer allocation just under 2MB */
68 #define DEVICEMEM_HISTORY_ALLOCATION_HISTORY_LEN 29127
69
70 typedef struct _DEVICEMEM_HISTORY_DATA_
71 {
72         IMG_UINT32 ui32Head;
73         DEVICEMEM_HISTORY_ALLOCATION *psAllocations;
74         POS_LOCK hLock;
75 } DEVICEMEM_HISTORY_DATA;
76
77 static DEVICEMEM_HISTORY_DATA gsDevicememHistoryData = { 0 };
78
79 static INLINE IMG_VOID DevicememHistoryLock(IMG_VOID)
80 {
81         OSLockAcquire(gsDevicememHistoryData.hLock);
82 }
83
84 static INLINE IMG_VOID DevicememHistoryUnlock(IMG_VOID)
85 {
86         OSLockRelease(gsDevicememHistoryData.hLock);
87 }
88
89 PVRSRV_ERROR DevicememHistoryInitKM(IMG_VOID)
90 {
91         PVRSRV_ERROR eError;
92
93         eError = OSLockCreate(&gsDevicememHistoryData.hLock, LOCK_TYPE_PASSIVE);
94
95         if(eError != PVRSRV_OK)
96         {
97                 PVR_DPF((PVR_DBG_ERROR, "DevicememHistoryInitKM: Failed to create lock"));
98                 goto err_lock;
99         }
100
101         gsDevicememHistoryData.psAllocations = OSAllocZMem(sizeof(DEVICEMEM_HISTORY_ALLOCATION) * DEVICEMEM_HISTORY_ALLOCATION_HISTORY_LEN);
102
103         if(gsDevicememHistoryData.psAllocations == IMG_NULL)
104         {
105                 PVR_DPF((PVR_DBG_ERROR, "DevicememHistoryInitKM: Failed to allocate space for allocations list"));
106                 goto err_allocations;
107         }
108
109         return PVRSRV_OK;
110
111 err_allocations:
112         OSLockDestroy(gsDevicememHistoryData.hLock);
113 err_lock:
114         return eError;
115 }
116
117 IMG_VOID DevicememHistoryDeInitKM(IMG_VOID)
118 {
119         OSFREEMEM(gsDevicememHistoryData.psAllocations);
120         OSLockDestroy(gsDevicememHistoryData.hLock);
121 }
122
123 static PVRSRV_ERROR DevicememHistoryWrite(IMG_DEV_VIRTADDR sDevVAddr, IMG_SIZE_T uiSize,
124                                                 const char szString[DEVICEMEM_HISTORY_TEXT_BUFSZ],
125                                                 IMG_BOOL bAlloc)
126 {
127         DEVICEMEM_HISTORY_ALLOCATION *psAlloc;
128
129         PVR_ASSERT(gsDevicememHistoryData.psAllocations != IMG_NULL);
130
131         DevicememHistoryLock();
132
133         psAlloc = &gsDevicememHistoryData.psAllocations[gsDevicememHistoryData.ui32Head];
134         PVR_ASSERT(gsDevicememHistoryData.ui32Head < DEVICEMEM_HISTORY_ALLOCATION_HISTORY_LEN);
135
136         gsDevicememHistoryData.ui32Head = (gsDevicememHistoryData.ui32Head + 1) % DEVICEMEM_HISTORY_ALLOCATION_HISTORY_LEN;
137
138         psAlloc->sDevVAddr = sDevVAddr;
139         psAlloc->uiSize = uiSize;
140         psAlloc->uiPID = OSGetCurrentProcessID();
141         OSStringNCopy(psAlloc->szString, szString, sizeof(psAlloc->szString));
142         psAlloc->szString[sizeof(psAlloc->szString) - 1] = '\0';
143         psAlloc->bAllocated = bAlloc;
144         psAlloc->ui64Time = OSClockns64();
145
146         DevicememHistoryUnlock();
147
148         return PVRSRV_OK;
149 }
150
151 PVRSRV_ERROR DevicememHistoryMapKM(IMG_DEV_VIRTADDR sDevVAddr, IMG_SIZE_T uiSize, const char szString[DEVICEMEM_HISTORY_TEXT_BUFSZ])
152 {
153         return DevicememHistoryWrite(sDevVAddr, uiSize, szString, IMG_TRUE);
154 }
155
156 PVRSRV_ERROR DevicememHistoryUnmapKM(IMG_DEV_VIRTADDR sDevVAddr, IMG_SIZE_T uiSize, const char szString[DEVICEMEM_HISTORY_TEXT_BUFSZ])
157 {
158         return DevicememHistoryWrite(sDevVAddr, uiSize, szString, IMG_FALSE);
159 }
160
161 /* given a time stamp, calculate the age in nanoseconds (relative to now) */
162 static IMG_UINT64 _CalculateAge(IMG_UINT64 ui64Then)
163 {
164         IMG_UINT64 ui64Now;
165
166         ui64Now = OSClockns64();
167
168         if(ui64Now >= ui64Then)
169         {
170                 /* no clock wrap */
171                 return ui64Now - ui64Then;
172         }
173         else
174         {
175                 /* clock has wrapped */
176                 return ((~(IMG_UINT64) 0) - ui64Then) + ui64Now + 1;
177         }
178 }
179
180 IMG_BOOL DevicememHistoryQuery(DEVICEMEM_HISTORY_QUERY_IN *psQueryIn, DEVICEMEM_HISTORY_QUERY_OUT *psQueryOut)
181 {
182         IMG_UINT32 ui32Entry;
183
184         /* initialise the results count for the caller */
185         psQueryOut->ui32NumResults = 0;
186
187         DevicememHistoryLock();
188
189         /* search from newest to oldest */
190
191         ui32Entry = gsDevicememHistoryData.ui32Head;
192
193         do
194         {
195                 DEVICEMEM_HISTORY_ALLOCATION *psAlloc;
196
197                 /* searching backwards (from newest to oldest)
198                  * wrap around backwards when going past zero
199                  */
200                 ui32Entry = (ui32Entry != 0) ? ui32Entry - 1 : DEVICEMEM_HISTORY_ALLOCATION_HISTORY_LEN - 1;
201                 psAlloc = &gsDevicememHistoryData.psAllocations[ui32Entry];
202
203                 if((psAlloc->uiPID == psQueryIn->uiPID) &&
204                         (psQueryIn->sDevVAddr.uiAddr >= psAlloc->sDevVAddr.uiAddr) &&
205                         (psQueryIn->sDevVAddr.uiAddr < psAlloc->sDevVAddr.uiAddr + psAlloc->uiSize))
206                 {
207                                 DEVICEMEM_HISTORY_QUERY_OUT_RESULT *psResult = &psQueryOut->sResults[psQueryOut->ui32NumResults];
208
209                                 OSStringNCopy(psResult->szString, psAlloc->szString, sizeof(psResult->szString));
210                                 psResult->szString[DEVICEMEM_HISTORY_TEXT_BUFSZ - 1] = '\0';
211                                 psResult->sBaseDevVAddr = psAlloc->sDevVAddr;
212                                 psResult->uiSize = psAlloc->uiSize;
213                                 psResult->bAllocated = psAlloc->bAllocated;
214                                 psResult->ui64Age = _CalculateAge(psAlloc->ui64Time);
215                                 psResult->ui64When = psAlloc->ui64Time;
216
217                                 psQueryOut->ui32NumResults++;
218                 }
219         } while((psQueryOut->ui32NumResults < DEVICEMEM_HISTORY_QUERY_OUT_MAX_RESULTS) &&
220                                                 (ui32Entry != gsDevicememHistoryData.ui32Head));
221
222         DevicememHistoryUnlock();
223
224         return psQueryOut->ui32NumResults > 0;
225 }