gpu: pvr: pdumpfs: add Kconfig and debugfs pdump mode handling
[sgx.git] / pvr / pb.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 #include <stddef.h>
28
29 #include "services_headers.h"
30 #include "sgxapi_km.h"
31 #include "sgxinfo.h"
32 #include "sgxinfokm.h"
33 #include "pvr_bridge_km.h"
34 #include "sgx_bridge_km.h"
35 #include "pvr_pdump.h"
36 #include "sgxutils.h"
37
38 static struct RESMAN_ITEM *psResItemCreateSharedPB;
39 static struct PVRSRV_PER_PROCESS_DATA *psPerProcCreateSharedPB;
40
41 static enum PVRSRV_ERROR SGXCleanupSharedPBDescCallback(void *pvParam,
42                                                    u32 ui32Param);
43 static enum PVRSRV_ERROR SGXCleanupSharedPBDescCreateLockCallback(void *pvParam,
44                                                              u32 ui32Param);
45
46 enum PVRSRV_ERROR SGXFindSharedPBDescKM(
47              struct PVRSRV_PER_PROCESS_DATA *psPerProc,
48              void *hDevCookie, IMG_BOOL bLockOnFailure,
49              u32 ui32TotalPBSize, void **phSharedPBDesc,
50              struct PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescKernelMemInfo,
51              struct PVRSRV_KERNEL_MEM_INFO **ppsHWPBDescKernelMemInfo,
52              struct PVRSRV_KERNEL_MEM_INFO **ppsBlockKernelMemInfo,
53              struct PVRSRV_KERNEL_MEM_INFO ***pppsSharedPBDescSubKernelMemInfos,
54              u32 *ui32SharedPBDescSubKernelMemInfosCount)
55 {
56         struct PVRSRV_STUB_PBDESC *psStubPBDesc;
57         struct PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescSubKernelMemInfos = NULL;
58         struct PVRSRV_SGXDEV_INFO *psSGXDevInfo;
59         enum PVRSRV_ERROR eError;
60
61         psSGXDevInfo = ((struct PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
62
63         psStubPBDesc = psSGXDevInfo->psStubPBDescListKM;
64         if (psStubPBDesc != NULL) {
65                 u32 i;
66                 struct RESMAN_ITEM *psResItem;
67
68                 if (psStubPBDesc->ui32TotalPBSize != ui32TotalPBSize) {
69                         PVR_DPF(PVR_DBG_WARNING, "SGXFindSharedPBDescKM: "
70                                 "Shared PB requested with different size "
71                                 "(0x%x) from existing shared PB (0x%x) - "
72                                 "requested size ignored",
73                                  ui32TotalPBSize,
74                                  psStubPBDesc->ui32TotalPBSize);
75                 }
76
77                 if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
78                                sizeof(struct PVRSRV_KERNEL_MEM_INFO *) *
79                                       psStubPBDesc->ui32SubKernelMemInfosCount,
80                                (void **) &ppsSharedPBDescSubKernelMemInfos,
81                                NULL) != PVRSRV_OK) {
82                         PVR_DPF(PVR_DBG_ERROR,
83                                  "SGXFindSharedPBDescKM: OSAllocMem failed");
84
85                                 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
86                                 goto ExitNotFound;
87                         }
88
89                         psResItem = ResManRegisterRes(psPerProc->hResManContext,
90                                               RESMAN_TYPE_SHARED_PB_DESC,
91                                               psStubPBDesc, 0,
92                                               &SGXCleanupSharedPBDescCallback);
93
94                         if (psResItem == NULL) {
95                                 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
96                                   sizeof(struct PVRSRV_KERNEL_MEM_INFO *)*
97                                   psStubPBDesc->ui32SubKernelMemInfosCount,
98                                   ppsSharedPBDescSubKernelMemInfos, NULL);
99
100                         PVR_DPF(PVR_DBG_ERROR, "SGXFindSharedPBDescKM: "
101                                                 "ResManRegisterRes failed");
102                                 eError = PVRSRV_ERROR_GENERIC;
103                                 goto ExitNotFound;
104                         }
105
106                         *ppsSharedPBDescKernelMemInfo =
107                             psStubPBDesc->psSharedPBDescKernelMemInfo;
108                         *ppsHWPBDescKernelMemInfo =
109                             psStubPBDesc->psHWPBDescKernelMemInfo;
110                         *ppsBlockKernelMemInfo =
111                             psStubPBDesc->psBlockKernelMemInfo;
112
113                         *ui32SharedPBDescSubKernelMemInfosCount =
114                             psStubPBDesc->ui32SubKernelMemInfosCount;
115
116                         *pppsSharedPBDescSubKernelMemInfos =
117                             ppsSharedPBDescSubKernelMemInfos;
118
119                         for (i = 0;
120                              i < psStubPBDesc->ui32SubKernelMemInfosCount;
121                              i++) {
122                                 ppsSharedPBDescSubKernelMemInfos[i] =
123                                     psStubPBDesc->ppsSubKernelMemInfos[i];
124                         }
125
126                         psStubPBDesc->ui32RefCount++;
127                         *phSharedPBDesc = (void *) psResItem;
128                         return PVRSRV_OK;
129                 }
130
131                 eError = PVRSRV_OK;
132                 if (bLockOnFailure) {
133                         if (psResItemCreateSharedPB == NULL) {
134                                 psResItemCreateSharedPB =
135                                     ResManRegisterRes(psPerProc->hResManContext,
136                                      RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK,
137                                      psPerProc, 0,
138                                      &SGXCleanupSharedPBDescCreateLockCallback);
139
140                         if (psResItemCreateSharedPB == NULL) {
141                                 PVR_DPF(PVR_DBG_ERROR, "SGXFindSharedPBDescKM: "
142                                                 "ResManRegisterRes failed");
143
144                                 eError = PVRSRV_ERROR_GENERIC;
145                                 goto ExitNotFound;
146                         }
147                         PVR_ASSERT(psPerProcCreateSharedPB == NULL);
148                         psPerProcCreateSharedPB = psPerProc;
149                 } else {
150                         eError = PVRSRV_ERROR_PROCESSING_BLOCKED;
151                 }
152         }
153 ExitNotFound:
154         *phSharedPBDesc = NULL;
155
156         return eError;
157 }
158
159 static enum PVRSRV_ERROR SGXCleanupSharedPBDescKM(
160                                 struct PVRSRV_STUB_PBDESC *psStubPBDescIn)
161 {
162         struct PVRSRV_STUB_PBDESC **ppsStubPBDesc;
163         u32 i;
164         struct PVRSRV_DEVICE_NODE *psDeviceNode;
165         struct PVRSRV_SGXDEV_INFO *psSGXDevInfo;
166
167         psDeviceNode = (struct PVRSRV_DEVICE_NODE *)psStubPBDescIn->hDevCookie;
168         psSGXDevInfo = (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
169
170         for (ppsStubPBDesc = (struct PVRSRV_STUB_PBDESC **)
171                         &psSGXDevInfo->psStubPBDescListKM;
172              *ppsStubPBDesc != NULL;
173              ppsStubPBDesc = &(*ppsStubPBDesc)->psNext) {
174                 struct PVRSRV_STUB_PBDESC *psStubPBDesc = *ppsStubPBDesc;
175
176                 if (psStubPBDesc == psStubPBDescIn) {
177                         psStubPBDesc->ui32RefCount--;
178                         PVR_ASSERT((s32) psStubPBDesc->ui32RefCount >= 0);
179
180                         if (psStubPBDesc->ui32RefCount == 0) {
181                                 *ppsStubPBDesc = psStubPBDesc->psNext;
182
183                                 for (i = 0;
184                                    i < psStubPBDesc->ui32SubKernelMemInfosCount;
185                                    i++)
186                                         PVRSRVFreeDeviceMemKM(psStubPBDesc->
187                                                                    hDevCookie,
188                                          psStubPBDesc->ppsSubKernelMemInfos[i]);
189
190                                 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
191                                         sizeof(struct PVRSRV_KERNEL_MEM_INFO *)*
192                                           psStubPBDesc->
193                                                 ui32SubKernelMemInfosCount,
194                                           psStubPBDesc->ppsSubKernelMemInfos,
195                                           NULL);
196
197                                 PVRSRVFreeSharedSysMemoryKM(psStubPBDesc->
198                                                 psBlockKernelMemInfo);
199
200                                 PVRSRVFreeDeviceMemKM(psStubPBDesc->hDevCookie,
201                                                 psStubPBDesc->
202                                                 psHWPBDescKernelMemInfo);
203
204                                 PVRSRVFreeSharedSysMemoryKM(psStubPBDesc->
205                                                 psSharedPBDescKernelMemInfo);
206
207                                 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
208                                              sizeof(struct PVRSRV_STUB_PBDESC),
209                                              psStubPBDesc, NULL);
210
211                                 SGXCleanupRequest(psDeviceNode, NULL,
212                                    PVRSRV_USSE_EDM_RESMAN_CLEANUP_SHAREDPBDESC);
213                         }
214                         return PVRSRV_OK;
215                 }
216         }
217
218         return PVRSRV_ERROR_INVALID_PARAMS;
219 }
220
221 static enum PVRSRV_ERROR SGXCleanupSharedPBDescCallback(void *pvParam,
222                                                         u32 ui32Param)
223 {
224         struct PVRSRV_STUB_PBDESC *psStubPBDesc =
225                                         (struct PVRSRV_STUB_PBDESC *)pvParam;
226
227         PVR_UNREFERENCED_PARAMETER(ui32Param);
228
229         return SGXCleanupSharedPBDescKM(psStubPBDesc);
230 }
231
232 static enum PVRSRV_ERROR SGXCleanupSharedPBDescCreateLockCallback(void *pvParam,
233                                                              u32 ui32Param)
234 {
235 #ifdef CONFIG_PVR_DEBUG_EXTRA
236         struct PVRSRV_PER_PROCESS_DATA *psPerProc =
237             (struct PVRSRV_PER_PROCESS_DATA *)pvParam;
238         PVR_ASSERT(psPerProc == psPerProcCreateSharedPB);
239 #else
240         PVR_UNREFERENCED_PARAMETER(pvParam);
241 #endif
242
243         PVR_UNREFERENCED_PARAMETER(ui32Param);
244
245         psPerProcCreateSharedPB = NULL;
246         psResItemCreateSharedPB = NULL;
247
248         return PVRSRV_OK;
249 }
250
251 enum PVRSRV_ERROR SGXUnrefSharedPBDescKM(void *hSharedPBDesc)
252 {
253         PVR_ASSERT(hSharedPBDesc != NULL);
254
255         ResManFreeResByPtr(hSharedPBDesc);
256
257         return PVRSRV_OK;
258 }
259
260 enum PVRSRV_ERROR SGXAddSharedPBDescKM(
261         struct PVRSRV_PER_PROCESS_DATA *psPerProc,
262         void *hDevCookie,
263         struct PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo,
264         struct PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo,
265         struct PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo,
266         u32 ui32TotalPBSize, void **phSharedPBDesc,
267         struct PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescSubKernelMemInfos,
268         u32 ui32SharedPBDescSubKernelMemInfosCount)
269 {
270         struct PVRSRV_STUB_PBDESC *psStubPBDesc = NULL;
271         enum PVRSRV_ERROR eRet = PVRSRV_ERROR_GENERIC;
272         u32 i;
273         struct PVRSRV_SGXDEV_INFO *psSGXDevInfo;
274         struct RESMAN_ITEM *psResItem;
275
276         if (psPerProcCreateSharedPB != psPerProc) {
277                 goto NoAdd;
278         } else {
279                 PVR_ASSERT(psResItemCreateSharedPB != NULL);
280
281                 ResManFreeResByPtr(psResItemCreateSharedPB);
282
283                 PVR_ASSERT(psResItemCreateSharedPB == NULL);
284                 PVR_ASSERT(psPerProcCreateSharedPB == NULL);
285         }
286
287         psSGXDevInfo = (struct PVRSRV_SGXDEV_INFO *)
288                 ((struct PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
289
290         psStubPBDesc = psSGXDevInfo->psStubPBDescListKM;
291         if (psStubPBDesc != NULL) {
292                 if (psStubPBDesc->ui32TotalPBSize != ui32TotalPBSize) {
293                         PVR_DPF(PVR_DBG_WARNING, "SGXAddSharedPBDescKM: "
294                                 "Shared PB requested with different size "
295                                 "(0x%x) from existing shared PB (0x%x) - "
296                                 "requested size ignored",
297                                  ui32TotalPBSize,
298                                  psStubPBDesc->ui32TotalPBSize);
299
300                 }
301
302                 psResItem = ResManRegisterRes(psPerProc->hResManContext,
303                                               RESMAN_TYPE_SHARED_PB_DESC,
304                                               psStubPBDesc, 0,
305                                               &SGXCleanupSharedPBDescCallback);
306                 if (psResItem == NULL) {
307                         PVR_DPF(PVR_DBG_ERROR,
308                                          "SGXAddSharedPBDescKM: "
309                                          "Failed to register existing shared "
310                                          "PBDesc with the resource manager");
311                         goto NoAddKeepPB;
312                 }
313
314                 psStubPBDesc->ui32RefCount++;
315
316                 *phSharedPBDesc = (void *) psResItem;
317                 eRet = PVRSRV_OK;
318                 goto NoAddKeepPB;
319         }
320
321         if (OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
322                        sizeof(struct PVRSRV_STUB_PBDESC),
323                        (void **)&psStubPBDesc, NULL) != PVRSRV_OK) {
324                 PVR_DPF(PVR_DBG_ERROR, "SGXAddSharedPBDescKM: Failed to alloc "
325                          "StubPBDesc");
326                 eRet = PVRSRV_ERROR_OUT_OF_MEMORY;
327                 goto NoAdd;
328         }
329
330         psStubPBDesc->ppsSubKernelMemInfos = NULL;
331
332         if (OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
333                        sizeof(struct PVRSRV_KERNEL_MEM_INFO *) *
334                                         ui32SharedPBDescSubKernelMemInfosCount,
335                        (void **)&psStubPBDesc->ppsSubKernelMemInfos, NULL) !=
336                         PVRSRV_OK) {
337                 PVR_DPF(PVR_DBG_ERROR, "SGXAddSharedPBDescKM: "
338                          "Failed to alloc "
339                          "StubPBDesc->ppsSubKernelMemInfos");
340                 eRet = PVRSRV_ERROR_OUT_OF_MEMORY;
341                 goto NoAdd;
342         }
343
344         if (PVRSRVDissociateMemFromResmanKM(psSharedPBDescKernelMemInfo)
345             != PVRSRV_OK)
346                 goto NoAdd;
347
348         if (PVRSRVDissociateMemFromResmanKM(psHWPBDescKernelMemInfo)
349             != PVRSRV_OK)
350                 goto NoAdd;
351
352         if (PVRSRVDissociateMemFromResmanKM(psBlockKernelMemInfo)
353             != PVRSRV_OK)
354                 goto NoAdd;
355
356         psStubPBDesc->ui32RefCount = 1;
357         psStubPBDesc->ui32TotalPBSize = ui32TotalPBSize;
358         psStubPBDesc->psSharedPBDescKernelMemInfo = psSharedPBDescKernelMemInfo;
359         psStubPBDesc->psHWPBDescKernelMemInfo = psHWPBDescKernelMemInfo;
360         psStubPBDesc->psBlockKernelMemInfo = psBlockKernelMemInfo;
361
362         psStubPBDesc->ui32SubKernelMemInfosCount =
363             ui32SharedPBDescSubKernelMemInfosCount;
364         for (i = 0; i < ui32SharedPBDescSubKernelMemInfosCount; i++) {
365                 psStubPBDesc->ppsSubKernelMemInfos[i] =
366                     ppsSharedPBDescSubKernelMemInfos[i];
367                 if (PVRSRVDissociateMemFromResmanKM
368                     (ppsSharedPBDescSubKernelMemInfos[i]) != PVRSRV_OK) {
369                         PVR_DPF(PVR_DBG_ERROR, "SGXAddSharedPBDescKM: "
370                                  "Failed to dissociate shared PBDesc "
371                                  "from process");
372                         goto NoAdd;
373                 }
374         }
375
376         psResItem = ResManRegisterRes(psPerProc->hResManContext,
377                                       RESMAN_TYPE_SHARED_PB_DESC,
378                                       psStubPBDesc,
379                                       0, &SGXCleanupSharedPBDescCallback);
380         if (psResItem == NULL) {
381                 PVR_DPF(PVR_DBG_ERROR, "SGXAddSharedPBDescKM: "
382                          "Failed to register shared PBDesc "
383                          " with the resource manager");
384                 goto NoAdd;
385         }
386         psStubPBDesc->hDevCookie = hDevCookie;
387
388         psStubPBDesc->psNext = psSGXDevInfo->psStubPBDescListKM;
389         psSGXDevInfo->psStubPBDescListKM = psStubPBDesc;
390
391         *phSharedPBDesc = (void *) psResItem;
392
393         return PVRSRV_OK;
394
395 NoAdd:
396         if (psStubPBDesc) {
397                 if (psStubPBDesc->ppsSubKernelMemInfos) {
398                         OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
399                                   sizeof(struct PVRSRV_KERNEL_MEM_INFO *) *
400                                         ui32SharedPBDescSubKernelMemInfosCount,
401                                   psStubPBDesc->ppsSubKernelMemInfos, NULL);
402                 }
403                 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
404                           sizeof(struct PVRSRV_STUB_PBDESC), psStubPBDesc,
405                           NULL);
406         }
407
408 NoAddKeepPB:
409         for (i = 0; i < ui32SharedPBDescSubKernelMemInfosCount; i++)
410                 PVRSRVFreeDeviceMemKM(hDevCookie,
411                                       ppsSharedPBDescSubKernelMemInfos[i]);
412
413         PVRSRVFreeSharedSysMemoryKM(psSharedPBDescKernelMemInfo);
414         PVRSRVFreeDeviceMemKM(hDevCookie, psHWPBDescKernelMemInfo);
415
416         PVRSRVFreeSharedSysMemoryKM(psBlockKernelMemInfo);
417
418         return eRet;
419 }