gpu: pvr: move debugfs infrastructure to its own files
[sgx.git] / pvr / pdump_common.c
1 /**********************************************************************
2  *
3  * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful but, except
10  * as otherwise stated in writing, without any warranty; without even the
11  * implied warranty of merchantability or fitness for a particular purpose.
12  * See the GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17  *
18  * The full GNU General Public License is included in this distribution in
19  * the file called "COPYING".
20  *
21  * Contact Information:
22  * Imagination Technologies Ltd. <gpl-support@imgtec.com>
23  * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
24  *
25  ******************************************************************************/
26
27 #if defined(PDUMP)
28 #include "services_headers.h"
29 #include "pdump_km.h"
30
31 #if !defined(PDUMP_TEMP_BUFFER_SIZE)
32 #define PDUMP_TEMP_BUFFER_SIZE (64 * 1024L)
33 #endif
34
35 #define MIN(x, y)               (((x) < (y)) ? (x) : (y))
36 #define PTR_PLUS(t, p, x)       ((t *)(((char *)(p)) + (x)))
37 #define VPTR_PLUS(p, x)         PTR_PLUS(void, p, x)
38 #define VPTR_INC(p, x)          (p = VPTR_PLUS(p, x))
39 #define MAX_PDUMP_MMU_CONTEXTS  10
40 static void *gpvTempBuffer;
41 static void *ghTempBufferBlockAlloc;
42 static u16 gui16MMUContextUsage;
43
44 static void *GetTempBuffer(void)
45 {
46         if (gpvTempBuffer == NULL) {
47                 enum PVRSRV_ERROR eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
48                                                       PDUMP_TEMP_BUFFER_SIZE,
49                                                       &gpvTempBuffer,
50                                                       &ghTempBufferBlockAlloc);
51                 if (eError != PVRSRV_OK)
52                         PVR_DPF(PVR_DBG_ERROR,
53                                  "GetTempBuffer: OSAllocMem failed: %d",
54                                  eError);
55         }
56
57         return gpvTempBuffer;
58 }
59
60 static void FreeTempBuffer(void)
61 {
62         if (gpvTempBuffer != NULL) {
63                 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, PDUMP_TEMP_BUFFER_SIZE,
64                              gpvTempBuffer, ghTempBufferBlockAlloc);
65                 gpvTempBuffer = NULL;
66         }
67 }
68
69 void PDumpInitCommon(void)
70 {
71         (void)GetTempBuffer();
72         PDumpInit();
73 }
74
75 void PDumpDeInitCommon(void)
76 {
77         FreeTempBuffer();
78         PDumpDeInit();
79 }
80
81 enum PVRSRV_ERROR PDumpMemUM(struct PVRSRV_PER_PROCESS_DATA *psPerProc,
82                              void *pvAltLinAddrUM, void *pvLinAddrUM,
83                              struct PVRSRV_KERNEL_MEM_INFO *psMemInfo,
84                              u32 ui32Offset, u32 ui32Bytes, u32 ui32Flags,
85                              void *hUniqueTag)
86 {
87         void *pvAddrUM;
88         void *pvAddrKM;
89         u32 ui32BytesDumped;
90         u32 ui32CurrentOffset;
91
92         if (psMemInfo->pvLinAddrKM != NULL && pvAltLinAddrUM == NULL)
93                 return PDumpMemKM(NULL, psMemInfo, ui32Offset, ui32Bytes,
94                                   ui32Flags, hUniqueTag);
95
96         pvAddrUM = (pvAltLinAddrUM != NULL) ? pvAltLinAddrUM :
97                         ((pvLinAddrUM != NULL) ? VPTR_PLUS(pvLinAddrUM,
98                                                           ui32Offset) : NULL);
99
100         pvAddrKM = GetTempBuffer();
101
102         PVR_ASSERT(pvAddrUM != NULL && pvAddrKM != NULL);
103         if (pvAddrUM == NULL || pvAddrKM == NULL) {
104                 PVR_DPF(PVR_DBG_ERROR, "PDumpMemUM: Nothing to dump");
105                 return PVRSRV_ERROR_GENERIC;
106         }
107
108         if (ui32Bytes > PDUMP_TEMP_BUFFER_SIZE)
109                 PDumpCommentWithFlags(ui32Flags,
110                 "Dumping 0x%8.8lx bytes of memory, in blocks of 0x%8.8lx bytes",
111                                       ui32Bytes, (u32) PDUMP_TEMP_BUFFER_SIZE);
112
113         ui32CurrentOffset = ui32Offset;
114         for (ui32BytesDumped = 0; ui32BytesDumped < ui32Bytes;) {
115                 enum PVRSRV_ERROR eError;
116                 u32 ui32BytesToDump =
117                     MIN(PDUMP_TEMP_BUFFER_SIZE, ui32Bytes - ui32BytesDumped);
118
119                 eError = OSCopyFromUser(psPerProc,
120                                         pvAddrKM, pvAddrUM, ui32BytesToDump);
121                 if (eError != PVRSRV_OK) {
122                         PVR_DPF(PVR_DBG_ERROR,
123                         "PDumpMemUM: OSCopyFromUser failed (%d), eError");
124                         return PVRSRV_ERROR_GENERIC;
125                 }
126
127                 eError = PDumpMemKM(pvAddrKM, psMemInfo, ui32CurrentOffset,
128                                     ui32BytesToDump, ui32Flags, hUniqueTag);
129
130                 if (eError != PVRSRV_OK) {
131                         if (ui32BytesDumped != 0)
132                                 PVR_DPF(PVR_DBG_ERROR,
133                                          "PDumpMemUM: PDumpMemKM failed (%d)",
134                                          eError);
135                         PVR_ASSERT(ui32BytesDumped == 0);
136                         return eError;
137                 }
138
139                 VPTR_INC(pvAddrUM, ui32BytesToDump);
140                 ui32CurrentOffset += ui32BytesToDump;
141                 ui32BytesDumped += ui32BytesToDump;
142         }
143
144         return PVRSRV_OK;
145 }
146
147 static enum PVRSRV_ERROR _PdumpAllocMMUContext(u32 *pui32MMUContextID)
148 {
149         u32 i;
150
151         for (i = 0; i < MAX_PDUMP_MMU_CONTEXTS; i++)
152                 if ((gui16MMUContextUsage & (1UL << i)) == 0) {
153                         gui16MMUContextUsage |= 1UL << i;
154                         *pui32MMUContextID = i;
155                         return PVRSRV_OK;
156                 }
157
158         PVR_DPF(PVR_DBG_ERROR,
159                  "_PdumpAllocMMUContext: no free MMU context ids");
160
161         return PVRSRV_ERROR_GENERIC;
162 }
163
164 static enum PVRSRV_ERROR _PdumpFreeMMUContext(u32 ui32MMUContextID)
165 {
166         if (ui32MMUContextID < MAX_PDUMP_MMU_CONTEXTS) {
167
168                 gui16MMUContextUsage &= ~(1UL << ui32MMUContextID);
169                 return PVRSRV_OK;
170         }
171
172         PVR_DPF(PVR_DBG_ERROR,
173                  "_PdumpFreeMMUContext: MMU context ids invalid");
174
175         return PVRSRV_ERROR_GENERIC;
176 }
177
178 enum PVRSRV_ERROR PDumpSetMMUContext(enum PVRSRV_DEVICE_TYPE eDeviceType,
179                                      char *pszMemSpace, u32 *pui32MMUContextID,
180                                      u32 ui32MMUType, void *hUniqueTag1,
181                                      void *pvPDCPUAddr)
182 {
183         u8 *pui8LinAddr = (u8 *) pvPDCPUAddr;
184         struct IMG_CPU_PHYADDR sCpuPAddr;
185         struct IMG_DEV_PHYADDR sDevPAddr;
186         u32 ui32MMUContextID;
187         enum PVRSRV_ERROR eError;
188
189         eError = _PdumpAllocMMUContext(&ui32MMUContextID);
190         if (eError != PVRSRV_OK) {
191                 PVR_DPF(PVR_DBG_ERROR,
192                          "PDumpSetMMUContext: _PdumpAllocMMUContext failed: %d",
193                          eError);
194                 return eError;
195         }
196
197         sCpuPAddr = OSMapLinToCPUPhys(pui8LinAddr);
198         sDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
199
200         sDevPAddr.uiAddr &= ~PVRSRV_4K_PAGE_SIZE;
201
202         PDumpComment("Set MMU Context\r\n");
203
204         PDumpComment("MMU :%s:v%d %d :%s:PA_%8.8lX%8.8lX\r\n",
205                      pszMemSpace, ui32MMUContextID, ui32MMUType, pszMemSpace,
206                      hUniqueTag1, sDevPAddr.uiAddr);
207
208         *pui32MMUContextID = ui32MMUContextID;
209
210         return PVRSRV_OK;
211 }
212
213 enum PVRSRV_ERROR PDumpClearMMUContext(enum PVRSRV_DEVICE_TYPE eDeviceType,
214                                        char *pszMemSpace,
215                                        u32 ui32MMUContextID, u32 ui32MMUType)
216 {
217         enum PVRSRV_ERROR eError;
218
219         PVR_UNREFERENCED_PARAMETER(eDeviceType);
220
221         PDumpComment("Clear MMU Context\r\n");
222
223         PDumpComment("MMU :%s:v%d %d\r\n",
224                      pszMemSpace, ui32MMUContextID, ui32MMUType);
225
226         eError = _PdumpFreeMMUContext(ui32MMUContextID);
227         if (eError != PVRSRV_OK) {
228                 PVR_DPF(PVR_DBG_ERROR,
229                         "PDumpClearMMUContext: _PdumpFreeMMUContext failed: %d",
230                          eError);
231                 return eError;
232         }
233
234         return PVRSRV_OK;
235 }
236
237 #endif