1df3a391f06354a48e87509bf6b54cabba4d6664
[h-e-n] / drivers / gpu / 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 "pdump_km.h"
36
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 = PVRSRV_ERROR_GENERIC;
60
61         psSGXDevInfo = ((struct PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
62
63         psStubPBDesc = psSGXDevInfo->psStubPBDescListKM;
64         if (psStubPBDesc != NULL) {
65                 if (psStubPBDesc->ui32TotalPBSize != ui32TotalPBSize)
66                         PVR_DPF(PVR_DBG_WARNING, "SGXFindSharedPBDescKM: "
67                                 "Shared PB requested with different size "
68                                 "(0x%x) from existing shared PB (0x%x) - "
69                                 "requested size ignored",
70                                  ui32TotalPBSize,
71                                  psStubPBDesc->ui32TotalPBSize);
72                 {
73                         u32 i;
74                         struct RESMAN_ITEM *psResItem;
75
76                         if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
77                                        sizeof(struct PVRSRV_KERNEL_MEM_INFO *)*
78                                        psStubPBDesc->ui32SubKernelMemInfosCount,
79                                        (void **) &
80                                        ppsSharedPBDescSubKernelMemInfos,
81                                        NULL) != PVRSRV_OK) {
82                                 PVR_DPF(PVR_DBG_ERROR, "SGXFindSharedPBDescKM:"
83                                                 " OSAllocMem failed");
84                                 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
85                                 goto ExitNotFound;
86                         }
87
88                         psResItem = ResManRegisterRes(psPerProc->hResManContext,
89                                               RESMAN_TYPE_SHARED_PB_DESC,
90                                               psStubPBDesc,
91                                               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
103                                 eError = PVRSRV_ERROR_GENERIC;
104                                 goto ExitNotFound;
105                         }
106
107                         *ppsSharedPBDescKernelMemInfo =
108                             psStubPBDesc->psSharedPBDescKernelMemInfo;
109                         *ppsHWPBDescKernelMemInfo =
110                             psStubPBDesc->psHWPBDescKernelMemInfo;
111                         *ppsBlockKernelMemInfo =
112                             psStubPBDesc->psBlockKernelMemInfo;
113
114                         *ui32SharedPBDescSubKernelMemInfosCount =
115                             psStubPBDesc->ui32SubKernelMemInfosCount;
116
117                         *pppsSharedPBDescSubKernelMemInfos =
118                             ppsSharedPBDescSubKernelMemInfos;
119
120                         for (i = 0;
121                              i < psStubPBDesc->ui32SubKernelMemInfosCount;
122                              i++)
123                                 ppsSharedPBDescSubKernelMemInfos[i] =
124                                     psStubPBDesc->ppsSubKernelMemInfos[i];
125
126                         psStubPBDesc->ui32RefCount++;
127                         *phSharedPBDesc = (void *) psResItem;
128                         return PVRSRV_OK;
129                 }
130         }
131
132         eError = PVRSRV_OK;
133         if (bLockOnFailure) {
134                 if (psResItemCreateSharedPB == NULL) {
135                         psResItemCreateSharedPB =
136                             ResManRegisterRes(psPerProc->hResManContext,
137                                      RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK,
138                                      psPerProc, 0,
139                                      &SGXCleanupSharedPBDescCreateLockCallback);
140
141                         if (psResItemCreateSharedPB == NULL) {
142                                 PVR_DPF(PVR_DBG_ERROR, "SGXFindSharedPBDescKM:"
143                                         " ResManRegisterRes failed");
144
145                                 eError = PVRSRV_ERROR_GENERIC;
146                                 goto ExitNotFound;
147                         }
148                         PVR_ASSERT(psPerProcCreateSharedPB == NULL);
149                         psPerProcCreateSharedPB = psPerProc;
150                 } else {
151                         eError = PVRSRV_ERROR_PROCESSING_BLOCKED;
152                 }
153         }
154 ExitNotFound:
155         *phSharedPBDesc = NULL;
156
157         return eError;
158 }
159
160 static enum PVRSRV_ERROR
161 SGXCleanupSharedPBDescKM(struct PVRSRV_STUB_PBDESC *psStubPBDescIn)
162 {
163         struct PVRSRV_STUB_PBDESC **ppsStubPBDesc;
164         u32 i;
165         struct PVRSRV_SGXDEV_INFO *psSGXDevInfo;
166
167         psSGXDevInfo = (struct PVRSRV_SGXDEV_INFO *)
168                 ((struct PVRSRV_DEVICE_NODE *)psStubPBDescIn->hDevCookie)->
169                                                                 pvDevice;
170
171         for (ppsStubPBDesc = (struct PVRSRV_STUB_PBDESC **)
172                         &psSGXDevInfo->psStubPBDescListKM;
173              *ppsStubPBDesc != NULL;
174              ppsStubPBDesc = &(*ppsStubPBDesc)->psNext) {
175                 struct PVRSRV_STUB_PBDESC *psStubPBDesc = *ppsStubPBDesc;
176
177                 if (psStubPBDesc == psStubPBDescIn) {
178                         psStubPBDesc->ui32RefCount--;
179                         PVR_ASSERT((s32) psStubPBDesc->ui32RefCount >= 0);
180
181                         if (psStubPBDesc->ui32RefCount == 0) {
182                                 struct PVRSRV_SGX_HOST_CTL *psSGXHostCtl =
183                                         (struct PVRSRV_SGX_HOST_CTL *)
184                                                 psSGXDevInfo->psSGXHostCtl;
185 #if defined(PDUMP)
186                                 void *hUniqueTag = MAKEUNIQUETAG(
187                                        psSGXDevInfo->psKernelSGXHostCtlMemInfo);
188 #endif
189                                 psSGXHostCtl->sTAHWPBDesc.uiAddr = 0;
190                                 psSGXHostCtl->s3DHWPBDesc.uiAddr = 0;
191
192                                 PDUMPCOMMENT("TA/3D CCB Control - "
193                                              "Reset HW PBDesc records");
194                                 PDUMPMEM(NULL,
195                                         psSGXDevInfo->psKernelSGXHostCtlMemInfo,
196                                         offsetof(struct PVRSRV_SGX_HOST_CTL,
197                                                         sTAHWPBDesc),
198                                         sizeof(struct IMG_DEV_VIRTADDR),
199                                         PDUMP_FLAGS_CONTINUOUS, hUniqueTag);
200                                 PDUMPMEM(NULL,
201                                         psSGXDevInfo->psKernelSGXHostCtlMemInfo,
202                                         offsetof(struct PVRSRV_SGX_HOST_CTL,
203                                                         s3DHWPBDesc),
204                                         sizeof(struct IMG_DEV_VIRTADDR),
205                                         PDUMP_FLAGS_CONTINUOUS, hUniqueTag);
206
207                                 *ppsStubPBDesc = psStubPBDesc->psNext;
208
209                                 for (i = 0;
210                                    i < psStubPBDesc->ui32SubKernelMemInfosCount;
211                                    i++)
212                                         PVRSRVFreeDeviceMemKM(psStubPBDesc->
213                                                                    hDevCookie,
214                                          psStubPBDesc->ppsSubKernelMemInfos[i]);
215
216                                 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
217                                         sizeof(struct PVRSRV_KERNEL_MEM_INFO *)*
218                                           psStubPBDesc->
219                                                 ui32SubKernelMemInfosCount,
220                                           psStubPBDesc->ppsSubKernelMemInfos,
221                                           NULL);
222
223                                 PVRSRVFreeSharedSysMemoryKM(psStubPBDesc->
224                                                 psBlockKernelMemInfo);
225
226                                 PVRSRVFreeDeviceMemKM(psStubPBDesc->hDevCookie,
227                                                 psStubPBDesc->
228                                                 psHWPBDescKernelMemInfo);
229
230                                 PVRSRVFreeSharedSysMemoryKM(psStubPBDesc->
231                                                 psSharedPBDescKernelMemInfo);
232
233                                 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
234                                              sizeof(struct PVRSRV_STUB_PBDESC),
235                                              psStubPBDesc, NULL);
236
237                         }
238                         return PVRSRV_OK;
239                 }
240         }
241
242         return PVRSRV_ERROR_INVALID_PARAMS;
243 }
244
245 static enum PVRSRV_ERROR SGXCleanupSharedPBDescCallback(void *pvParam,
246                                                         u32 ui32Param)
247 {
248         struct PVRSRV_STUB_PBDESC *psStubPBDesc =
249                                         (struct PVRSRV_STUB_PBDESC *)pvParam;
250
251         PVR_UNREFERENCED_PARAMETER(ui32Param);
252
253         return SGXCleanupSharedPBDescKM(psStubPBDesc);
254 }
255
256 static enum PVRSRV_ERROR SGXCleanupSharedPBDescCreateLockCallback(void *pvParam,
257                                                              u32 ui32Param)
258 {
259 #ifdef DEBUG
260         struct PVRSRV_PER_PROCESS_DATA *psPerProc =
261             (struct PVRSRV_PER_PROCESS_DATA *)pvParam;
262 #else
263         PVR_UNREFERENCED_PARAMETER(pvParam);
264 #endif
265
266         PVR_UNREFERENCED_PARAMETER(ui32Param);
267
268         PVR_ASSERT(psPerProc == psPerProcCreateSharedPB);
269
270         psPerProcCreateSharedPB = NULL;
271         psResItemCreateSharedPB = NULL;
272
273         return PVRSRV_OK;
274 }
275
276 enum PVRSRV_ERROR SGXUnrefSharedPBDescKM(void *hSharedPBDesc)
277 {
278         PVR_ASSERT(hSharedPBDesc != NULL);
279
280         ResManFreeResByPtr(hSharedPBDesc);
281         return PVRSRV_OK;
282 }
283
284 enum PVRSRV_ERROR SGXAddSharedPBDescKM(
285         struct PVRSRV_PER_PROCESS_DATA *psPerProc,
286         void *hDevCookie,
287         struct PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo,
288         struct PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo,
289         struct PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo,
290         u32 ui32TotalPBSize, void **phSharedPBDesc,
291         struct PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescSubKernelMemInfos,
292         u32 ui32SharedPBDescSubKernelMemInfosCount)
293 {
294         struct PVRSRV_STUB_PBDESC *psStubPBDesc = NULL;
295         enum PVRSRV_ERROR eRet = PVRSRV_ERROR_GENERIC;
296         u32 i;
297         struct PVRSRV_SGXDEV_INFO *psSGXDevInfo;
298         struct RESMAN_ITEM *psResItem;
299
300         if (psPerProcCreateSharedPB != psPerProc) {
301                 goto NoAdd;
302         } else {
303                 PVR_ASSERT(psResItemCreateSharedPB != NULL);
304
305                 ResManFreeResByPtr(psResItemCreateSharedPB);
306
307                 PVR_ASSERT(psResItemCreateSharedPB == NULL);
308                 PVR_ASSERT(psPerProcCreateSharedPB == NULL);
309         }
310
311         psSGXDevInfo = (struct PVRSRV_SGXDEV_INFO *)
312                 ((struct PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
313
314         psStubPBDesc = psSGXDevInfo->psStubPBDescListKM;
315         if (psStubPBDesc != NULL) {
316                 if (psStubPBDesc->ui32TotalPBSize != ui32TotalPBSize)
317                         PVR_DPF(PVR_DBG_WARNING, "SGXAddSharedPBDescKM: "
318                                 "Shared PB requested with different size "
319                                 "(0x%x) from existing shared PB (0x%x) - "
320                                 "requested size ignored",
321                                  ui32TotalPBSize,
322                                  psStubPBDesc->ui32TotalPBSize);
323
324                 {
325
326                         psResItem = ResManRegisterRes(psPerProc->hResManContext,
327                                               RESMAN_TYPE_SHARED_PB_DESC,
328                                               psStubPBDesc, 0,
329                                               &SGXCleanupSharedPBDescCallback);
330                         if (psResItem == NULL) {
331                                 PVR_DPF(PVR_DBG_ERROR,
332                                          "SGXAddSharedPBDescKM: "
333                                          "Failed to register existing shared "
334                                          "PBDesc with the resource manager");
335                                 goto NoAddKeepPB;
336                         }
337
338                         psStubPBDesc->ui32RefCount++;
339
340                         *phSharedPBDesc = (void *) psResItem;
341                         eRet = PVRSRV_OK;
342                         goto NoAddKeepPB;
343                 }
344         }
345
346         if (OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
347                        sizeof(struct PVRSRV_STUB_PBDESC),
348                        (void **)&psStubPBDesc, NULL) != PVRSRV_OK) {
349                 PVR_DPF(PVR_DBG_ERROR, "SGXAddSharedPBDescKM: Failed to alloc "
350                          "StubPBDesc");
351                 eRet = PVRSRV_ERROR_OUT_OF_MEMORY;
352                 goto NoAdd;
353         }
354
355         psStubPBDesc->ppsSubKernelMemInfos = NULL;
356
357         if (OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
358                        sizeof(struct PVRSRV_KERNEL_MEM_INFO *) *
359                                         ui32SharedPBDescSubKernelMemInfosCount,
360                        (void **)&psStubPBDesc->ppsSubKernelMemInfos, NULL) !=
361                         PVRSRV_OK) {
362                 PVR_DPF(PVR_DBG_ERROR, "SGXAddSharedPBDescKM: "
363                          "Failed to alloc "
364                          "StubPBDesc->ppsSubKernelMemInfos");
365                 eRet = PVRSRV_ERROR_OUT_OF_MEMORY;
366                 goto NoAdd;
367         }
368
369         if (PVRSRVDissociateMemFromResmanKM(psSharedPBDescKernelMemInfo)
370             != PVRSRV_OK)
371                 goto NoAdd;
372
373         if (PVRSRVDissociateMemFromResmanKM(psHWPBDescKernelMemInfo)
374             != PVRSRV_OK)
375                 goto NoAdd;
376
377         if (PVRSRVDissociateMemFromResmanKM(psBlockKernelMemInfo)
378             != PVRSRV_OK)
379                 goto NoAdd;
380
381         psStubPBDesc->ui32RefCount = 1;
382         psStubPBDesc->ui32TotalPBSize = ui32TotalPBSize;
383         psStubPBDesc->psSharedPBDescKernelMemInfo = psSharedPBDescKernelMemInfo;
384         psStubPBDesc->psHWPBDescKernelMemInfo = psHWPBDescKernelMemInfo;
385         psStubPBDesc->psBlockKernelMemInfo = psBlockKernelMemInfo;
386
387         psStubPBDesc->ui32SubKernelMemInfosCount =
388             ui32SharedPBDescSubKernelMemInfosCount;
389         for (i = 0; i < ui32SharedPBDescSubKernelMemInfosCount; i++) {
390                 psStubPBDesc->ppsSubKernelMemInfos[i] =
391                     ppsSharedPBDescSubKernelMemInfos[i];
392                 if (PVRSRVDissociateMemFromResmanKM
393                     (ppsSharedPBDescSubKernelMemInfos[i])
394                     != PVRSRV_OK) {
395                         PVR_DPF(PVR_DBG_ERROR, "SGXAddSharedPBDescKM: "
396                                  "Failed to dissociate shared PBDesc "
397                                  "from process");
398                         goto NoAdd;
399                 }
400         }
401
402         psResItem = ResManRegisterRes(psPerProc->hResManContext,
403                                       RESMAN_TYPE_SHARED_PB_DESC,
404                                       psStubPBDesc,
405                                       0, &SGXCleanupSharedPBDescCallback);
406         if (psResItem == NULL) {
407                 PVR_DPF(PVR_DBG_ERROR, "SGXAddSharedPBDescKM: "
408                          "Failed to register shared PBDesc "
409                          " with the resource manager");
410                 goto NoAdd;
411         }
412         psStubPBDesc->hDevCookie = hDevCookie;
413
414         psStubPBDesc->psNext = psSGXDevInfo->psStubPBDescListKM;
415         psSGXDevInfo->psStubPBDescListKM = psStubPBDesc;
416
417         *phSharedPBDesc = (void *) psResItem;
418
419         return PVRSRV_OK;
420
421 NoAdd:
422         if (psStubPBDesc) {
423                 if (psStubPBDesc->ppsSubKernelMemInfos)
424                         OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
425                                   sizeof(struct PVRSRV_KERNEL_MEM_INFO *) *
426                                         ui32SharedPBDescSubKernelMemInfosCount,
427                                   psStubPBDesc->ppsSubKernelMemInfos, NULL);
428                 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
429                           sizeof(struct PVRSRV_STUB_PBDESC), psStubPBDesc,
430                           NULL);
431         }
432
433 NoAddKeepPB:
434         for (i = 0; i < ui32SharedPBDescSubKernelMemInfosCount; i++)
435                 PVRSRVFreeDeviceMemKM(hDevCookie,
436                                       ppsSharedPBDescSubKernelMemInfos[i]);
437
438         PVRSRVFreeSharedSysMemoryKM(psSharedPBDescKernelMemInfo);
439         PVRSRVFreeDeviceMemKM(hDevCookie, psHWPBDescKernelMemInfo);
440
441         PVRSRVFreeSharedSysMemoryKM(psBlockKernelMemInfo);
442
443         return eRet;
444 }