1 /*************************************************************************/ /*!
3 @Title RGX TA/3D routines
4 @Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
5 @Description RGX TA/3D routines
6 @License Dual MIT/GPLv2
8 The contents of this file are subject to the MIT license as set out below.
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:
17 The above copyright notice and this permission notice shall be included in
18 all copies or substantial portions of the Software.
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.
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.
32 This License is also included in this distribution in the file called
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 /* for the offsetof macro */
47 #include "pvr_debug.h"
49 #include "rgxfwutils.h"
53 #include "devicemem.h"
54 #include "devicemem_pdump.h"
57 #include "rgx_memallocflags.h"
59 #include "rgxhwperf.h"
60 #include "rgxtimerquery.h"
63 #include "rgxdefs_km.h"
64 #include "rgx_fwif_km.h"
66 #include "sync_server.h"
67 #include "sync_internal.h"
68 #include "process_stats.h"
71 #if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
73 #endif /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) */
75 typedef struct _DEVMEM_REF_LOOKUP_
77 IMG_UINT32 ui32ZSBufferID;
78 RGX_ZSBUFFER_DATA *psZSBuffer;
81 typedef struct _DEVMEM_FREELIST_LOOKUP_
83 IMG_UINT32 ui32FreeListID;
84 RGX_FREELIST *psFreeList;
85 } DEVMEM_FREELIST_LOOKUP;
88 DEVMEM_MEMDESC *psContextStateMemDesc;
89 RGX_SERVER_COMMON_CONTEXT *psServerCommonContext;
90 IMG_UINT32 ui32Priority;
91 } RGX_SERVER_RC_TA_DATA;
94 DEVMEM_MEMDESC *psContextStateMemDesc;
95 RGX_SERVER_COMMON_CONTEXT *psServerCommonContext;
96 IMG_UINT32 ui32Priority;
97 } RGX_SERVER_RC_3D_DATA;
99 struct _RGX_SERVER_RENDER_CONTEXT_ {
100 PVRSRV_DEVICE_NODE *psDeviceNode;
101 DEVMEM_MEMDESC *psFWRenderContextMemDesc;
102 DEVMEM_MEMDESC *psFWFrameworkMemDesc;
103 RGX_SERVER_RC_TA_DATA sTAData;
104 RGX_SERVER_RC_3D_DATA s3DData;
105 IMG_UINT32 ui32CleanupStatus;
106 #define RC_CLEANUP_TA_COMPLETE (1 << 0)
107 #define RC_CLEANUP_3D_COMPLETE (1 << 1)
108 PVRSRV_CLIENT_SYNC_PRIM *psCleanupSync;
109 DLLIST_NODE sListNode;
110 SYNC_ADDR_LIST sSyncAddrListTAFence;
111 SYNC_ADDR_LIST sSyncAddrListTAUpdate;
112 SYNC_ADDR_LIST sSyncAddrList3DFence;
113 SYNC_ADDR_LIST sSyncAddrList3DUpdate;
119 __attribute__((noreturn))
121 void sleep_for_ever(void)
123 #if defined(__KLOCWORK__) // klocworks would report an infinite loop because of while(1).
128 OSSleepms(~0); // sleep the maximum amount of time possible
135 Static functions used by render context code
139 PVRSRV_ERROR _DestroyTAContext(RGX_SERVER_RC_TA_DATA *psTAData,
140 PVRSRV_DEVICE_NODE *psDeviceNode,
141 PVRSRV_CLIENT_SYNC_PRIM *psCleanupSync)
145 /* Check if the FW has finished with this resource ... */
146 eError = RGXFWRequestCommonContextCleanUp(psDeviceNode,
147 FWCommonContextGetFWAddress(psTAData->psServerCommonContext),
150 if (eError == PVRSRV_ERROR_RETRY)
154 else if (eError != PVRSRV_OK)
156 PVR_LOG(("%s: Unexpected error from RGXFWRequestCommonContextCleanUp (%s)",
158 PVRSRVGetErrorStringKM(eError)));
162 /* ... it has so we can free it's resources */
164 /* Log the number of TA context stores which occurred */
166 RGXFWIF_TACTX_STATE *psFWTAState;
168 eError = DevmemAcquireCpuVirtAddr(psTAData->psContextStateMemDesc,
169 (IMG_VOID**)&psFWTAState);
170 if (eError != PVRSRV_OK)
172 PVR_DPF((PVR_DBG_ERROR,"%s: Failed to map firmware render context state (%u)",
173 __FUNCTION__, eError));
177 /* Release the CPU virt addr */
178 DevmemReleaseCpuVirtAddr(psTAData->psContextStateMemDesc);
182 FWCommonContextFree(psTAData->psServerCommonContext);
183 DevmemFwFree(psTAData->psContextStateMemDesc);
188 PVRSRV_ERROR _Destroy3DContext(RGX_SERVER_RC_3D_DATA *ps3DData,
189 PVRSRV_DEVICE_NODE *psDeviceNode,
190 PVRSRV_CLIENT_SYNC_PRIM *psCleanupSync)
194 /* Check if the FW has finished with this resource ... */
195 eError = RGXFWRequestCommonContextCleanUp(psDeviceNode,
196 FWCommonContextGetFWAddress(ps3DData->psServerCommonContext),
199 if (eError == PVRSRV_ERROR_RETRY)
203 else if (eError != PVRSRV_OK)
205 PVR_LOG(("%s: Unexpected error from RGXFWRequestCommonContextCleanUp (%s)",
207 PVRSRVGetErrorStringKM(eError)));
211 /* ... it has so we can free it's resources */
213 /* Log the number of 3D context stores which occurred */
215 RGXFWIF_3DCTX_STATE *psFW3DState;
217 eError = DevmemAcquireCpuVirtAddr(ps3DData->psContextStateMemDesc,
218 (IMG_VOID**)&psFW3DState);
219 if (eError != PVRSRV_OK)
221 PVR_DPF((PVR_DBG_ERROR,"%s: Failed to map firmware render context state (%u)",
222 __FUNCTION__, eError));
226 /* Release the CPU virt addr */
227 DevmemReleaseCpuVirtAddr(ps3DData->psContextStateMemDesc);
232 FWCommonContextFree(ps3DData->psServerCommonContext);
233 DevmemFwFree(ps3DData->psContextStateMemDesc);
237 static IMG_BOOL _RGXDumpPMRPageList(PDLLIST_NODE psNode, IMG_PVOID pvCallbackData)
239 RGX_PMR_NODE *psPMRNode = IMG_CONTAINER_OF(psNode, RGX_PMR_NODE, sMemoryBlock);
242 eError = PMRDumpPageList(psPMRNode->psPMR,
243 RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT);
244 if (eError != PVRSRV_OK)
246 PVR_DPF((PVR_DBG_ERROR,"Error (%u) printing pmr %p", eError, psPMRNode->psPMR));
252 IMG_BOOL RGXDumpFreeListPageList(RGX_FREELIST *psFreeList)
254 PVR_LOG(("Freelist FWAddr 0x%08x, ID = %d, CheckSum 0x%016llx",
255 psFreeList->sFreeListFWDevVAddr.ui32Addr,
256 psFreeList->ui32FreelistID,
257 psFreeList->ui64FreelistChecksum));
259 /* Dump Init FreeList page list */
260 PVR_LOG((" Initial Memory block"));
261 dllist_foreach_node(&psFreeList->sMemoryBlockInitHead,
265 /* Dump Grow FreeList page list */
266 PVR_LOG((" Grow Memory blocks"));
267 dllist_foreach_node(&psFreeList->sMemoryBlockHead,
274 static PVRSRV_ERROR _UpdateFwFreelistSize(RGX_FREELIST *psFreeList,
276 IMG_UINT32 ui32DeltaSize)
279 RGXFWIF_KCCB_CMD sGPCCBCmd;
281 sGPCCBCmd.eCmdType = (bGrow) ? RGXFWIF_KCCB_CMD_FREELIST_GROW_UPDATE : RGXFWIF_KCCB_CMD_FREELIST_SHRINK_UPDATE;
282 sGPCCBCmd.uCmdData.sFreeListGSData.psFreeListFWDevVAddr = psFreeList->sFreeListFWDevVAddr.ui32Addr;
283 sGPCCBCmd.uCmdData.sFreeListGSData.ui32DeltaSize = ui32DeltaSize;
284 sGPCCBCmd.uCmdData.sFreeListGSData.ui32NewSize = psFreeList->ui32CurrentFLPages;
286 PVR_DPF((PVR_DBG_MESSAGE, "Send FW update: freelist [FWAddr=0x%08x] has 0x%08x pages",
287 psFreeList->sFreeListFWDevVAddr.ui32Addr,
288 psFreeList->ui32CurrentFLPages));
290 /* Submit command to the firmware. */
291 LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
293 eError = RGXScheduleCommand(psFreeList->psDevInfo,
298 if (eError != PVRSRV_ERROR_RETRY)
302 OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
303 } END_LOOP_UNTIL_TIMEOUT();
305 if (eError != PVRSRV_OK)
307 PVR_DPF((PVR_DBG_ERROR, "_UpdateFwFreelistSize: failed to update FW freelist size. (error = %u)", eError));
314 static PVRSRV_ERROR _FreeListCheckSum(RGX_FREELIST *psFreeList,
315 IMG_UINT64 *pui64CheckSum)
317 #if defined(NO_HARDWARE)
318 /* No checksum needed as we have all information in the pdumps */
319 PVR_UNREFERENCED_PARAMETER(psFreeList);
324 IMG_SIZE_T uiNumBytes;
325 IMG_UINT8* pui8Buffer;
326 IMG_UINT32* pui32Buffer;
327 IMG_UINT32 ui32CheckSumAdd = 0;
328 IMG_UINT32 ui32CheckSumXor = 0;
329 IMG_UINT32 ui32Entry;
330 IMG_UINT32 ui32Entry2;
332 /* Allocate Buffer of the size of the freelist */
333 pui8Buffer = OSAllocMem(psFreeList->ui32CurrentFLPages * sizeof(IMG_UINT32));
334 if (pui8Buffer == IMG_NULL)
336 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
337 goto _OSAllocMem_Exit;
340 /* Copy freelist content into Buffer */
341 eError = PMR_ReadBytes(psFreeList->psFreeListPMR,
342 psFreeList->uiFreeListPMROffset + (psFreeList->ui32MaxFLPages - psFreeList->ui32CurrentFLPages) * sizeof(IMG_UINT32),
344 psFreeList->ui32CurrentFLPages * sizeof(IMG_UINT32),
346 if (eError != PVRSRV_OK)
348 goto _PMR_ReadBytes_Exit;
351 PVR_ASSERT(uiNumBytes == psFreeList->ui32CurrentFLPages * sizeof(IMG_UINT32));
353 /* Generate checksum */
354 pui32Buffer = (IMG_UINT32 *)pui8Buffer;
355 for(ui32Entry = 0; ui32Entry < psFreeList->ui32CurrentFLPages; ui32Entry++)
357 ui32CheckSumAdd += pui32Buffer[ui32Entry];
358 ui32CheckSumXor ^= pui32Buffer[ui32Entry];
360 /* Check for double entries */
361 for (ui32Entry2 = 0; ui32Entry2 < psFreeList->ui32CurrentFLPages; ui32Entry2++)
363 if ((ui32Entry != ui32Entry2) &&
364 (pui32Buffer[ui32Entry] == pui32Buffer[ui32Entry2]))
366 PVR_DPF((PVR_DBG_ERROR, "Freelist consistency failure: FW addr: 0x%08X, Double entry found 0x%08x on idx: %d and %d",
367 psFreeList->sFreeListFWDevVAddr.ui32Addr,
368 pui32Buffer[ui32Entry2],
377 OSFreeMem(pui8Buffer);
379 /* Set return value */
380 *pui64CheckSum = ((IMG_UINT64)ui32CheckSumXor << 32) | ui32CheckSumAdd;
381 PVR_ASSERT(eError == PVRSRV_OK);
385 error exit paths follow
389 OSFreeMem(pui8Buffer);
392 PVR_ASSERT(eError != PVRSRV_OK);
397 PVRSRV_ERROR RGXGrowFreeList(RGX_FREELIST *psFreeList,
398 IMG_UINT32 ui32NumPages,
399 PDLLIST_NODE pListHeader)
401 RGX_PMR_NODE *psPMRNode;
402 IMG_DEVMEM_SIZE_T uiSize;
403 IMG_BOOL bMappingTable = IMG_TRUE;
404 IMG_DEVMEM_OFFSET_T uiOffset;
405 IMG_DEVMEM_SIZE_T uiLength;
406 IMG_DEVMEM_SIZE_T uistartPage;
408 IMG_UINT64 ui64CheckSum;
409 IMG_UINT32 ui32CheckSumXor;
410 IMG_UINT32 ui32CheckSumAdd;
412 /* Are we allowed to grow ? */
413 if ((psFreeList->ui32MaxFLPages - psFreeList->ui32CurrentFLPages) < ui32NumPages)
415 PVR_DPF((PVR_DBG_WARNING,"Freelist [0x%p]: grow by %u pages denied. Max PB size reached (current pages %u/%u)",
418 psFreeList->ui32CurrentFLPages,
419 psFreeList->ui32MaxFLPages));
420 return PVRSRV_ERROR_PBSIZE_ALREADY_MAX;
423 /* Allocate kernel memory block structure */
424 psPMRNode = OSAllocMem(sizeof(*psPMRNode));
425 if (psPMRNode == IMG_NULL)
427 PVR_DPF((PVR_DBG_ERROR, "RGXGrowFreeList: failed to allocate host data structure"));
428 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
433 * Lock protects simultaneous manipulation of:
434 * - the memory block list
435 * - the freelist's ui32CurrentFLPages
437 OSLockAcquire(psFreeList->psDevInfo->hLockFreeList);
440 psPMRNode->ui32NumPages = ui32NumPages;
441 psPMRNode->psFreeList = psFreeList;
443 /* Allocate Memory Block */
444 PDUMPCOMMENT("Allocate PB Block (Pages %08X)", ui32NumPages);
445 uiSize = (IMG_DEVMEM_SIZE_T)ui32NumPages * RGX_BIF_PM_PHYSICAL_PAGE_SIZE;
446 eError = PhysmemNewRamBackedPMR(psFreeList->psDevInfo->psDeviceNode,
452 RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT,
453 PVRSRV_MEMALLOCFLAG_GPU_READABLE,
455 if(eError != PVRSRV_OK)
457 PVR_DPF((PVR_DBG_ERROR,
458 "RGXGrowFreeList: Failed to allocate PB block of size: 0x%016llX",
459 (IMG_UINT64)uiSize));
460 goto ErrorBlockAlloc;
463 /* Zeroing physical pages pointed by the PMR */
464 if (psFreeList->psDevInfo->ui32DeviceFlags & RGXKM_DEVICE_STATE_ZERO_FREELIST)
466 eError = PMRZeroingPMR(psPMRNode->psPMR, RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT);
467 if (eError != PVRSRV_OK)
469 PVR_DPF((PVR_DBG_ERROR,"RGXGrowFreeList: Failed to zero PMR %p of freelist %p with Error %d",
477 uiLength = psPMRNode->ui32NumPages * sizeof(IMG_UINT32);
478 uistartPage = (psFreeList->ui32MaxFLPages - psFreeList->ui32CurrentFLPages - psPMRNode->ui32NumPages);
479 uiOffset = psFreeList->uiFreeListPMROffset + (uistartPage * sizeof(IMG_UINT32));
481 /* write Freelist with Memory Block physical addresses */
482 eError = PMRWritePMPageList(
483 /* Target PMR, offset, and length */
484 psFreeList->psFreeListPMR,
487 /* Referenced PMR, and "page" granularity */
489 RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT,
490 &psPMRNode->psPageList,
492 if (eError != PVRSRV_OK)
494 PVR_DPF((PVR_DBG_ERROR,
495 "RGXGrowFreeList: Failed to write pages of Node %p",
497 goto ErrorPopulateFreelist;
500 /* We add It must be added to the tail, otherwise the freelist population won't work */
501 dllist_add_to_head(pListHeader, &psPMRNode->sMemoryBlock);
503 /* Update number of available pages */
504 psFreeList->ui32CurrentFLPages += ui32NumPages;
506 /* Update statistics */
507 if (psFreeList->ui32NumHighPages < psFreeList->ui32CurrentFLPages)
509 psFreeList->ui32NumHighPages = psFreeList->ui32CurrentFLPages;
512 if (psFreeList->bCheckFreelist)
514 /* Update checksum */
515 ui32CheckSumAdd = (IMG_UINT32)(psFreeList->ui64FreelistChecksum + ui64CheckSum);
516 ui32CheckSumXor = (IMG_UINT32)((psFreeList->ui64FreelistChecksum ^ ui64CheckSum) >> 32);
517 psFreeList->ui64FreelistChecksum = ((IMG_UINT64)ui32CheckSumXor << 32) | ui32CheckSumAdd;
518 /* Note: We can't do a freelist check here, because the freelist is probably empty (OOM) */
521 OSLockRelease(psFreeList->psDevInfo->hLockFreeList);
523 PVR_DPF((PVR_DBG_MESSAGE,"Freelist [%p]: grow by %u pages (current pages %u/%u)",
526 psFreeList->ui32CurrentFLPages,
527 psFreeList->ui32MaxFLPages));
532 ErrorPopulateFreelist:
533 PMRUnrefPMR(psPMRNode->psPMR);
536 OSFreeMem(psPMRNode);
537 OSLockRelease(psFreeList->psDevInfo->hLockFreeList);
540 PVR_ASSERT(eError != PVRSRV_OK);
545 static PVRSRV_ERROR RGXShrinkFreeList(PDLLIST_NODE pListHeader,
546 RGX_FREELIST *psFreeList)
549 RGX_PMR_NODE *psPMRNode;
550 PVRSRV_ERROR eError = PVRSRV_OK;
551 IMG_UINT32 ui32OldValue;
554 * Lock protects simultaneous manipulation of:
555 * - the memory block list
556 * - the freelist's ui32CurrentFLPages value
558 PVR_ASSERT(pListHeader);
559 PVR_ASSERT(psFreeList);
560 PVR_ASSERT(psFreeList->psDevInfo);
561 PVR_ASSERT(psFreeList->psDevInfo->hLockFreeList);
563 OSLockAcquire(psFreeList->psDevInfo->hLockFreeList);
565 /* Get node from head of list and remove it */
566 psNode = dllist_get_next_node(pListHeader);
569 dllist_remove_node(psNode);
571 psPMRNode = IMG_CONTAINER_OF(psNode, RGX_PMR_NODE, sMemoryBlock);
572 PVR_ASSERT(psPMRNode);
573 PVR_ASSERT(psPMRNode->psPMR);
574 PVR_ASSERT(psPMRNode->psFreeList);
576 /* remove block from freelist list */
578 /* Unwrite Freelist with Memory Block physical addresses */
579 eError = PMRUnwritePMPageList(psPMRNode->psPageList);
580 if (eError != PVRSRV_OK)
582 PVR_DPF((PVR_DBG_ERROR,
583 "RGXRemoveBlockFromFreeListKM: Failed to unwrite pages of Node %p",
585 PVR_ASSERT(IMG_FALSE);
588 /* Free PMR (We should be the only one that holds a ref on the PMR) */
589 eError = PMRUnrefPMR(psPMRNode->psPMR);
590 if (eError != PVRSRV_OK)
592 PVR_DPF((PVR_DBG_ERROR,
593 "RGXRemoveBlockFromFreeListKM: Failed to free PB block %p (error %u)",
596 PVR_ASSERT(IMG_FALSE);
599 /* update available pages in freelist */
600 ui32OldValue = psFreeList->ui32CurrentFLPages;
601 psFreeList->ui32CurrentFLPages -= psPMRNode->ui32NumPages;
603 /* check underflow */
604 PVR_ASSERT(ui32OldValue > psFreeList->ui32CurrentFLPages);
606 PVR_DPF((PVR_DBG_MESSAGE, "Freelist [%p]: shrink by %u pages (current pages %u/%u)",
608 psPMRNode->ui32NumPages,
609 psFreeList->ui32CurrentFLPages,
610 psFreeList->ui32MaxFLPages));
612 OSFreeMem(psPMRNode);
616 PVR_DPF((PVR_DBG_WARNING,"Freelist [0x%p]: shrink denied. PB already at initial PB size (%u pages)",
618 psFreeList->ui32InitFLPages));
619 eError = PVRSRV_ERROR_PBSIZE_ALREADY_MIN;
622 OSLockRelease(psFreeList->psDevInfo->hLockFreeList);
627 static IMG_BOOL _FindFreeList(PDLLIST_NODE psNode, IMG_PVOID pvCallbackData)
629 DEVMEM_FREELIST_LOOKUP *psRefLookUp = (DEVMEM_FREELIST_LOOKUP *)pvCallbackData;
630 RGX_FREELIST *psFreeList;
632 psFreeList = IMG_CONTAINER_OF(psNode, RGX_FREELIST, sNode);
634 if (psFreeList->ui32FreelistID == psRefLookUp->ui32FreeListID)
636 psRefLookUp->psFreeList = psFreeList;
645 IMG_VOID RGXProcessRequestGrow(PVRSRV_RGXDEV_INFO *psDevInfo,
646 IMG_UINT32 ui32FreelistID)
648 DEVMEM_FREELIST_LOOKUP sLookUp;
649 RGXFWIF_KCCB_CMD s3DCCBCmd;
650 IMG_UINT32 ui32GrowValue;
653 PVR_ASSERT(psDevInfo);
655 /* find the freelist with the corresponding ID */
656 sLookUp.ui32FreeListID = ui32FreelistID;
657 sLookUp.psFreeList = IMG_NULL;
659 OSLockAcquire(psDevInfo->hLockFreeList);
660 dllist_foreach_node(&psDevInfo->sFreeListHead, _FindFreeList, (IMG_PVOID)&sLookUp);
661 OSLockRelease(psDevInfo->hLockFreeList);
663 if (sLookUp.psFreeList)
665 RGX_FREELIST *psFreeList = sLookUp.psFreeList;
667 /* Try to grow the freelist */
668 eError = RGXGrowFreeList(psFreeList,
669 psFreeList->ui32GrowFLPages,
670 &psFreeList->sMemoryBlockHead);
671 if (eError == PVRSRV_OK)
673 /* Grow successful, return size of grow size */
674 ui32GrowValue = psFreeList->ui32GrowFLPages;
676 psFreeList->ui32NumGrowReqByFW++;
678 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
680 PVRSRVStatsUpdateFreelistStats(0,
681 1, /* Add 1 to the appropriate counter (Requests by FW) */
682 psFreeList->ui32InitFLPages,
683 psFreeList->ui32NumHighPages,
684 psFreeList->ownerPid);
693 PVR_DPF((PVR_DBG_ERROR,"Grow for FreeList %p failed (error %u)",
699 s3DCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_FREELIST_GROW_UPDATE;
700 s3DCCBCmd.uCmdData.sFreeListGSData.psFreeListFWDevVAddr = sLookUp.psFreeList->sFreeListFWDevVAddr.ui32Addr;
701 s3DCCBCmd.uCmdData.sFreeListGSData.ui32DeltaSize = ui32GrowValue;
702 s3DCCBCmd.uCmdData.sFreeListGSData.ui32NewSize = psFreeList->ui32CurrentFLPages;
704 LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
706 eError = RGXScheduleCommand(psDevInfo,
711 if (eError != PVRSRV_ERROR_RETRY)
715 OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
716 } END_LOOP_UNTIL_TIMEOUT();
717 /* Kernel CCB should never fill up, as the FW is processing them right away */
719 PVR_ASSERT(eError == PVRSRV_OK);
723 /* Should never happen */
724 PVR_DPF((PVR_DBG_ERROR,"FreeList Lookup for FreeList ID 0x%08x failed (Populate)", sLookUp.ui32FreeListID));
725 PVR_ASSERT(IMG_FALSE);
729 static IMG_BOOL _RGXCheckFreeListReconstruction(PDLLIST_NODE psNode, IMG_PVOID pvCallbackData)
732 PVRSRV_RGXDEV_INFO *psDevInfo;
733 RGX_FREELIST *psFreeList;
734 RGX_PMR_NODE *psPMRNode;
736 IMG_DEVMEM_OFFSET_T uiOffset;
737 IMG_DEVMEM_SIZE_T uiLength;
738 IMG_UINT32 ui32StartPage;
739 IMG_UINT64 ui64CheckSum;
741 psPMRNode = IMG_CONTAINER_OF(psNode, RGX_PMR_NODE, sMemoryBlock);
742 psFreeList = psPMRNode->psFreeList;
743 PVR_ASSERT(psFreeList);
744 psDevInfo = psFreeList->psDevInfo;
745 PVR_ASSERT(psDevInfo);
747 uiLength = psPMRNode->ui32NumPages * sizeof(IMG_UINT32);
748 ui32StartPage = (psFreeList->ui32MaxFLPages - psFreeList->ui32CurrentFLPages - psPMRNode->ui32NumPages);
749 uiOffset = psFreeList->uiFreeListPMROffset + (ui32StartPage * sizeof(IMG_UINT32));
751 PMRUnwritePMPageList(psPMRNode->psPageList);
752 psPMRNode->psPageList = IMG_NULL;
753 eError = PMRWritePMPageList(
754 /* Target PMR, offset, and length */
755 psFreeList->psFreeListPMR,
758 /* Referenced PMR, and "page" granularity */
760 RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT,
761 &psPMRNode->psPageList,
764 if (eError != PVRSRV_OK)
766 PVR_DPF((PVR_DBG_ERROR,"Error (%u) writing FL 0x%08x", eError, (IMG_UINT32)psFreeList->ui32FreelistID));
769 /* Zeroing physical pages pointed by the reconstructed freelist */
770 if (psDevInfo->ui32DeviceFlags & RGXKM_DEVICE_STATE_ZERO_FREELIST)
772 eError = PMRZeroingPMR(psPMRNode->psPMR, RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT);
773 if (eError != PVRSRV_OK)
775 PVR_DPF((PVR_DBG_ERROR,"_RGXCheckFreeListReconstruction: Failed to zero PMR %p of freelist %p with Error %d",
783 psFreeList->ui32CurrentFLPages += psPMRNode->ui32NumPages;
788 IMG_VOID RGXProcessRequestFreelistsReconstruction(PVRSRV_RGXDEV_INFO *psDevInfo,
790 IMG_UINT32 ui32FreelistsCount,
791 IMG_UINT32 *paui32Freelists)
794 DEVMEM_FREELIST_LOOKUP sLookUp;
795 IMG_UINT32 ui32Loop, ui32Loop2;
796 RGXFWIF_KCCB_CMD s3DCCBCmd;
797 IMG_UINT64 ui64CheckSum;
799 PVR_ASSERT(psDevInfo);
801 //PVR_DPF((PVR_DBG_ERROR,"FreeList RECONSTRUCTION: Reconstructing %u freelist(s)", ui32FreelistsCount));
803 for (ui32Loop = 0; ui32Loop < ui32FreelistsCount; ui32Loop++)
805 /* check if there is more than one occurrence of FL on the list */
806 for (ui32Loop2 = ui32Loop + 1; ui32Loop2 < ui32FreelistsCount; ui32Loop2++)
808 if (paui32Freelists[ui32Loop] == paui32Freelists[ui32Loop2])
810 /* There is a duplicate on a list, skip current Freelist */
815 if (ui32Loop2 < ui32FreelistsCount)
817 /* There is a duplicate on the list, skip current Freelist */
821 /* find the freelist with the corresponding ID */
822 sLookUp.ui32FreeListID = paui32Freelists[ui32Loop];
823 sLookUp.psFreeList = IMG_NULL;
825 //PVR_DPF((PVR_DBG_ERROR,"FreeList RECONSTRUCTION: Looking for freelist %08X", (IMG_UINT32)sLookUp.ui32FreeListID));
826 OSLockAcquire(psDevInfo->hLockFreeList);
827 //PVR_DPF((PVR_DBG_ERROR,"FreeList RECONSTRUCTION: Freelist head %08X", (IMG_UINT32)&psDevInfo->sFreeListHead));
828 dllist_foreach_node(&psDevInfo->sFreeListHead, _FindFreeList, (IMG_PVOID)&sLookUp);
829 OSLockRelease(psDevInfo->hLockFreeList);
831 if (sLookUp.psFreeList)
833 RGX_FREELIST *psFreeList = sLookUp.psFreeList;
835 //PVR_DPF((PVR_DBG_ERROR,"FreeList RECONSTRUCTION: Reconstructing freelist %08X", (IMG_UINT32)psFreeList));
837 /* Do the FreeList Reconstruction */
839 psFreeList->ui32CurrentFLPages = 0;
841 /* Reconstructing Init FreeList pages */
842 dllist_foreach_node(&psFreeList->sMemoryBlockInitHead,
843 _RGXCheckFreeListReconstruction,
846 /* Reconstructing Grow FreeList pages */
847 dllist_foreach_node(&psFreeList->sMemoryBlockHead,
848 _RGXCheckFreeListReconstruction,
851 if (psFreeList->bCheckFreelist)
853 /* Get Freelist checksum (as the list is fully populated) */
854 eError = _FreeListCheckSum(psFreeList,
856 if (eError != PVRSRV_OK)
858 PVR_DPF((PVR_DBG_ERROR,
859 "RGXProcessRequestFreelistsReconstruction: Failed to get freelist checksum Node %p",
865 /* Verify checksum with previous value */
866 if (psFreeList->ui64FreelistChecksum != ui64CheckSum)
868 PVR_DPF((PVR_DBG_ERROR, "RGXProcessRequestFreelistsReconstruction: Freelist [%p] checksum failed: before reconstruction = 0x%016llx, after reconstruction = 0x%016llx",
870 psFreeList->ui64FreelistChecksum,
879 if (eError == PVRSRV_OK)
881 /* Freelist reconstruction successful */
882 s3DCCBCmd.uCmdData.sFreeListsReconstructionData.aui32FreelistIDs[ui32Loop] =
883 paui32Freelists[ui32Loop];
887 /* Freelist reconstruction failed */
888 s3DCCBCmd.uCmdData.sFreeListsReconstructionData.aui32FreelistIDs[ui32Loop] =
889 paui32Freelists[ui32Loop] | RGXFWIF_FREELISTS_RECONSTRUCTION_FAILED_FLAG;
891 PVR_DPF((PVR_DBG_ERROR,"Reconstructing of FreeList %p failed (error %u)",
898 /* Should never happen */
899 PVR_DPF((PVR_DBG_ERROR,"FreeList Lookup for FreeList ID 0x%08x failed (Freelist reconstruction)", sLookUp.ui32FreeListID));
900 PVR_ASSERT(IMG_FALSE);
905 s3DCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_FREELISTS_RECONSTRUCTION_UPDATE;
906 s3DCCBCmd.uCmdData.sFreeListsReconstructionData.ui32FreelistsCount = ui32FreelistsCount;
908 LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
910 eError = RGXScheduleCommand(psDevInfo,
915 if (eError != PVRSRV_ERROR_RETRY)
919 OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
920 } END_LOOP_UNTIL_TIMEOUT();
922 /* Kernel CCB should never fill up, as the FW is processing them right away */
923 PVR_ASSERT(eError == PVRSRV_OK);
926 /* Create HWRTDataSet */
928 PVRSRV_ERROR RGXCreateHWRTData(PVRSRV_DEVICE_NODE *psDeviceNode,
929 IMG_UINT32 psRenderTarget,
930 IMG_DEV_VIRTADDR psPMMListDevVAddr,
931 IMG_DEV_VIRTADDR psVFPPageTableAddr,
932 RGX_FREELIST *apsFreeLists[RGXFW_MAX_FREELISTS],
933 RGX_RTDATA_CLEANUP_DATA **ppsCleanupData,
934 DEVMEM_MEMDESC **ppsRTACtlMemDesc,
935 IMG_UINT32 ui32PPPScreen,
936 IMG_UINT32 ui32PPPGridOffset,
937 IMG_UINT64 ui64PPPMultiSampleCtl,
938 IMG_UINT32 ui32TPCStride,
939 IMG_DEV_VIRTADDR sTailPtrsDevVAddr,
940 IMG_UINT32 ui32TPCSize,
941 IMG_UINT32 ui32TEScreen,
943 IMG_UINT32 ui32TEMTILE1,
944 IMG_UINT32 ui32TEMTILE2,
945 IMG_UINT32 ui32MTileStride,
946 IMG_UINT32 ui32ISPMergeLowerX,
947 IMG_UINT32 ui32ISPMergeLowerY,
948 IMG_UINT32 ui32ISPMergeUpperX,
949 IMG_UINT32 ui32ISPMergeUpperY,
950 IMG_UINT32 ui32ISPMergeScaleX,
951 IMG_UINT32 ui32ISPMergeScaleY,
952 IMG_UINT16 ui16MaxRTs,
953 DEVMEM_MEMDESC **ppsMemDesc,
954 IMG_UINT32 *puiHWRTData)
957 PVRSRV_RGXDEV_INFO *psDevInfo;
958 RGXFWIF_DEV_VIRTADDR pFirmwareAddr;
959 RGXFWIF_HWRTDATA *psHWRTData;
960 RGXFWIF_RTA_CTL *psRTACtl;
962 RGX_RTDATA_CLEANUP_DATA *psTmpCleanup;
964 /* Prepare cleanup struct */
965 psTmpCleanup = OSAllocMem(sizeof(*psTmpCleanup));
966 if (psTmpCleanup == IMG_NULL)
968 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
972 OSMemSet(psTmpCleanup, 0, sizeof(*psTmpCleanup));
973 *ppsCleanupData = psTmpCleanup;
975 /* Allocate cleanup sync */
976 eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext,
977 &psTmpCleanup->psCleanupSync,
979 if (eError != PVRSRV_OK)
981 PVR_DPF((PVR_DBG_ERROR,"RGXCreateHWRTData: Failed to allocate cleanup sync (0x%x)",
986 psDevInfo = psDeviceNode->pvDevice;
989 * This FW RT-Data is only mapped into kernel for initialisation.
990 * Otherwise this allocation is only used by the FW.
991 * Therefore the GPU cache doesn't need coherency,
992 * and write-combine is suffice on the CPU side (WC buffer will be flushed at the first TA-kick)
994 eError = DevmemFwAllocate(psDevInfo,
995 sizeof(RGXFWIF_HWRTDATA),
996 PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
997 PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(META_CACHED) |
998 PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
999 PVRSRV_MEMALLOCFLAG_GPU_READABLE |
1000 PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
1001 PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
1002 PVRSRV_MEMALLOCFLAG_CPU_READABLE |
1003 PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
1004 PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE |
1005 PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE,
1008 if (eError != PVRSRV_OK)
1010 PVR_DPF((PVR_DBG_ERROR, "RGXCreateHWRTData: DevmemAllocate for RGX_FWIF_HWRTDATA failed"));
1011 goto FWRTDataAllocateError;
1014 psTmpCleanup->psDeviceNode = psDeviceNode;
1015 psTmpCleanup->psFWHWRTDataMemDesc = *ppsMemDesc;
1017 RGXSetFirmwareAddress(&pFirmwareAddr, *ppsMemDesc, 0, RFW_FWADDR_FLAG_NONE);
1019 *puiHWRTData = pFirmwareAddr.ui32Addr;
1021 eError = DevmemAcquireCpuVirtAddr(*ppsMemDesc, (IMG_VOID **)&psHWRTData);
1022 PVR_LOGG_IF_ERROR(eError, "Devmem AcquireCpuVirtAddr", FWRTDataCpuMapError);
1025 psHWRTData->psPMMListDevVAddr = psPMMListDevVAddr;
1026 psHWRTData->psParentRenderTarget.ui32Addr = psRenderTarget;
1027 #if defined(SUPPORT_VFP)
1028 psHWRTData->sVFPPageTableAddr = psVFPPageTableAddr;
1031 psHWRTData->ui32PPPScreen = ui32PPPScreen;
1032 psHWRTData->ui32PPPGridOffset = ui32PPPGridOffset;
1033 psHWRTData->ui64PPPMultiSampleCtl = ui64PPPMultiSampleCtl;
1034 psHWRTData->ui32TPCStride = ui32TPCStride;
1035 psHWRTData->sTailPtrsDevVAddr = sTailPtrsDevVAddr;
1036 psHWRTData->ui32TPCSize = ui32TPCSize;
1037 psHWRTData->ui32TEScreen = ui32TEScreen;
1038 psHWRTData->ui32TEAA = ui32TEAA;
1039 psHWRTData->ui32TEMTILE1 = ui32TEMTILE1;
1040 psHWRTData->ui32TEMTILE2 = ui32TEMTILE2;
1041 psHWRTData->ui32MTileStride = ui32MTileStride;
1042 psHWRTData->ui32ISPMergeLowerX = ui32ISPMergeLowerX;
1043 psHWRTData->ui32ISPMergeLowerY = ui32ISPMergeLowerY;
1044 psHWRTData->ui32ISPMergeUpperX = ui32ISPMergeUpperX;
1045 psHWRTData->ui32ISPMergeUpperY = ui32ISPMergeUpperY;
1046 psHWRTData->ui32ISPMergeScaleX = ui32ISPMergeScaleX;
1047 psHWRTData->ui32ISPMergeScaleY = ui32ISPMergeScaleY;
1049 OSLockAcquire(psDevInfo->hLockFreeList);
1050 for (ui32Loop = 0; ui32Loop < RGXFW_MAX_FREELISTS; ui32Loop++)
1052 psTmpCleanup->apsFreeLists[ui32Loop] = apsFreeLists[ui32Loop];
1053 psTmpCleanup->apsFreeLists[ui32Loop]->ui32RefCount++;
1054 psHWRTData->apsFreeLists[ui32Loop] = *((PRGXFWIF_FREELIST *)&(psTmpCleanup->apsFreeLists[ui32Loop]->sFreeListFWDevVAddr.ui32Addr));
1055 /* invalid initial snapshot value, the snapshot is always taken during first kick
1056 * and hence the value get replaced during the first kick anyway. So its safe to set it 0.
1058 psHWRTData->aui32FreeListHWRSnapshot[ui32Loop] = 0;
1060 OSLockRelease(psDevInfo->hLockFreeList);
1062 PDUMPCOMMENT("Allocate RGXFW RTA control");
1063 eError = DevmemFwAllocate(psDevInfo,
1064 sizeof(RGXFWIF_RTA_CTL),
1065 PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
1066 PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(META_CACHED) |
1067 PVRSRV_MEMALLOCFLAG_GPU_READABLE |
1068 PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
1069 PVRSRV_MEMALLOCFLAG_UNCACHED |
1070 PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC,
1071 "FirmwareRTAControl",
1074 if (eError != PVRSRV_OK)
1076 PVR_DPF((PVR_DBG_ERROR,"RGXCreateHWRTData: Failed to allocate RGX RTA control (%u)",
1078 goto FWRTAAllocateError;
1080 psTmpCleanup->psRTACtlMemDesc = *ppsRTACtlMemDesc;
1081 RGXSetFirmwareAddress(&psHWRTData->psRTACtl,
1083 0, RFW_FWADDR_FLAG_NONE);
1085 eError = DevmemAcquireCpuVirtAddr(*ppsRTACtlMemDesc, (IMG_VOID **)&psRTACtl);
1086 PVR_LOGG_IF_ERROR(eError, "Devmem AcquireCpuVirtAddr", FWRTACpuMapError);
1087 psRTACtl->ui32RenderTargetIndex = 0;
1088 psRTACtl->ui32ActiveRenderTargets = 0;
1092 /* Allocate memory for the checks */
1093 PDUMPCOMMENT("Allocate memory for shadow render target cache");
1094 eError = DevmemFwAllocate(psDevInfo,
1096 PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
1097 PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(META_CACHED) |
1098 PVRSRV_MEMALLOCFLAG_GPU_READABLE |
1099 PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
1100 PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
1101 PVRSRV_MEMALLOCFLAG_UNCACHED|
1102 PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC,
1103 "FirmwareShadowRTCache",
1104 &psTmpCleanup->psRTArrayMemDesc);
1105 if (eError != PVRSRV_OK)
1107 PVR_DPF((PVR_DBG_ERROR,"RGXCreateHWRTData: Failed to allocate %d bytes for render target array (%u)",
1110 goto FWAllocateRTArryError;
1113 RGXSetFirmwareAddress(&psRTACtl->paui32ValidRenderTargets,
1114 psTmpCleanup->psRTArrayMemDesc,
1115 0, RFW_FWADDR_FLAG_NONE);
1119 psRTACtl->paui32ValidRenderTargets.ui32Addr = 0;
1122 PDUMPCOMMENT("Dump HWRTData 0x%08X", *puiHWRTData);
1123 DevmemPDumpLoadMem(*ppsMemDesc, 0, sizeof(*psHWRTData), PDUMP_FLAGS_CONTINUOUS);
1124 PDUMPCOMMENT("Dump RTACtl");
1125 DevmemPDumpLoadMem(*ppsRTACtlMemDesc, 0, sizeof(*psRTACtl), PDUMP_FLAGS_CONTINUOUS);
1127 DevmemReleaseCpuVirtAddr(*ppsMemDesc);
1128 DevmemReleaseCpuVirtAddr(*ppsRTACtlMemDesc);
1131 DevmemFwFree(psTmpCleanup->psRTArrayMemDesc);
1132 FWAllocateRTArryError:
1133 DevmemReleaseCpuVirtAddr(*ppsRTACtlMemDesc);
1135 RGXUnsetFirmwareAddress(*ppsRTACtlMemDesc);
1136 DevmemFwFree(*ppsRTACtlMemDesc);
1138 OSLockAcquire(psDevInfo->hLockFreeList);
1139 for (ui32Loop = 0; ui32Loop < RGXFW_MAX_FREELISTS; ui32Loop++)
1141 PVR_ASSERT(psTmpCleanup->apsFreeLists[ui32Loop]->ui32RefCount > 0);
1142 psTmpCleanup->apsFreeLists[ui32Loop]->ui32RefCount--;
1144 OSLockRelease(psDevInfo->hLockFreeList);
1145 DevmemReleaseCpuVirtAddr(*ppsMemDesc);
1146 FWRTDataCpuMapError:
1147 RGXUnsetFirmwareAddress(*ppsMemDesc);
1148 DevmemFwFree(*ppsMemDesc);
1149 FWRTDataAllocateError:
1150 SyncPrimFree(psTmpCleanup->psCleanupSync);
1152 OSFreeMem(psTmpCleanup);
1158 /* Destroy HWRTDataSet */
1160 PVRSRV_ERROR RGXDestroyHWRTData(RGX_RTDATA_CLEANUP_DATA *psCleanupData)
1162 PVRSRV_RGXDEV_INFO *psDevInfo;
1163 PVRSRV_ERROR eError;
1164 PRGXFWIF_HWRTDATA psHWRTData;
1165 IMG_UINT32 ui32Loop;
1167 PVR_ASSERT(psCleanupData);
1169 RGXSetFirmwareAddress(&psHWRTData, psCleanupData->psFWHWRTDataMemDesc, 0, RFW_FWADDR_NOREF_FLAG);
1171 /* Cleanup HWRTData in TA */
1172 eError = RGXFWRequestHWRTDataCleanUp(psCleanupData->psDeviceNode,
1174 psCleanupData->psCleanupSync,
1176 if (eError == PVRSRV_ERROR_RETRY)
1181 psDevInfo = psCleanupData->psDeviceNode->pvDevice;
1183 /* Cleanup HWRTData in 3D */
1184 eError = RGXFWRequestHWRTDataCleanUp(psCleanupData->psDeviceNode,
1186 psCleanupData->psCleanupSync,
1188 if (eError == PVRSRV_ERROR_RETRY)
1193 /* If we got here then TA and 3D operations on this RTData have finished */
1194 if(psCleanupData->psRTACtlMemDesc)
1196 RGXUnsetFirmwareAddress(psCleanupData->psRTACtlMemDesc);
1197 DevmemFwFree(psCleanupData->psRTACtlMemDesc);
1200 RGXUnsetFirmwareAddress(psCleanupData->psFWHWRTDataMemDesc);
1201 DevmemFwFree(psCleanupData->psFWHWRTDataMemDesc);
1203 if(psCleanupData->psRTArrayMemDesc)
1205 RGXUnsetFirmwareAddress(psCleanupData->psRTArrayMemDesc);
1206 DevmemFwFree(psCleanupData->psRTArrayMemDesc);
1209 SyncPrimFree(psCleanupData->psCleanupSync);
1211 /* decrease freelist refcount */
1212 OSLockAcquire(psDevInfo->hLockFreeList);
1213 for (ui32Loop = 0; ui32Loop < RGXFW_MAX_FREELISTS; ui32Loop++)
1215 PVR_ASSERT(psCleanupData->apsFreeLists[ui32Loop]->ui32RefCount > 0);
1216 psCleanupData->apsFreeLists[ui32Loop]->ui32RefCount--;
1218 OSLockRelease(psDevInfo->hLockFreeList);
1220 OSFreeMem(psCleanupData);
1226 PVRSRV_ERROR RGXCreateFreeList(PVRSRV_DEVICE_NODE *psDeviceNode,
1227 IMG_UINT32 ui32MaxFLPages,
1228 IMG_UINT32 ui32InitFLPages,
1229 IMG_UINT32 ui32GrowFLPages,
1230 IMG_BOOL bCheckFreelist,
1231 IMG_DEV_VIRTADDR sFreeListDevVAddr,
1233 IMG_DEVMEM_OFFSET_T uiFreeListPMROffset,
1234 RGX_FREELIST **ppsFreeList)
1236 PVRSRV_ERROR eError;
1237 RGXFWIF_FREELIST *psFWFreeList;
1238 DEVMEM_MEMDESC *psFWFreelistMemDesc;
1239 RGX_FREELIST *psFreeList;
1240 PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
1242 /* Allocate kernel freelist struct */
1243 psFreeList = OSAllocMem(sizeof(*psFreeList));
1244 if (psFreeList == IMG_NULL)
1246 PVR_DPF((PVR_DBG_ERROR, "RGXCreateFreeList: failed to allocate host data structure"));
1247 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1248 goto ErrorAllocHost;
1250 OSMemSet(psFreeList, 0, sizeof(*psFreeList));
1252 /* Allocate cleanup sync */
1253 eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext,
1254 &psFreeList->psCleanupSync,
1255 "ta3d free list cleanup");
1256 if (eError != PVRSRV_OK)
1258 PVR_DPF((PVR_DBG_ERROR,"RGXCreateFreeList: Failed to allocate cleanup sync (0x%x)",
1264 * This FW FreeList context is only mapped into kernel for initialisation.
1265 * Otherwise this allocation is only used by the FW.
1266 * Therefore the GPU cache doesn't need coherency,
1267 * and write-combine is suffice on the CPU side (WC buffer will be flushed at the first TA-kick)
1269 eError = DevmemFwAllocate(psDevInfo,
1270 sizeof(*psFWFreeList),
1271 PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
1272 PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
1273 PVRSRV_MEMALLOCFLAG_GPU_READABLE |
1274 PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
1275 PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
1276 PVRSRV_MEMALLOCFLAG_CPU_READABLE |
1277 PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
1278 PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE |
1279 PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE,
1281 &psFWFreelistMemDesc);
1282 if (eError != PVRSRV_OK)
1284 PVR_DPF((PVR_DBG_ERROR, "RGXCreateFreeList: DevmemAllocate for RGXFWIF_FREELIST failed"));
1285 goto FWFreeListAlloc;
1288 /* Initialise host data structures */
1289 psFreeList->psDevInfo = psDevInfo;
1290 psFreeList->psFreeListPMR = psFreeListPMR;
1291 psFreeList->uiFreeListPMROffset = uiFreeListPMROffset;
1292 psFreeList->psFWFreelistMemDesc = psFWFreelistMemDesc;
1293 RGXSetFirmwareAddress(&psFreeList->sFreeListFWDevVAddr, psFWFreelistMemDesc, 0, RFW_FWADDR_FLAG_NONE);
1294 psFreeList->ui32FreelistID = psDevInfo->ui32FreelistCurrID++;
1295 psFreeList->ui32MaxFLPages = ui32MaxFLPages;
1296 psFreeList->ui32InitFLPages = ui32InitFLPages;
1297 psFreeList->ui32GrowFLPages = ui32GrowFLPages;
1298 psFreeList->ui32CurrentFLPages = 0;
1299 psFreeList->ui64FreelistChecksum = 0;
1300 psFreeList->ui32RefCount = 0;
1301 psFreeList->bCheckFreelist = bCheckFreelist;
1302 dllist_init(&psFreeList->sMemoryBlockHead);
1303 dllist_init(&psFreeList->sMemoryBlockInitHead);
1306 /* Add to list of freelists */
1307 OSLockAcquire(psDevInfo->hLockFreeList);
1308 dllist_add_to_tail(&psDevInfo->sFreeListHead, &psFreeList->sNode);
1309 OSLockRelease(psDevInfo->hLockFreeList);
1312 /* Initialise FW data structure */
1313 eError = DevmemAcquireCpuVirtAddr(psFreeList->psFWFreelistMemDesc, (IMG_VOID **)&psFWFreeList);
1314 PVR_LOGG_IF_ERROR(eError, "Devmem AcquireCpuVirtAddr", FWFreeListCpuMap);
1315 psFWFreeList->ui32MaxPages = ui32MaxFLPages;
1316 psFWFreeList->ui32CurrentPages = ui32InitFLPages;
1317 psFWFreeList->ui32GrowPages = ui32GrowFLPages;
1318 psFWFreeList->ui64CurrentStackTop = ui32InitFLPages - 1;
1319 psFWFreeList->psFreeListDevVAddr = sFreeListDevVAddr;
1320 psFWFreeList->ui64CurrentDevVAddr = sFreeListDevVAddr.uiAddr + ((ui32MaxFLPages - ui32InitFLPages) * sizeof(IMG_UINT32));
1321 psFWFreeList->ui32FreeListID = psFreeList->ui32FreelistID;
1322 psFWFreeList->bGrowPending = IMG_FALSE;
1324 PVR_DPF((PVR_DBG_MESSAGE,"Freelist %p created: Max pages 0x%08x, Init pages 0x%08x, Max FL base address 0x%016llx, Init FL base address 0x%016llx",
1328 sFreeListDevVAddr.uiAddr,
1329 psFWFreeList->psFreeListDevVAddr.uiAddr));
1331 PDUMPCOMMENT("Dump FW FreeList");
1332 DevmemPDumpLoadMem(psFreeList->psFWFreelistMemDesc, 0, sizeof(*psFWFreeList), PDUMP_FLAGS_CONTINUOUS);
1335 * Separate dump of the Freelist's number of Pages and stack pointer.
1336 * This allows to easily modify the PB size in the out2.txt files.
1338 PDUMPCOMMENT("FreeList TotalPages");
1339 DevmemPDumpLoadMemValue64(psFreeList->psFWFreelistMemDesc,
1340 offsetof(RGXFWIF_FREELIST, ui32CurrentPages),
1341 psFWFreeList->ui32CurrentPages,
1342 PDUMP_FLAGS_CONTINUOUS);
1343 PDUMPCOMMENT("FreeList StackPointer");
1344 DevmemPDumpLoadMemValue64(psFreeList->psFWFreelistMemDesc,
1345 offsetof(RGXFWIF_FREELIST, ui64CurrentStackTop),
1346 psFWFreeList->ui64CurrentStackTop,
1347 PDUMP_FLAGS_CONTINUOUS);
1349 DevmemReleaseCpuVirtAddr(psFreeList->psFWFreelistMemDesc);
1352 /* Add initial PB block */
1353 eError = RGXGrowFreeList(psFreeList,
1355 &psFreeList->sMemoryBlockInitHead);
1356 if (eError != PVRSRV_OK)
1358 PVR_DPF((PVR_DBG_ERROR,
1359 "RGXCreateFreeList: failed to allocate initial memory block for free list 0x%016llx (error = %u)",
1360 sFreeListDevVAddr.uiAddr,
1362 goto ErrorAllocBlock;
1364 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
1366 PVRSRVStatsUpdateFreelistStats(1, /* Add 1 to the appropriate counter (Requests by App)*/
1368 psFreeList->ui32InitFLPages,
1369 psFreeList->ui32NumHighPages,
1370 psFreeList->ownerPid);
1374 psFreeList->ownerPid = OSGetCurrentProcessIDKM();
1376 *ppsFreeList = psFreeList;
1380 /* Error handling */
1383 DevmemReleaseCpuVirtAddr(psFreeList->psFWFreelistMemDesc);
1386 /* Remove freelists from list */
1387 OSLockAcquire(psDevInfo->hLockFreeList);
1388 dllist_remove_node(&psFreeList->sNode);
1389 OSLockRelease(psDevInfo->hLockFreeList);
1391 RGXUnsetFirmwareAddress(psFWFreelistMemDesc);
1392 DevmemFwFree(psFWFreelistMemDesc);
1395 SyncPrimFree(psFreeList->psCleanupSync);
1398 OSFreeMem(psFreeList);
1401 PVR_ASSERT(eError != PVRSRV_OK);
1410 PVRSRV_ERROR RGXDestroyFreeList(RGX_FREELIST *psFreeList)
1412 PVRSRV_ERROR eError;
1413 IMG_UINT64 ui64CheckSum;
1415 PVR_ASSERT(psFreeList);
1417 if (psFreeList->ui32RefCount != 0)
1419 /* Freelist still busy */
1420 return PVRSRV_ERROR_RETRY;
1423 /* Freelist is not in use => start firmware cleanup */
1424 eError = RGXFWRequestFreeListCleanUp(psFreeList->psDevInfo,
1425 psFreeList->sFreeListFWDevVAddr,
1426 psFreeList->psCleanupSync);
1427 if(eError != PVRSRV_OK)
1429 /* Can happen if the firmware took too long to handle the cleanup request,
1430 * or if SLC-flushes didn't went through (due to some GPU lockup) */
1434 if (psFreeList->bCheckFreelist)
1436 /* Do consistency tests (as the list is fully populated) */
1437 eError = _FreeListCheckSum(psFreeList,
1439 if (eError != PVRSRV_OK)
1441 PVR_DPF((PVR_DBG_ERROR,
1442 "RGXDestroyFreeList: Failed to get freelist checksum Node %p",
1448 if (psFreeList->ui64FreelistChecksum != ui64CheckSum)
1450 PVR_DPF((PVR_DBG_ERROR,
1451 "RGXDestroyFreeList: Checksum mismatch [%p]! stored 0x%016llx, verified 0x%016llx %p",
1453 psFreeList->ui64FreelistChecksum,
1461 /* Destroy FW structures */
1462 RGXUnsetFirmwareAddress(psFreeList->psFWFreelistMemDesc);
1463 DevmemFwFree(psFreeList->psFWFreelistMemDesc);
1465 /* Remove grow shrink blocks */
1466 while (!dllist_is_empty(&psFreeList->sMemoryBlockHead))
1468 eError = RGXShrinkFreeList(&psFreeList->sMemoryBlockHead, psFreeList);
1469 PVR_ASSERT(eError == PVRSRV_OK);
1472 /* Remove initial PB block */
1473 eError = RGXShrinkFreeList(&psFreeList->sMemoryBlockInitHead, psFreeList);
1474 PVR_ASSERT(eError == PVRSRV_OK);
1476 /* consistency checks */
1477 PVR_ASSERT(dllist_is_empty(&psFreeList->sMemoryBlockInitHead));
1478 PVR_ASSERT(psFreeList->ui32CurrentFLPages == 0);
1480 /* Remove FreeList from list */
1481 OSLockAcquire(psFreeList->psDevInfo->hLockFreeList);
1482 dllist_remove_node(&psFreeList->sNode);
1483 OSLockRelease(psFreeList->psDevInfo->hLockFreeList);
1485 SyncPrimFree(psFreeList->psCleanupSync);
1488 OSFreeMem(psFreeList);
1496 RGXAddBlockToFreeListKM
1500 PVRSRV_ERROR RGXAddBlockToFreeListKM(RGX_FREELIST *psFreeList,
1501 IMG_UINT32 ui32NumPages)
1503 PVRSRV_ERROR eError;
1505 /* Check if we have reference to freelist's PMR */
1506 if (psFreeList->psFreeListPMR == IMG_NULL)
1508 PVR_DPF((PVR_DBG_ERROR, "Freelist is not configured for grow"));
1509 return PVRSRV_ERROR_INVALID_PARAMS;
1513 eError = RGXGrowFreeList(psFreeList,
1515 &psFreeList->sMemoryBlockHead);
1516 if(eError == PVRSRV_OK)
1518 /* update freelist data in firmware */
1519 _UpdateFwFreelistSize(psFreeList, IMG_TRUE, ui32NumPages);
1521 psFreeList->ui32NumGrowReqByApp++;
1523 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
1525 PVRSRVStatsUpdateFreelistStats(1, /* Add 1 to the appropriate counter (Requests by App)*/
1527 psFreeList->ui32InitFLPages,
1528 psFreeList->ui32NumHighPages,
1529 psFreeList->ownerPid);
1538 RGXRemoveBlockFromFreeListKM
1542 PVRSRV_ERROR RGXRemoveBlockFromFreeListKM(RGX_FREELIST *psFreeList)
1544 PVRSRV_ERROR eError;
1547 * Make sure the pages part of the memory block are not in use anymore.
1548 * Instruct the firmware to update the freelist pointers accordingly.
1551 eError = RGXShrinkFreeList(&psFreeList->sMemoryBlockHead,
1559 RGXCreateRenderTarget
1562 PVRSRV_ERROR RGXCreateRenderTarget(PVRSRV_DEVICE_NODE *psDeviceNode,
1563 IMG_DEV_VIRTADDR psVHeapTableDevVAddr,
1564 RGX_RT_CLEANUP_DATA **ppsCleanupData,
1565 IMG_UINT32 *sRenderTargetFWDevVAddr)
1567 PVRSRV_ERROR eError = PVRSRV_OK;
1568 RGXFWIF_RENDER_TARGET *psRenderTarget;
1569 RGXFWIF_DEV_VIRTADDR pFirmwareAddr;
1570 PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
1571 RGX_RT_CLEANUP_DATA *psCleanupData;
1573 psCleanupData = OSAllocMem(sizeof(*psCleanupData));
1574 if (psCleanupData == IMG_NULL)
1576 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1580 OSMemSet(psCleanupData, 0, sizeof(*psCleanupData));
1581 psCleanupData->psDeviceNode = psDeviceNode;
1583 * This FW render target context is only mapped into kernel for initialisation.
1584 * Otherwise this allocation is only used by the FW.
1585 * Therefore the GPU cache doesn't need coherency,
1586 * and write-combine is suffice on the CPU side (WC buffer will be flushed at the first TA-kick)
1588 eError = DevmemFwAllocate(psDevInfo,
1589 sizeof(*psRenderTarget),
1590 PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
1591 PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
1592 PVRSRV_MEMALLOCFLAG_GPU_READABLE |
1593 PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
1594 PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
1595 PVRSRV_MEMALLOCFLAG_CPU_READABLE |
1596 PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
1597 PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE |
1598 PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE,
1599 "FirmwareRenderTarget",
1600 &psCleanupData->psRenderTargetMemDesc);
1601 if (eError != PVRSRV_OK)
1603 PVR_DPF((PVR_DBG_ERROR, "RGXCreateRenderTarget: DevmemAllocate for Render Target failed"));
1606 RGXSetFirmwareAddress(&pFirmwareAddr, psCleanupData->psRenderTargetMemDesc, 0, RFW_FWADDR_FLAG_NONE);
1607 *sRenderTargetFWDevVAddr = pFirmwareAddr.ui32Addr;
1609 eError = DevmemAcquireCpuVirtAddr(psCleanupData->psRenderTargetMemDesc, (IMG_VOID **)&psRenderTarget);
1610 PVR_LOGG_IF_ERROR(eError, "Devmem AcquireCpuVirtAddr", err_fwalloc);
1612 psRenderTarget->psVHeapTableDevVAddr = psVHeapTableDevVAddr;
1613 psRenderTarget->bTACachesNeedZeroing = IMG_FALSE;
1614 PDUMPCOMMENT("Dump RenderTarget");
1615 DevmemPDumpLoadMem(psCleanupData->psRenderTargetMemDesc, 0, sizeof(*psRenderTarget), PDUMP_FLAGS_CONTINUOUS);
1616 DevmemReleaseCpuVirtAddr(psCleanupData->psRenderTargetMemDesc);
1618 *ppsCleanupData = psCleanupData;
1624 OSFreeMem(psCleanupData);
1628 DevmemFwFree(psCleanupData->psRenderTargetMemDesc);
1635 RGXDestroyRenderTarget
1638 PVRSRV_ERROR RGXDestroyRenderTarget(RGX_RT_CLEANUP_DATA *psCleanupData)
1640 RGXUnsetFirmwareAddress(psCleanupData->psRenderTargetMemDesc);
1644 When we get RT cleanup in the FW call that instead
1646 /* Flush the the SLC before freeing */
1648 RGXFWIF_KCCB_CMD sFlushInvalCmd;
1649 PVRSRV_ERROR eError;
1650 PVRSRV_DEVICE_NODE *psDeviceNode = psCleanupData->psDeviceNode;
1652 /* Schedule the SLC flush command ... */
1654 PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Submit SLC flush and invalidate");
1656 sFlushInvalCmd.eCmdType = RGXFWIF_KCCB_CMD_SLCFLUSHINVAL;
1657 sFlushInvalCmd.uCmdData.sSLCFlushInvalData.bInval = IMG_TRUE;
1658 sFlushInvalCmd.uCmdData.sSLCFlushInvalData.eDM = RGXFWIF_DM_2D; //Covers all of Sidekick
1659 sFlushInvalCmd.uCmdData.sSLCFlushInvalData.psContext.ui32Addr = 0;
1661 eError = RGXSendCommandWithPowLock(psDeviceNode->pvDevice,
1664 sizeof(sFlushInvalCmd),
1666 if (eError != PVRSRV_OK)
1668 PVR_DPF((PVR_DBG_ERROR,"RGXDestroyRenderTarget: Failed to schedule SLC flush command with error (%u)", eError));
1672 /* Wait for the SLC flush to complete */
1673 eError = RGXWaitForFWOp(psDeviceNode->pvDevice, RGXFWIF_DM_GP, psDeviceNode->psSyncPrim, IMG_TRUE);
1674 if (eError != PVRSRV_OK)
1676 PVR_DPF((PVR_DBG_ERROR,"RGXDestroyRenderTarget: SLC flush and invalidate aborted with error (%u)", eError));
1681 DevmemFwFree(psCleanupData->psRenderTargetMemDesc);
1682 OSFreeMem(psCleanupData);
1690 PVRSRV_ERROR RGXCreateZSBufferKM(PVRSRV_DEVICE_NODE *psDeviceNode,
1691 DEVMEMINT_RESERVATION *psReservation,
1693 PVRSRV_MEMALLOCFLAGS_T uiMapFlags,
1694 RGX_ZSBUFFER_DATA **ppsZSBuffer,
1695 IMG_UINT32 *pui32ZSBufferFWDevVAddr)
1697 PVRSRV_ERROR eError;
1698 PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
1699 RGXFWIF_FWZSBUFFER *psFWZSBuffer;
1700 RGX_ZSBUFFER_DATA *psZSBuffer;
1701 DEVMEM_MEMDESC *psFWZSBufferMemDesc;
1702 IMG_BOOL bOnDemand = ((uiMapFlags & PVRSRV_MEMALLOCFLAG_NO_OSPAGES_ON_ALLOC) > 0);
1704 /* Allocate host data structure */
1705 psZSBuffer = OSAllocMem(sizeof(*psZSBuffer));
1706 if (psZSBuffer == IMG_NULL)
1708 PVR_DPF((PVR_DBG_ERROR,"RGXCreateZSBufferKM: Failed to allocate cleanup data structure for ZS-Buffer"));
1709 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1710 goto ErrorAllocCleanup;
1712 OSMemSet(psZSBuffer, 0, sizeof(*psZSBuffer));
1714 eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext,
1715 &psZSBuffer->psCleanupSync,
1716 "ta3d zs buffer cleanup");
1717 if (eError != PVRSRV_OK)
1719 PVR_DPF((PVR_DBG_ERROR,"RGXCreateZSBufferKM: Failed to allocate cleanup sync (0x%x)",
1721 goto ErrorSyncAlloc;
1724 /* Populate Host data */
1725 psZSBuffer->psDevInfo = psDevInfo;
1726 psZSBuffer->psReservation = psReservation;
1727 psZSBuffer->psPMR = psPMR;
1728 psZSBuffer->uiMapFlags = uiMapFlags;
1729 psZSBuffer->ui32RefCount = 0;
1730 psZSBuffer->bOnDemand = bOnDemand;
1733 psZSBuffer->ui32ZSBufferID = psDevInfo->ui32ZSBufferCurrID++;
1734 psZSBuffer->psMapping = IMG_NULL;
1736 OSLockAcquire(psDevInfo->hLockZSBuffer);
1737 dllist_add_to_tail(&psDevInfo->sZSBufferHead, &psZSBuffer->sNode);
1738 OSLockRelease(psDevInfo->hLockZSBuffer);
1741 /* Allocate firmware memory for ZS-Buffer. */
1742 PDUMPCOMMENT("Allocate firmware ZS-Buffer data structure");
1743 eError = DevmemFwAllocate(psDevInfo,
1744 sizeof(*psFWZSBuffer),
1745 PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
1746 PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
1747 PVRSRV_MEMALLOCFLAG_GPU_READABLE |
1748 PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
1749 PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
1750 PVRSRV_MEMALLOCFLAG_CPU_READABLE |
1751 PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
1752 PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE |
1753 PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE,
1755 &psFWZSBufferMemDesc);
1756 if (eError != PVRSRV_OK)
1758 PVR_DPF((PVR_DBG_ERROR,"RGXCreateZSBufferKM: Failed to allocate firmware ZS-Buffer (%u)", eError));
1759 goto ErrorAllocFWZSBuffer;
1761 psZSBuffer->psZSBufferMemDesc = psFWZSBufferMemDesc;
1763 /* Temporarily map the firmware render context to the kernel. */
1764 eError = DevmemAcquireCpuVirtAddr(psFWZSBufferMemDesc,
1765 (IMG_VOID **)&psFWZSBuffer);
1766 if (eError != PVRSRV_OK)
1768 PVR_DPF((PVR_DBG_ERROR,"RGXCreateZSBufferKM: Failed to map firmware ZS-Buffer (%u)", eError));
1769 goto ErrorAcquireFWZSBuffer;
1772 /* Populate FW ZS-Buffer data structure */
1773 psFWZSBuffer->bOnDemand = bOnDemand;
1774 psFWZSBuffer->eState = (bOnDemand) ? RGXFWIF_ZSBUFFER_UNBACKED : RGXFWIF_ZSBUFFER_BACKED;
1775 psFWZSBuffer->ui32ZSBufferID = psZSBuffer->ui32ZSBufferID;
1777 /* Get firmware address of ZS-Buffer. */
1778 RGXSetFirmwareAddress(&psZSBuffer->sZSBufferFWDevVAddr, psFWZSBufferMemDesc, 0, RFW_FWADDR_FLAG_NONE);
1780 /* Dump the ZS-Buffer and the memory content */
1781 PDUMPCOMMENT("Dump firmware ZS-Buffer");
1782 DevmemPDumpLoadMem(psFWZSBufferMemDesc, 0, sizeof(*psFWZSBuffer), PDUMP_FLAGS_CONTINUOUS);
1784 /* Release address acquired above. */
1785 DevmemReleaseCpuVirtAddr(psFWZSBufferMemDesc);
1788 /* define return value */
1789 *ppsZSBuffer = psZSBuffer;
1790 *pui32ZSBufferFWDevVAddr = psZSBuffer->sZSBufferFWDevVAddr.ui32Addr;
1792 PVR_DPF((PVR_DBG_MESSAGE, "ZS-Buffer [%p] created (%s)",
1794 (bOnDemand) ? "On-Demand": "Up-front"));
1796 psZSBuffer->owner=OSGetCurrentProcessIDKM();
1800 /* error handling */
1802 ErrorAcquireFWZSBuffer:
1803 DevmemFwFree(psFWZSBufferMemDesc);
1805 ErrorAllocFWZSBuffer:
1806 SyncPrimFree(psZSBuffer->psCleanupSync);
1809 OSFreeMem(psZSBuffer);
1812 PVR_ASSERT(eError != PVRSRV_OK);
1821 PVRSRV_ERROR RGXDestroyZSBufferKM(RGX_ZSBUFFER_DATA *psZSBuffer)
1823 POS_LOCK hLockZSBuffer;
1824 PVRSRV_ERROR eError;
1826 PVR_ASSERT(psZSBuffer);
1827 hLockZSBuffer = psZSBuffer->psDevInfo->hLockZSBuffer;
1829 /* Request ZS Buffer cleanup */
1830 eError = RGXFWRequestZSBufferCleanUp(psZSBuffer->psDevInfo,
1831 psZSBuffer->sZSBufferFWDevVAddr,
1832 psZSBuffer->psCleanupSync);
1833 if (eError != PVRSRV_ERROR_RETRY)
1835 /* Free the firmware render context. */
1836 RGXUnsetFirmwareAddress(psZSBuffer->psZSBufferMemDesc);
1837 DevmemFwFree(psZSBuffer->psZSBufferMemDesc);
1839 /* Remove Deferred Allocation from list */
1840 if (psZSBuffer->bOnDemand)
1842 OSLockAcquire(hLockZSBuffer);
1843 PVR_ASSERT(dllist_node_is_in_list(&psZSBuffer->sNode));
1844 dllist_remove_node(&psZSBuffer->sNode);
1845 OSLockRelease(hLockZSBuffer);
1848 SyncPrimFree(psZSBuffer->psCleanupSync);
1850 PVR_ASSERT(psZSBuffer->ui32RefCount == 0);
1852 PVR_DPF((PVR_DBG_MESSAGE,"ZS-Buffer [%p] destroyed",psZSBuffer));
1854 /* Free ZS-Buffer host data structure */
1855 OSFreeMem(psZSBuffer);
1863 RGXBackingZSBuffer(RGX_ZSBUFFER_DATA *psZSBuffer)
1865 POS_LOCK hLockZSBuffer;
1866 PVRSRV_ERROR eError;
1870 return PVRSRV_ERROR_INVALID_PARAMS;
1873 if ((psZSBuffer->uiMapFlags & PVRSRV_MEMALLOCFLAG_NO_OSPAGES_ON_ALLOC) == 0)
1875 /* Only deferred allocations can be populated */
1876 return PVRSRV_ERROR_INVALID_PARAMS;
1879 PVR_DPF((PVR_DBG_MESSAGE,"ZS Buffer [%p, ID=0x%08x]: Physical backing requested",
1881 psZSBuffer->ui32ZSBufferID));
1882 hLockZSBuffer = psZSBuffer->psDevInfo->hLockZSBuffer;
1884 OSLockAcquire(hLockZSBuffer);
1886 if (psZSBuffer->ui32RefCount == 0)
1888 if (psZSBuffer->bOnDemand)
1890 IMG_HANDLE hDevmemHeap;
1892 PVR_ASSERT(psZSBuffer->psMapping == IMG_NULL);
1895 eError = DevmemServerGetHeapHandle(psZSBuffer->psReservation, &hDevmemHeap);
1896 PVR_ASSERT(psZSBuffer->psMapping == IMG_NULL);
1898 eError = DevmemIntMapPMR(hDevmemHeap,
1899 psZSBuffer->psReservation,
1901 psZSBuffer->uiMapFlags,
1902 &psZSBuffer->psMapping);
1903 if (eError != PVRSRV_OK)
1905 PVR_DPF((PVR_DBG_ERROR,"Unable populate ZS Buffer [%p, ID=0x%08x] with error %u",
1907 psZSBuffer->ui32ZSBufferID,
1909 OSLockRelease(hLockZSBuffer);
1913 PVR_DPF((PVR_DBG_MESSAGE, "ZS Buffer [%p, ID=0x%08x]: Physical backing acquired",
1915 psZSBuffer->ui32ZSBufferID));
1919 /* Increase refcount*/
1920 psZSBuffer->ui32RefCount++;
1922 OSLockRelease(hLockZSBuffer);
1929 RGXPopulateZSBufferKM(RGX_ZSBUFFER_DATA *psZSBuffer,
1930 RGX_POPULATION **ppsPopulation)
1932 RGX_POPULATION *psPopulation;
1933 PVRSRV_ERROR eError;
1935 psZSBuffer->ui32NumReqByApp++;
1937 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
1938 PVRSRVStatsUpdateZSBufferStats(1,0,psZSBuffer->owner);
1941 /* Do the backing */
1942 eError = RGXBackingZSBuffer(psZSBuffer);
1943 if (eError != PVRSRV_OK)
1945 goto OnErrorBacking;
1948 /* Create the handle to the backing */
1949 psPopulation = OSAllocMem(sizeof(*psPopulation));
1950 if (psPopulation == IMG_NULL)
1952 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1956 psPopulation->psZSBuffer = psZSBuffer;
1959 *ppsPopulation = psPopulation;
1964 RGXUnbackingZSBuffer(psZSBuffer);
1967 PVR_ASSERT(eError != PVRSRV_OK);
1972 RGXUnbackingZSBuffer(RGX_ZSBUFFER_DATA *psZSBuffer)
1974 POS_LOCK hLockZSBuffer;
1975 PVRSRV_ERROR eError;
1979 return PVRSRV_ERROR_INVALID_PARAMS;
1982 PVR_ASSERT(psZSBuffer->ui32RefCount);
1984 PVR_DPF((PVR_DBG_MESSAGE,"ZS Buffer [%p, ID=0x%08x]: Physical backing removal requested",
1986 psZSBuffer->ui32ZSBufferID));
1988 hLockZSBuffer = psZSBuffer->psDevInfo->hLockZSBuffer;
1990 OSLockAcquire(hLockZSBuffer);
1992 if (psZSBuffer->bOnDemand)
1994 if (psZSBuffer->ui32RefCount == 1)
1996 PVR_ASSERT(psZSBuffer->psMapping);
1998 eError = DevmemIntUnmapPMR(psZSBuffer->psMapping);
1999 if (eError != PVRSRV_OK)
2001 PVR_DPF((PVR_DBG_ERROR,"Unable to unpopulate ZS Buffer [%p, ID=0x%08x] with error %u",
2003 psZSBuffer->ui32ZSBufferID,
2005 OSLockRelease(hLockZSBuffer);
2009 PVR_DPF((PVR_DBG_MESSAGE, "ZS Buffer [%p, ID=0x%08x]: Physical backing removed",
2011 psZSBuffer->ui32ZSBufferID));
2015 /* Decrease refcount*/
2016 psZSBuffer->ui32RefCount--;
2018 OSLockRelease(hLockZSBuffer);
2024 RGXUnpopulateZSBufferKM(RGX_POPULATION *psPopulation)
2026 PVRSRV_ERROR eError;
2030 return PVRSRV_ERROR_INVALID_PARAMS;
2033 eError = RGXUnbackingZSBuffer(psPopulation->psZSBuffer);
2034 if (eError != PVRSRV_OK)
2039 OSFreeMem(psPopulation);
2044 static IMG_BOOL _FindZSBuffer(PDLLIST_NODE psNode, IMG_PVOID pvCallbackData)
2046 DEVMEM_REF_LOOKUP *psRefLookUp = (DEVMEM_REF_LOOKUP *)pvCallbackData;
2047 RGX_ZSBUFFER_DATA *psZSBuffer;
2049 psZSBuffer = IMG_CONTAINER_OF(psNode, RGX_ZSBUFFER_DATA, sNode);
2051 if (psZSBuffer->ui32ZSBufferID == psRefLookUp->ui32ZSBufferID)
2053 psRefLookUp->psZSBuffer = psZSBuffer;
2062 IMG_VOID RGXProcessRequestZSBufferBacking(PVRSRV_RGXDEV_INFO *psDevInfo,
2063 IMG_UINT32 ui32ZSBufferID)
2065 DEVMEM_REF_LOOKUP sLookUp;
2066 RGXFWIF_KCCB_CMD sTACCBCmd;
2067 PVRSRV_ERROR eError;
2069 PVR_ASSERT(psDevInfo);
2071 /* scan all deferred allocations */
2072 sLookUp.ui32ZSBufferID = ui32ZSBufferID;
2073 sLookUp.psZSBuffer = IMG_NULL;
2075 OSLockAcquire(psDevInfo->hLockZSBuffer);
2076 dllist_foreach_node(&psDevInfo->sZSBufferHead, _FindZSBuffer, (IMG_PVOID)&sLookUp);
2077 OSLockRelease(psDevInfo->hLockZSBuffer);
2079 if (sLookUp.psZSBuffer)
2081 IMG_BOOL bBackingDone = IMG_TRUE;
2084 eError = RGXBackingZSBuffer(sLookUp.psZSBuffer);
2085 if (eError != PVRSRV_OK)
2087 PVR_DPF((PVR_DBG_ERROR,"Populating ZS-Buffer failed failed with error %u (ID = 0x%08x)", eError, ui32ZSBufferID));
2088 bBackingDone = IMG_FALSE;
2091 /* send confirmation */
2092 sTACCBCmd.eCmdType = RGXFWIF_KCCB_CMD_ZSBUFFER_BACKING_UPDATE;
2093 sTACCBCmd.uCmdData.sZSBufferBackingData.psZSBufferFWDevVAddr = sLookUp.psZSBuffer->sZSBufferFWDevVAddr.ui32Addr;
2094 sTACCBCmd.uCmdData.sZSBufferBackingData.bDone = bBackingDone;
2096 LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
2098 eError = RGXScheduleCommand(psDevInfo,
2103 if (eError != PVRSRV_ERROR_RETRY)
2107 OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
2108 } END_LOOP_UNTIL_TIMEOUT();
2110 /* Kernel CCB should never fill up, as the FW is processing them right away */
2111 PVR_ASSERT(eError == PVRSRV_OK);
2113 sLookUp.psZSBuffer->ui32NumReqByFW++;
2115 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
2116 PVRSRVStatsUpdateZSBufferStats(0,1,sLookUp.psZSBuffer->owner);
2122 PVR_DPF((PVR_DBG_ERROR,"ZS Buffer Lookup for ZS Buffer ID 0x%08x failed (Populate)", sLookUp.ui32ZSBufferID));
2126 IMG_VOID RGXProcessRequestZSBufferUnbacking(PVRSRV_RGXDEV_INFO *psDevInfo,
2127 IMG_UINT32 ui32ZSBufferID)
2129 DEVMEM_REF_LOOKUP sLookUp;
2130 RGXFWIF_KCCB_CMD sTACCBCmd;
2131 PVRSRV_ERROR eError;
2133 PVR_ASSERT(psDevInfo);
2135 /* scan all deferred allocations */
2136 sLookUp.ui32ZSBufferID = ui32ZSBufferID;
2137 sLookUp.psZSBuffer = IMG_NULL;
2139 OSLockAcquire(psDevInfo->hLockZSBuffer);
2140 dllist_foreach_node(&psDevInfo->sZSBufferHead, _FindZSBuffer, (IMG_PVOID)&sLookUp);
2141 OSLockRelease(psDevInfo->hLockZSBuffer);
2143 if (sLookUp.psZSBuffer)
2145 /* Unpopulate ZLS */
2146 eError = RGXUnbackingZSBuffer(sLookUp.psZSBuffer);
2147 if (eError != PVRSRV_OK)
2149 PVR_DPF((PVR_DBG_ERROR,"UnPopulating ZS-Buffer failed failed with error %u (ID = 0x%08x)", eError, ui32ZSBufferID));
2150 PVR_ASSERT(IMG_FALSE);
2153 /* send confirmation */
2154 sTACCBCmd.eCmdType = RGXFWIF_KCCB_CMD_ZSBUFFER_UNBACKING_UPDATE;
2155 sTACCBCmd.uCmdData.sZSBufferBackingData.psZSBufferFWDevVAddr = sLookUp.psZSBuffer->sZSBufferFWDevVAddr.ui32Addr;
2156 sTACCBCmd.uCmdData.sZSBufferBackingData.bDone = IMG_TRUE;
2158 LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
2160 eError = RGXScheduleCommand(psDevInfo,
2165 if (eError != PVRSRV_ERROR_RETRY)
2169 OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
2170 } END_LOOP_UNTIL_TIMEOUT();
2172 /* Kernel CCB should never fill up, as the FW is processing them right away */
2173 PVR_ASSERT(eError == PVRSRV_OK);
2178 PVR_DPF((PVR_DBG_ERROR,"ZS Buffer Lookup for ZS Buffer ID 0x%08x failed (UnPopulate)", sLookUp.ui32ZSBufferID));
2183 PVRSRV_ERROR _CreateTAContext(CONNECTION_DATA *psConnection,
2184 PVRSRV_DEVICE_NODE *psDeviceNode,
2185 DEVMEM_MEMDESC *psAllocatedMemDesc,
2186 IMG_UINT32 ui32AllocatedOffset,
2187 DEVMEM_MEMDESC *psFWMemContextMemDesc,
2188 IMG_DEV_VIRTADDR sVDMCallStackAddr,
2189 IMG_UINT32 ui32Priority,
2190 RGX_COMMON_CONTEXT_INFO *psInfo,
2191 RGX_SERVER_RC_TA_DATA *psTAData)
2193 PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
2194 RGXFWIF_TACTX_STATE *psContextState;
2195 PVRSRV_ERROR eError;
2197 Allocate device memory for the firmware GPU context suspend state.
2198 Note: the FW reads/writes the state to memory by accessing the GPU register interface.
2200 PDUMPCOMMENT("Allocate RGX firmware TA context suspend state");
2202 eError = DevmemFwAllocate(psDevInfo,
2203 sizeof(RGXFWIF_TACTX_STATE),
2204 RGX_FWCOMCTX_ALLOCFLAGS,
2205 "FirmwareTAContextState",
2206 &psTAData->psContextStateMemDesc);
2207 if (eError != PVRSRV_OK)
2209 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRenderContextKM: Failed to allocate firmware GPU context suspend state (%u)",
2211 goto fail_tacontextsuspendalloc;
2214 eError = DevmemAcquireCpuVirtAddr(psTAData->psContextStateMemDesc,
2215 (IMG_VOID **)&psContextState);
2216 if (eError != PVRSRV_OK)
2218 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRenderContextKM: Failed to map firmware render context state (%u)",
2220 goto fail_suspendcpuvirtacquire;
2222 psContextState->uTAReg_VDM_CALL_STACK_POINTER_Init = sVDMCallStackAddr.uiAddr;
2223 DevmemReleaseCpuVirtAddr(psTAData->psContextStateMemDesc);
2225 eError = FWCommonContextAllocate(psConnection,
2229 ui32AllocatedOffset,
2230 psFWMemContextMemDesc,
2231 psTAData->psContextStateMemDesc,
2235 &psTAData->psServerCommonContext);
2236 if (eError != PVRSRV_OK)
2238 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRenderContextKM: Failed to init TA fw common context (%u)",
2240 goto fail_tacommoncontext;
2244 * Dump the FW 3D context suspend state buffer
2246 PDUMPCOMMENT("Dump the TA context suspend state buffer");
2247 DevmemPDumpLoadMem(psTAData->psContextStateMemDesc,
2249 sizeof(RGXFWIF_TACTX_STATE),
2250 PDUMP_FLAGS_CONTINUOUS);
2252 psTAData->ui32Priority = ui32Priority;
2255 fail_tacommoncontext:
2256 fail_suspendcpuvirtacquire:
2257 DevmemFwFree(psTAData->psContextStateMemDesc);
2258 fail_tacontextsuspendalloc:
2259 PVR_ASSERT(eError != PVRSRV_OK);
2265 PVRSRV_ERROR _Create3DContext(CONNECTION_DATA *psConnection,
2266 PVRSRV_DEVICE_NODE *psDeviceNode,
2267 DEVMEM_MEMDESC *psAllocatedMemDesc,
2268 IMG_UINT32 ui32AllocatedOffset,
2269 DEVMEM_MEMDESC *psFWMemContextMemDesc,
2270 IMG_UINT32 ui32Priority,
2271 RGX_COMMON_CONTEXT_INFO *psInfo,
2272 RGX_SERVER_RC_3D_DATA *ps3DData)
2274 PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
2275 PVRSRV_ERROR eError;
2278 Allocate device memory for the firmware GPU context suspend state.
2279 Note: the FW reads/writes the state to memory by accessing the GPU register interface.
2281 PDUMPCOMMENT("Allocate RGX firmware 3D context suspend state");
2283 eError = DevmemFwAllocate(psDevInfo,
2284 sizeof(RGXFWIF_3DCTX_STATE),
2285 RGX_FWCOMCTX_ALLOCFLAGS,
2286 "Firmware3DContextState",
2287 &ps3DData->psContextStateMemDesc);
2288 if (eError != PVRSRV_OK)
2290 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRenderContextKM: Failed to allocate firmware GPU context suspend state (%u)",
2292 goto fail_3dcontextsuspendalloc;
2295 eError = FWCommonContextAllocate(psConnection,
2299 ui32AllocatedOffset,
2300 psFWMemContextMemDesc,
2301 ps3DData->psContextStateMemDesc,
2305 &ps3DData->psServerCommonContext);
2306 if (eError != PVRSRV_OK)
2308 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRenderContextKM: Failed to init 3D fw common context (%u)",
2310 goto fail_3dcommoncontext;
2314 * Dump the FW 3D context suspend state buffer
2316 PDUMPCOMMENT("Dump the 3D context suspend state buffer");
2317 DevmemPDumpLoadMem(ps3DData->psContextStateMemDesc,
2319 sizeof(RGXFWIF_3DCTX_STATE),
2320 PDUMP_FLAGS_CONTINUOUS);
2322 ps3DData->ui32Priority = ui32Priority;
2325 fail_3dcommoncontext:
2326 DevmemFwFree(ps3DData->psContextStateMemDesc);
2327 fail_3dcontextsuspendalloc:
2328 PVR_ASSERT(eError != PVRSRV_OK);
2335 * PVRSRVRGXCreateRenderContextKM
2338 PVRSRV_ERROR PVRSRVRGXCreateRenderContextKM(CONNECTION_DATA *psConnection,
2339 PVRSRV_DEVICE_NODE *psDeviceNode,
2340 IMG_UINT32 ui32Priority,
2341 IMG_DEV_VIRTADDR sMCUFenceAddr,
2342 IMG_DEV_VIRTADDR sVDMCallStackAddr,
2343 IMG_UINT32 ui32FrameworkRegisterSize,
2344 IMG_PBYTE pabyFrameworkRegisters,
2345 IMG_HANDLE hMemCtxPrivData,
2346 RGX_SERVER_RENDER_CONTEXT **ppsRenderContext)
2348 PVRSRV_ERROR eError;
2349 PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
2350 RGX_SERVER_RENDER_CONTEXT *psRenderContext;
2351 DEVMEM_MEMDESC *psFWMemContextMemDesc = RGXGetFWMemDescFromMemoryContextHandle(hMemCtxPrivData);
2352 RGX_COMMON_CONTEXT_INFO sInfo;
2354 /* Prepare cleanup structure */
2355 *ppsRenderContext = IMG_NULL;
2356 psRenderContext = OSAllocMem(sizeof(*psRenderContext));
2357 if (psRenderContext == IMG_NULL)
2359 return PVRSRV_ERROR_OUT_OF_MEMORY;
2362 OSMemSet(psRenderContext, 0, sizeof(*psRenderContext));
2363 psRenderContext->psDeviceNode = psDeviceNode;
2366 Create the FW render context, this has the TA and 3D FW common
2367 contexts embedded within it
2369 eError = DevmemFwAllocate(psDevInfo,
2370 sizeof(RGXFWIF_FWRENDERCONTEXT),
2371 RGX_FWCOMCTX_ALLOCFLAGS,
2372 "FirmwareRenderContext",
2373 &psRenderContext->psFWRenderContextMemDesc);
2374 if (eError != PVRSRV_OK)
2376 goto fail_fwrendercontext;
2380 As the common context alloc will dump the TA and 3D common contexts
2381 after the've been setup we skip of the 2 common contexts and dump the
2382 rest of the structure
2384 PDUMPCOMMENT("Dump shared part of render context context");
2385 DevmemPDumpLoadMem(psRenderContext->psFWRenderContextMemDesc,
2386 (sizeof(RGXFWIF_FWCOMMONCONTEXT) * 2),
2387 sizeof(RGXFWIF_FWRENDERCONTEXT) - (sizeof(RGXFWIF_FWCOMMONCONTEXT) * 2),
2388 PDUMP_FLAGS_CONTINUOUS);
2390 /* Allocate cleanup sync */
2391 eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext,
2392 &psRenderContext->psCleanupSync,
2393 "ta3d render context cleanup");
2394 if (eError != PVRSRV_OK)
2396 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRenderContextKM: Failed to allocate cleanup sync (0x%x)",
2398 goto fail_syncalloc;
2402 * Create the FW framework buffer
2404 eError = PVRSRVRGXFrameworkCreateKM(psDeviceNode,
2405 &psRenderContext->psFWFrameworkMemDesc,
2406 ui32FrameworkRegisterSize);
2407 if (eError != PVRSRV_OK)
2409 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRenderContextKM: Failed to allocate firmware GPU framework state (%u)",
2411 goto fail_frameworkcreate;
2414 /* Copy the Framework client data into the framework buffer */
2415 eError = PVRSRVRGXFrameworkCopyCommand(psRenderContext->psFWFrameworkMemDesc,
2416 pabyFrameworkRegisters,
2417 ui32FrameworkRegisterSize);
2418 if (eError != PVRSRV_OK)
2420 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRenderContextKM: Failed to populate the framework buffer (%u)",
2422 goto fail_frameworkcopy;
2425 sInfo.psFWFrameworkMemDesc = psRenderContext->psFWFrameworkMemDesc;
2426 sInfo.psMCUFenceAddr = &sMCUFenceAddr;
2428 eError = _CreateTAContext(psConnection,
2430 psRenderContext->psFWRenderContextMemDesc,
2431 offsetof(RGXFWIF_FWRENDERCONTEXT, sTAContext),
2432 psFWMemContextMemDesc,
2436 &psRenderContext->sTAData);
2437 if (eError != PVRSRV_OK)
2439 goto fail_tacontext;
2442 eError = _Create3DContext(psConnection,
2444 psRenderContext->psFWRenderContextMemDesc,
2445 offsetof(RGXFWIF_FWRENDERCONTEXT, s3DContext),
2446 psFWMemContextMemDesc,
2449 &psRenderContext->s3DData);
2450 if (eError != PVRSRV_OK)
2452 goto fail_3dcontext;
2455 SyncAddrListInit(&psRenderContext->sSyncAddrListTAFence);
2456 SyncAddrListInit(&psRenderContext->sSyncAddrListTAUpdate);
2457 SyncAddrListInit(&psRenderContext->sSyncAddrList3DFence);
2458 SyncAddrListInit(&psRenderContext->sSyncAddrList3DUpdate);
2461 PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
2463 OSWRLockAcquireWrite(psDevInfo->hRenderCtxListLock, DEVINFO_RENDERLIST);
2464 dllist_add_to_tail(&(psDevInfo->sRenderCtxtListHead), &(psRenderContext->sListNode));
2465 OSWRLockReleaseWrite(psDevInfo->hRenderCtxListLock);
2468 *ppsRenderContext= psRenderContext;
2472 _DestroyTAContext(&psRenderContext->sTAData,
2474 psRenderContext->psCleanupSync);
2477 DevmemFwFree(psRenderContext->psFWFrameworkMemDesc);
2478 fail_frameworkcreate:
2479 SyncPrimFree(psRenderContext->psCleanupSync);
2481 DevmemFwFree(psRenderContext->psFWRenderContextMemDesc);
2482 fail_fwrendercontext:
2483 OSFreeMem(psRenderContext);
2484 PVR_ASSERT(eError != PVRSRV_OK);
2490 * PVRSRVRGXDestroyRenderContextKM
2493 PVRSRV_ERROR PVRSRVRGXDestroyRenderContextKM(RGX_SERVER_RENDER_CONTEXT *psRenderContext)
2495 PVRSRV_ERROR eError;
2496 PVRSRV_RGXDEV_INFO *psDevInfo = psRenderContext->psDeviceNode->pvDevice;
2498 /* remove node from list before calling destroy - as destroy, if successful
2499 * will invalidate the node
2500 * must be re-added if destroy fails
2502 OSWRLockAcquireWrite(psDevInfo->hRenderCtxListLock, DEVINFO_RENDERLIST);
2503 dllist_remove_node(&(psRenderContext->sListNode));
2504 OSWRLockReleaseWrite(psDevInfo->hRenderCtxListLock);
2506 /* Cleanup the TA if we haven't already */
2507 if ((psRenderContext->ui32CleanupStatus & RC_CLEANUP_TA_COMPLETE) == 0)
2509 eError = _DestroyTAContext(&psRenderContext->sTAData,
2510 psRenderContext->psDeviceNode,
2511 psRenderContext->psCleanupSync);
2512 if (eError != PVRSRV_ERROR_RETRY)
2514 psRenderContext->ui32CleanupStatus |= RC_CLEANUP_TA_COMPLETE;
2522 /* Cleanup the 3D if we haven't already */
2523 if ((psRenderContext->ui32CleanupStatus & RC_CLEANUP_3D_COMPLETE) == 0)
2525 eError = _Destroy3DContext(&psRenderContext->s3DData,
2526 psRenderContext->psDeviceNode,
2527 psRenderContext->psCleanupSync);
2528 if (eError != PVRSRV_ERROR_RETRY)
2530 psRenderContext->ui32CleanupStatus |= RC_CLEANUP_3D_COMPLETE;
2539 Only if both TA and 3D contexts have been cleaned up can we
2540 free the shared resources
2542 if (psRenderContext->ui32CleanupStatus == (RC_CLEANUP_3D_COMPLETE | RC_CLEANUP_TA_COMPLETE))
2544 RGXFWIF_FWRENDERCONTEXT *psFWRenderContext;
2546 /* Update SPM statistics */
2547 eError = DevmemAcquireCpuVirtAddr(psRenderContext->psFWRenderContextMemDesc,
2548 (IMG_VOID **)&psFWRenderContext);
2549 if (eError == PVRSRV_OK)
2551 DevmemReleaseCpuVirtAddr(psRenderContext->psFWRenderContextMemDesc);
2555 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXDestroyRenderContextKM: Failed to map firmware render context (%u)",
2559 /* Free the framework buffer */
2560 DevmemFwFree(psRenderContext->psFWFrameworkMemDesc);
2562 /* Free the firmware render context */
2563 DevmemFwFree(psRenderContext->psFWRenderContextMemDesc);
2565 /* Free the cleanup sync */
2566 SyncPrimFree(psRenderContext->psCleanupSync);
2568 SyncAddrListDeinit(&psRenderContext->sSyncAddrListTAFence);
2569 SyncAddrListDeinit(&psRenderContext->sSyncAddrListTAUpdate);
2570 SyncAddrListDeinit(&psRenderContext->sSyncAddrList3DFence);
2571 SyncAddrListDeinit(&psRenderContext->sSyncAddrList3DUpdate);
2573 OSFreeMem(psRenderContext);
2579 OSWRLockAcquireWrite(psDevInfo->hRenderCtxListLock, DEVINFO_RENDERLIST);
2580 dllist_add_to_tail(&(psDevInfo->sRenderCtxtListHead), &(psRenderContext->sListNode));
2581 OSWRLockReleaseWrite(psDevInfo->hRenderCtxListLock);
2587 /* 1 command for the TA */
2588 static RGX_CCB_CMD_HELPER_DATA sTACmdHelperData;
2589 /* Up to 3 commands for the 3D (partial render fence, partial reader, and render) */
2590 static RGX_CCB_CMD_HELPER_DATA as3DCmdHelperData[3];
2593 * PVRSRVRGXKickTA3DKM
2596 PVRSRV_ERROR PVRSRVRGXKickTA3DKM(RGX_SERVER_RENDER_CONTEXT *psRenderContext,
2597 IMG_UINT32 ui32ClientTAFenceCount,
2598 SYNC_PRIMITIVE_BLOCK **apsClientTAFenceSyncPrimBlock,
2599 IMG_UINT32 *paui32ClientTAFenceSyncOffset,
2600 IMG_UINT32 *paui32ClientTAFenceValue,
2601 IMG_UINT32 ui32ClientTAUpdateCount,
2602 SYNC_PRIMITIVE_BLOCK **apsClientTAUpdateSyncPrimBlock,
2603 IMG_UINT32 *paui32ClientTAUpdateSyncOffset,
2604 IMG_UINT32 *paui32ClientTAUpdateValue,
2605 IMG_UINT32 ui32ServerTASyncPrims,
2606 IMG_UINT32 *paui32ServerTASyncFlags,
2607 SERVER_SYNC_PRIMITIVE **pasServerTASyncs,
2608 IMG_UINT32 ui32Client3DFenceCount,
2609 SYNC_PRIMITIVE_BLOCK **apsClient3DFenceSyncPrimBlock,
2610 IMG_UINT32 *paui32Client3DFenceSyncOffset,
2611 IMG_UINT32 *paui32Client3DFenceValue,
2612 IMG_UINT32 ui32Client3DUpdateCount,
2613 SYNC_PRIMITIVE_BLOCK **apsClient3DUpdateSyncPrimBlock,
2614 IMG_UINT32 *paui32Client3DUpdateSyncOffset,
2615 IMG_UINT32 *paui32Client3DUpdateValue,
2616 IMG_UINT32 ui32Server3DSyncPrims,
2617 IMG_UINT32 *paui32Server3DSyncFlags,
2618 SERVER_SYNC_PRIMITIVE **pasServer3DSyncs,
2619 SYNC_PRIMITIVE_BLOCK *psPRFenceSyncPrimBlock,
2620 IMG_UINT32 ui32PRFenceSyncOffset,
2621 IMG_UINT32 ui32PRFenceValue,
2622 IMG_UINT32 ui32NumFenceFDs,
2623 IMG_INT32 *ai32FenceFDs,
2624 IMG_UINT32 ui32TACmdSize,
2625 IMG_PBYTE pui8TADMCmd,
2626 IMG_UINT32 ui323DPRCmdSize,
2627 IMG_PBYTE pui83DPRDMCmd,
2628 IMG_UINT32 ui323DCmdSize,
2629 IMG_PBYTE pui83DDMCmd,
2630 IMG_UINT32 ui32ExtJobRef,
2631 IMG_UINT32 ui32IntJobRef,
2632 IMG_BOOL bLastTAInScene,
2637 IMG_BOOL bPDumpContinuous,
2638 RGX_RTDATA_CLEANUP_DATA *psRTDataCleanup,
2639 RGX_ZSBUFFER_DATA *psZBuffer,
2640 RGX_ZSBUFFER_DATA *psSBuffer,
2641 IMG_BOOL bCommitRefCountsTA,
2642 IMG_BOOL bCommitRefCounts3D,
2643 IMG_BOOL *pbCommittedRefCountsTA,
2644 IMG_BOOL *pbCommittedRefCounts3D)
2647 IMG_UINT32 ui32TACmdCount=0;
2648 IMG_UINT32 ui323DCmdCount=0;
2649 IMG_BOOL bKickTADM = IMG_FALSE;
2650 IMG_BOOL bKick3DDM = IMG_FALSE;
2652 IMG_UINT32 *paui32Server3DSyncFlagsPR = IMG_NULL;
2653 IMG_UINT32 *paui32Server3DSyncFlags3D = IMG_NULL;
2655 PVRSRV_ERROR eError = PVRSRV_OK;
2656 PVRSRV_ERROR eError2;
2658 /* Internal client sync info, used to help with merging of Android fd syncs */
2659 IMG_UINT32 ui32IntClientTAFenceCount = 0;
2660 PRGXFWIF_UFO_ADDR *pauiIntClientTAFenceUFOAddress = IMG_NULL;
2661 IMG_UINT32 *paui32IntClientTAFenceValue = IMG_NULL;
2663 IMG_UINT32 ui32NumUpdateSyncs = 0;
2664 PRGXFWIF_UFO_ADDR *puiUpdateFWAddrs = IMG_NULL;
2665 IMG_UINT32 *pui32UpdateValues = IMG_NULL;
2667 PRGXFWIF_UFO_ADDR uiPRFenceUFOAddress;
2669 #if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
2670 /* Android fd sync update info */
2671 struct pvr_sync_append_data *psFDData = NULL;
2674 PRGXFWIF_TIMESTAMP_ADDR pPreAddr;
2675 PRGXFWIF_TIMESTAMP_ADDR pPostAddr;
2676 PRGXFWIF_UFO_ADDR pRMWUFOAddr;
2678 PRGXFWIF_UFO_ADDR *pauiClientTAFenceUFOAddress;
2679 PRGXFWIF_UFO_ADDR *pauiClientTAUpdateUFOAddress;
2680 PRGXFWIF_UFO_ADDR *pauiClient3DFenceUFOAddress;
2681 PRGXFWIF_UFO_ADDR *pauiClient3DUpdateUFOAddress;
2683 *pbCommittedRefCountsTA = IMG_FALSE;
2684 *pbCommittedRefCounts3D = IMG_FALSE;
2686 eError = SyncAddrListPopulate(&psRenderContext->sSyncAddrListTAFence,
2687 ui32ClientTAFenceCount,
2688 apsClientTAFenceSyncPrimBlock,
2689 paui32ClientTAFenceSyncOffset);
2690 if(eError != PVRSRV_OK)
2692 goto err_populate_sync_addr_list;
2695 pauiClientTAFenceUFOAddress = psRenderContext->sSyncAddrListTAFence.pasFWAddrs;
2697 eError = SyncAddrListPopulate(&psRenderContext->sSyncAddrListTAUpdate,
2698 ui32ClientTAUpdateCount,
2699 apsClientTAUpdateSyncPrimBlock,
2700 paui32ClientTAUpdateSyncOffset);
2701 if(eError != PVRSRV_OK)
2703 goto err_populate_sync_addr_list;
2706 pauiClientTAUpdateUFOAddress = psRenderContext->sSyncAddrListTAUpdate.pasFWAddrs;
2708 eError = SyncAddrListPopulate(&psRenderContext->sSyncAddrList3DFence,
2709 ui32Client3DFenceCount,
2710 apsClient3DFenceSyncPrimBlock,
2711 paui32Client3DFenceSyncOffset);
2712 if(eError != PVRSRV_OK)
2714 goto err_populate_sync_addr_list;
2717 pauiClient3DFenceUFOAddress = psRenderContext->sSyncAddrList3DFence.pasFWAddrs;
2719 eError = SyncAddrListPopulate(&psRenderContext->sSyncAddrList3DUpdate,
2720 ui32Client3DUpdateCount,
2721 apsClient3DUpdateSyncPrimBlock,
2722 paui32Client3DUpdateSyncOffset);
2723 if(eError != PVRSRV_OK)
2725 goto err_populate_sync_addr_list;
2728 pauiClient3DUpdateUFOAddress = psRenderContext->sSyncAddrList3DUpdate.pasFWAddrs;
2730 eError = SyncPrimitiveBlockToFWAddr(psPRFenceSyncPrimBlock,
2731 ui32PRFenceSyncOffset,
2732 &uiPRFenceUFOAddress);
2734 if(eError != PVRSRV_OK)
2736 goto err_pr_fence_address;
2739 /* Sanity check the server fences */
2740 for (i=0;i<ui32ServerTASyncPrims;i++)
2742 if (!(paui32ServerTASyncFlags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK))
2744 PVR_DPF((PVR_DBG_ERROR, "%s: Server fence (on TA) must fence", __FUNCTION__));
2745 return PVRSRV_ERROR_INVALID_SYNC_PRIM_OP;
2749 for (i=0;i<ui32Server3DSyncPrims;i++)
2751 if (!(paui32Server3DSyncFlags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK))
2753 PVR_DPF((PVR_DBG_ERROR, "%s: Server fence (on 3D) must fence", __FUNCTION__));
2754 return PVRSRV_ERROR_INVALID_SYNC_PRIM_OP;
2758 RGX_GetTimestampCmdHelper((PVRSRV_RGXDEV_INFO*) psRenderContext->psDeviceNode->pvDevice,
2764 Sanity check we have a PR kick if there are client or server fences
2766 #if defined(UNDER_WDDM)
2767 /* sanity check only applies to WDDM for a TA kick. 3D kicks don't have a PR kick
2768 * but do have fences
2773 if (!bKickPR & ((ui32Client3DFenceCount != 0) || (ui32Server3DSyncPrims != 0)))
2775 PVR_DPF((PVR_DBG_ERROR, "%s: 3D fence (client or server) passed without a PR kick", __FUNCTION__));
2776 return PVRSRV_ERROR_INVALID_PARAMS;
2778 #if defined(UNDER_WDDM)
2782 /* Init and acquire to TA command if required */
2785 RGX_SERVER_RC_TA_DATA *psTAData = &psRenderContext->sTAData;
2787 ui32IntClientTAFenceCount = ui32ClientTAFenceCount;
2788 pauiIntClientTAFenceUFOAddress = pauiClientTAFenceUFOAddress;
2789 paui32IntClientTAFenceValue = paui32ClientTAFenceValue;
2791 #if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
2792 if (ui32NumFenceFDs)
2795 This call is only using the Android fd sync to fence the
2796 TA command. There is an update but this is used to
2797 indicate that the fence has been finished with and so it
2798 can happen after the PR as by then we've finished using
2802 pvr_sync_append_fences("TA",
2809 ui32IntClientTAFenceCount,
2810 pauiIntClientTAFenceUFOAddress,
2811 paui32IntClientTAFenceValue,
2813 if (eError != PVRSRV_OK)
2817 ui32NumUpdateSyncs = psFDData->nr_updates;
2818 puiUpdateFWAddrs = psFDData->update_ufo_addresses;
2819 pui32UpdateValues = psFDData->update_values;
2820 ui32IntClientTAFenceCount = psFDData->nr_checks;
2821 pauiIntClientTAFenceUFOAddress = psFDData->check_ufo_addresses;
2822 paui32IntClientTAFenceValue = psFDData->check_values;
2824 #endif /* PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC */
2826 /* Init the TA command helper */
2827 eError = RGXCmdHelperInitCmdCCB(FWCommonContextGetClientCCB(psTAData->psServerCommonContext),
2828 ui32IntClientTAFenceCount,
2829 pauiIntClientTAFenceUFOAddress,
2830 paui32IntClientTAFenceValue,
2831 ui32ClientTAUpdateCount,
2832 pauiClientTAUpdateUFOAddress,
2833 paui32ClientTAUpdateValue,
2834 ui32ServerTASyncPrims,
2835 paui32ServerTASyncFlags,
2840 (bKick3D ? IMG_NULL : & pPostAddr),
2841 (bKick3D ? IMG_NULL : & pRMWUFOAddr),
2842 RGXFWIF_CCB_CMD_TYPE_TA,
2846 if (eError != PVRSRV_OK)
2848 goto fail_tacmdinit;
2851 eError = RGXCmdHelperAcquireCmdCCB(1,
2854 if (eError != PVRSRV_OK)
2858 goto fail_taacquirecmd;
2862 /* commit the TA ref counting next time, when the CCB space is successfully
2865 bCommitRefCountsTA = IMG_FALSE;
2874 /* Only kick the 3D if required */
2875 if (eError == PVRSRV_OK)
2879 RGX_SERVER_RC_3D_DATA *ps3DData = &psRenderContext->s3DData;
2881 if (ui32Server3DSyncPrims)
2884 The fence (and possible update) straddle multiple commands so
2885 we have to modify the flags to do the right things at the right
2887 At this stage we should only fence, any updates will happen with
2888 the normal 3D command.
2890 paui32Server3DSyncFlagsPR = OSAllocMem(sizeof(IMG_UINT32) * ui32Server3DSyncPrims);
2891 if (paui32Server3DSyncFlagsPR == IMG_NULL)
2893 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
2894 goto fail_prserversyncflagsallocpr;
2897 /* Copy only the fence flag across */
2898 for (i=0;i<ui32Server3DSyncPrims;i++)
2900 paui32Server3DSyncFlagsPR[i] = paui32Server3DSyncFlags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK;
2905 The command helper doesn't know about the PR fence so create
2906 the command with all the fences against it and later create
2907 the PR command itself which _must_ come after the PR fence.
2909 sPRUFO.puiAddrUFO = uiPRFenceUFOAddress;
2910 sPRUFO.ui32Value = ui32PRFenceValue;
2912 /* Init the PR fence command helper */
2913 eError = RGXCmdHelperInitCmdCCB(FWCommonContextGetClientCCB(ps3DData->psServerCommonContext),
2914 ui32Client3DFenceCount,
2915 pauiClient3DFenceUFOAddress,
2916 paui32Client3DFenceValue,
2920 (bKick3D ? ui32Server3DSyncPrims : 0),
2921 paui32Server3DSyncFlagsPR,
2924 (IMG_UINT8*) &sPRUFO,
2928 RGXFWIF_CCB_CMD_TYPE_FENCE_PR,
2931 &as3DCmdHelperData[ui323DCmdCount++]);
2932 if (eError != PVRSRV_OK)
2934 goto fail_prfencecmdinit;
2937 /* Init the 3D PR command helper */
2939 See note above PVRFDSyncQueryFencesKM as to why updates for android
2940 syncs are passed in with the PR
2942 eError = RGXCmdHelperInitCmdCCB(FWCommonContextGetClientCCB(ps3DData->psServerCommonContext),
2957 RGXFWIF_CCB_CMD_TYPE_3D_PR,
2960 &as3DCmdHelperData[ui323DCmdCount++]);
2961 if (eError != PVRSRV_OK)
2963 goto fail_prcmdinit;
2967 if (bKick3D || bAbort)
2969 RGX_SERVER_RC_3D_DATA *ps3DData = &psRenderContext->s3DData;
2971 if (ui32Server3DSyncPrims)
2974 Copy only the update flags for the 3D as the fences will be in
2975 the PR command created above
2977 paui32Server3DSyncFlags3D = OSAllocMem(sizeof(IMG_UINT32) * ui32Server3DSyncPrims);
2978 if (paui32Server3DSyncFlags3D == IMG_NULL)
2980 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
2981 goto fail_prserversyncflagsalloc3d;
2984 /* Copy only the update flag across */
2985 for (i=0;i<ui32Server3DSyncPrims;i++)
2987 paui32Server3DSyncFlags3D[i] = paui32Server3DSyncFlags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_UPDATE;
2991 /* Init the 3D command helper */
2992 eError = RGXCmdHelperInitCmdCCB(FWCommonContextGetClientCCB(ps3DData->psServerCommonContext),
2996 ui32Client3DUpdateCount,
2997 pauiClient3DUpdateUFOAddress,
2998 paui32Client3DUpdateValue,
2999 ui32Server3DSyncPrims,
3000 paui32Server3DSyncFlags3D,
3004 (bKickTA ? IMG_NULL : & pPreAddr),
3007 RGXFWIF_CCB_CMD_TYPE_3D,
3010 &as3DCmdHelperData[ui323DCmdCount++]);
3011 if (eError != PVRSRV_OK)
3013 goto fail_3dcmdinit;
3019 PVR_ASSERT(bKickPR || bKick3D);
3021 /* Acquire space for all the 3D command(s) */
3022 eError = RGXCmdHelperAcquireCmdCCB(ui323DCmdCount,
3025 if (eError != PVRSRV_OK)
3027 if (!bKick3DDM && !bKickTADM)
3029 goto fail_3dacquirecmd;
3034 There are no DM commands but we still need to kick the
3035 DM to flush out the padding command.
3036 Also reset the TA count as we're going to try again
3041 /* commit the 3D ref counting next time, when the CCB space is
3042 * successfully acquired
3044 bCommitRefCounts3D = IMG_FALSE;
3051 We should acquire the space in the kernel CCB here as after this point
3052 we release the commands which will take operations on server syncs
3053 which can't be undone
3057 Everything is ready to go now, release the commands
3061 RGXCmdHelperReleaseCmdCCB(ui32TACmdCount,
3064 FWCommonContextGetFWAddress(psRenderContext->sTAData.psServerCommonContext).ui32Addr);
3069 RGXCmdHelperReleaseCmdCCB(ui323DCmdCount,
3072 FWCommonContextGetFWAddress(psRenderContext->s3DData.psServerCommonContext).ui32Addr);
3077 RGXFWIF_KCCB_CMD sTAKCCBCmd;
3079 /* Construct the kernel TA CCB command. */
3080 sTAKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_KICK;
3081 sTAKCCBCmd.uCmdData.sCmdKickData.psContext = FWCommonContextGetFWAddress(psRenderContext->sTAData.psServerCommonContext);
3082 sTAKCCBCmd.uCmdData.sCmdKickData.ui32CWoffUpdate = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psRenderContext->sTAData.psServerCommonContext));
3084 if(bCommitRefCountsTA)
3086 AttachKickResourcesCleanupCtls((PRGXFWIF_CLEANUP_CTL *) &sTAKCCBCmd.uCmdData.sCmdKickData.apsCleanupCtl,
3087 &sTAKCCBCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl,
3093 *pbCommittedRefCountsTA = IMG_TRUE;
3097 sTAKCCBCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl = 0;
3100 LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
3102 eError2 = RGXScheduleCommand(psRenderContext->psDeviceNode->pvDevice,
3107 if (eError2 != PVRSRV_ERROR_RETRY)
3111 OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
3112 } END_LOOP_UNTIL_TIMEOUT();
3114 #if defined(SUPPORT_GPUTRACE_EVENTS)
3115 RGXHWPerfFTraceGPUEnqueueEvent(psRenderContext->psDeviceNode->pvDevice,
3116 ui32ExtJobRef, ui32IntJobRef, "TA3D");
3123 RGXFWIF_KCCB_CMD s3DKCCBCmd;
3125 /* Construct the kernel 3D CCB command. */
3126 s3DKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_KICK;
3127 s3DKCCBCmd.uCmdData.sCmdKickData.psContext = FWCommonContextGetFWAddress(psRenderContext->s3DData.psServerCommonContext);
3128 s3DKCCBCmd.uCmdData.sCmdKickData.ui32CWoffUpdate = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psRenderContext->s3DData.psServerCommonContext));
3130 if(bCommitRefCounts3D)
3132 AttachKickResourcesCleanupCtls((PRGXFWIF_CLEANUP_CTL *) &s3DKCCBCmd.uCmdData.sCmdKickData.apsCleanupCtl,
3133 &s3DKCCBCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl,
3139 *pbCommittedRefCounts3D = IMG_TRUE;
3143 s3DKCCBCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl = 0;
3147 LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
3149 eError2 = RGXScheduleCommand(psRenderContext->psDeviceNode->pvDevice,
3154 if (eError2 != PVRSRV_ERROR_RETRY)
3158 OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
3159 } END_LOOP_UNTIL_TIMEOUT();
3163 * Now check eError (which may have returned an error from our earlier calls
3164 * to RGXCmdHelperAcquireCmdCCB) - we needed to process any flush command first
3165 * so we check it now...
3167 if (eError != PVRSRV_OK )
3169 goto fail_3dacquirecmd;
3172 #if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
3173 #if defined(NO_HARDWARE)
3174 pvr_sync_nohw_complete_fences(psFDData);
3176 pvr_sync_free_append_fences_data(psFDData);
3179 if(paui32Server3DSyncFlags3D)
3181 OSFreeMem(paui32Server3DSyncFlags3D);
3184 if(paui32Server3DSyncFlagsPR)
3186 OSFreeMem(paui32Server3DSyncFlagsPR);
3193 if (paui32Server3DSyncFlags3D)
3195 OSFreeMem(paui32Server3DSyncFlags3D);
3197 fail_prserversyncflagsalloc3d:
3199 fail_prfencecmdinit:
3200 if (paui32Server3DSyncFlagsPR)
3202 OSFreeMem(paui32Server3DSyncFlagsPR);
3204 fail_prserversyncflagsallocpr:
3207 #if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
3208 pvr_sync_rollback_append_fences(psFDData);
3209 pvr_sync_free_append_fences_data(psFDData);
3212 err_pr_fence_address:
3213 err_populate_sync_addr_list:
3214 PVR_ASSERT(eError != PVRSRV_OK);
3218 PVRSRV_ERROR PVRSRVRGXSetRenderContextPriorityKM(CONNECTION_DATA *psConnection,
3219 RGX_SERVER_RENDER_CONTEXT *psRenderContext,
3220 IMG_UINT32 ui32Priority)
3222 PVRSRV_ERROR eError;
3224 if (psRenderContext->sTAData.ui32Priority != ui32Priority)
3226 eError = ContextSetPriority(psRenderContext->sTAData.psServerCommonContext,
3228 psRenderContext->psDeviceNode->pvDevice,
3231 if (eError != PVRSRV_OK)
3233 PVR_DPF((PVR_DBG_ERROR, "%s: Failed to set the priority of the TA part of the rendercontext (%s)", __FUNCTION__, PVRSRVGetErrorStringKM(eError)));
3234 goto fail_tacontext;
3236 psRenderContext->sTAData.ui32Priority = ui32Priority;
3239 if (psRenderContext->s3DData.ui32Priority != ui32Priority)
3241 eError = ContextSetPriority(psRenderContext->s3DData.psServerCommonContext,
3243 psRenderContext->psDeviceNode->pvDevice,
3246 if (eError != PVRSRV_OK)
3248 PVR_DPF((PVR_DBG_ERROR, "%s: Failed to set the priority of the 3D part of the rendercontext (%s)", __FUNCTION__, PVRSRVGetErrorStringKM(eError)));
3249 goto fail_3dcontext;
3251 psRenderContext->s3DData.ui32Priority = ui32Priority;
3257 PVR_ASSERT(eError != PVRSRV_OK);
3263 * PVRSRVRGXGetLastResetReason
3265 PVRSRV_ERROR PVRSRVRGXGetLastRenderContextResetReasonKM(RGX_SERVER_RENDER_CONTEXT *psRenderContext,
3266 IMG_UINT32 *peLastResetReason)
3268 RGX_SERVER_RC_TA_DATA *psRenderCtxTAData = &(psRenderContext->sTAData);
3269 RGX_SERVER_COMMON_CONTEXT *psCurrentServerTACommonCtx = psRenderCtxTAData->psServerCommonContext;
3270 RGX_SERVER_RC_3D_DATA *psRenderCtx3DData = &(psRenderContext->s3DData);
3271 RGX_SERVER_COMMON_CONTEXT *psCurrentServer3DCommonCtx = psRenderCtx3DData->psServerCommonContext;
3272 RGXFWIF_CONTEXT_RESET_REASON eLastTAResetReason, eLast3DResetReason;
3274 PVR_ASSERT(psRenderContext != IMG_NULL);
3275 PVR_ASSERT(peLastResetReason != IMG_NULL);
3277 /* Get the last reset reasons from both the TA and 3D so they are reset... */
3278 eLastTAResetReason = FWCommonContextGetLastResetReason(psCurrentServerTACommonCtx);
3279 eLast3DResetReason = FWCommonContextGetLastResetReason(psCurrentServer3DCommonCtx);
3281 /* Combine the reset reason from TA and 3D into one... */
3282 *peLastResetReason = (IMG_UINT32) eLast3DResetReason;
3283 if (eLast3DResetReason == RGXFWIF_CONTEXT_RESET_REASON_NONE ||
3284 ((eLast3DResetReason == RGXFWIF_CONTEXT_RESET_REASON_INNOCENT_LOCKUP ||
3285 eLast3DResetReason == RGXFWIF_CONTEXT_RESET_REASON_INNOCENT_OVERRUNING) &&
3286 (eLastTAResetReason == RGXFWIF_CONTEXT_RESET_REASON_GUILTY_LOCKUP ||
3287 eLastTAResetReason == RGXFWIF_CONTEXT_RESET_REASON_GUILTY_OVERRUNING)))
3289 *peLastResetReason = (IMG_UINT32) eLastTAResetReason;
3297 * PVRSRVRGXGetPartialRenderCountKM
3299 PVRSRV_ERROR PVRSRVRGXGetPartialRenderCountKM(DEVMEM_MEMDESC *psHWRTDataMemDesc,
3300 IMG_UINT32 *pui32NumPartialRenders)
3302 RGXFWIF_HWRTDATA *psHWRTData;
3303 PVRSRV_ERROR eError;
3305 eError = DevmemAcquireCpuVirtAddr(psHWRTDataMemDesc, (IMG_VOID **)&psHWRTData);
3307 if (eError != PVRSRV_OK)
3309 PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXGetPartialRenderCountKM: Failed to map Firmware Render Target Data (%u)", eError));
3313 *pui32NumPartialRenders = psHWRTData->ui32NumPartialRenders;
3315 DevmemReleaseCpuVirtAddr(psHWRTDataMemDesc);
3321 static IMG_BOOL CheckForStalledRenderCtxtCommand(PDLLIST_NODE psNode, IMG_PVOID pvCallbackData)
3323 RGX_SERVER_RENDER_CONTEXT *psCurrentServerRenderCtx = IMG_CONTAINER_OF(psNode, RGX_SERVER_RENDER_CONTEXT, sListNode);
3324 RGX_SERVER_RC_TA_DATA *psRenderCtxTAData = &(psCurrentServerRenderCtx->sTAData);
3325 RGX_SERVER_COMMON_CONTEXT *psCurrentServerTACommonCtx = psRenderCtxTAData->psServerCommonContext;
3326 RGX_SERVER_RC_3D_DATA *psRenderCtx3DData = &(psCurrentServerRenderCtx->s3DData);
3327 RGX_SERVER_COMMON_CONTEXT *psCurrentServer3DCommonCtx = psRenderCtx3DData->psServerCommonContext;
3328 DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf = pvCallbackData;
3331 DumpStalledFWCommonContext(psCurrentServerTACommonCtx, pfnDumpDebugPrintf);
3332 DumpStalledFWCommonContext(psCurrentServer3DCommonCtx, pfnDumpDebugPrintf);
3336 IMG_VOID CheckForStalledRenderCtxt(PVRSRV_RGXDEV_INFO *psDevInfo,
3337 DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf)
3339 OSWRLockAcquireRead(psDevInfo->hRenderCtxListLock, DEVINFO_RENDERLIST);
3340 dllist_foreach_node(&(psDevInfo->sRenderCtxtListHead),
3341 CheckForStalledRenderCtxtCommand, pfnDumpDebugPrintf);
3342 OSWRLockReleaseRead(psDevInfo->hRenderCtxListLock);
3345 static IMG_BOOL CheckForStalledClientRenderCtxtCommand(PDLLIST_NODE psNode, IMG_PVOID pvCallbackData)
3347 PVRSRV_ERROR *peError = (PVRSRV_ERROR*)pvCallbackData;
3348 RGX_SERVER_RENDER_CONTEXT *psCurrentServerRenderCtx = IMG_CONTAINER_OF(psNode, RGX_SERVER_RENDER_CONTEXT, sListNode);
3349 RGX_SERVER_RC_TA_DATA *psRenderCtxTAData = &(psCurrentServerRenderCtx->sTAData);
3350 RGX_SERVER_COMMON_CONTEXT *psCurrentServerTACommonCtx = psRenderCtxTAData->psServerCommonContext;
3351 RGX_SERVER_RC_3D_DATA *psRenderCtx3DData = &(psCurrentServerRenderCtx->s3DData);
3352 RGX_SERVER_COMMON_CONTEXT *psCurrentServer3DCommonCtx = psRenderCtx3DData->psServerCommonContext;
3354 if (PVRSRV_ERROR_CCCB_STALLED == CheckStalledClientCommonContext(psCurrentServerTACommonCtx))
3356 *peError = PVRSRV_ERROR_CCCB_STALLED;
3358 if (PVRSRV_ERROR_CCCB_STALLED == CheckStalledClientCommonContext(psCurrentServer3DCommonCtx))
3360 *peError = PVRSRV_ERROR_CCCB_STALLED;
3365 IMG_BOOL CheckForStalledClientRenderCtxt(PVRSRV_RGXDEV_INFO *psDevInfo)
3367 PVRSRV_ERROR eError = PVRSRV_OK;
3368 OSWRLockAcquireRead(psDevInfo->hRenderCtxListLock, DEVINFO_RENDERLIST);
3369 dllist_foreach_node(&(psDevInfo->sRenderCtxtListHead),
3370 CheckForStalledClientRenderCtxtCommand, &eError);
3371 OSWRLockReleaseRead(psDevInfo->hRenderCtxListLock);
3372 return (PVRSRV_ERROR_CCCB_STALLED == eError)? IMG_TRUE: IMG_FALSE;
3375 IMG_EXPORT PVRSRV_ERROR
3376 PVRSRVRGXKickSyncTAKM(RGX_SERVER_RENDER_CONTEXT *psRenderContext,
3377 IMG_UINT32 ui32TAClientFenceCount,
3378 SYNC_PRIMITIVE_BLOCK **apsTAClientFenceSyncPrimBlock,
3379 IMG_UINT32 *paui32TAClientFenceSyncOffset,
3380 IMG_UINT32 *paui32TAClientFenceValue,
3381 IMG_UINT32 ui32TAClientUpdateCount,
3382 SYNC_PRIMITIVE_BLOCK **apsTAClientUpdateSyncPrimBlock,
3383 IMG_UINT32 *paui32TAClientUpdateSyncOffset,
3384 IMG_UINT32 *paui32TAClientUpdateValue,
3385 IMG_UINT32 ui32TAServerSyncPrimsCount,
3386 IMG_UINT32 *paui32TAServerSyncFlags,
3387 SERVER_SYNC_PRIMITIVE **pasTAServerSyncs,
3388 IMG_UINT32 ui323DClientFenceCount,
3389 SYNC_PRIMITIVE_BLOCK **aps3DClientFenceSyncPrimBlock,
3390 IMG_UINT32 *paui323DClientFenceSyncOffset,
3391 IMG_UINT32 *paui323DClientFenceValue,
3392 IMG_UINT32 ui323DClientUpdateCount,
3393 SYNC_PRIMITIVE_BLOCK **aps3DClientUpdateSyncPrimBlock,
3394 IMG_UINT32 *paui323DClientUpdateSyncOffset,
3395 IMG_UINT32 *paui323DClientUpdateValue,
3396 IMG_UINT32 ui323DServerSyncPrimsCount,
3397 IMG_UINT32 *paui323DServerSyncFlags,
3398 SERVER_SYNC_PRIMITIVE **pas3DServerSyncs,
3399 IMG_UINT32 ui32NumFenceFDs,
3400 IMG_INT32 *pai32FenceFDs,
3401 IMG_BOOL bPDumpContinuous)
3403 PVRSRV_ERROR eError = PVRSRV_OK;
3404 PRGXFWIF_UFO_ADDR *pauiTAClientFenceUFOAddress;
3405 PRGXFWIF_UFO_ADDR *pauiTAClientUpdateUFOAddress;
3406 PRGXFWIF_UFO_ADDR *paui3DClientFenceUFOAddress;
3407 PRGXFWIF_UFO_ADDR *paui3DClientUpdateUFOAddress;
3409 #if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
3410 /* Android fd sync update info */
3411 struct pvr_sync_append_data *psFDData = NULL;
3414 eError = SyncAddrListPopulate(&psRenderContext->sSyncAddrListTAFence,
3415 ui32TAClientFenceCount,
3416 apsTAClientFenceSyncPrimBlock,
3417 paui32TAClientFenceSyncOffset);
3418 if(eError != PVRSRV_OK)
3420 goto err_populate_sync_addr_list;
3423 pauiTAClientFenceUFOAddress = psRenderContext->sSyncAddrListTAFence.pasFWAddrs;
3425 eError = SyncAddrListPopulate(&psRenderContext->sSyncAddrListTAUpdate,
3426 ui32TAClientUpdateCount,
3427 apsTAClientUpdateSyncPrimBlock,
3428 paui32TAClientUpdateSyncOffset);
3429 if(eError != PVRSRV_OK)
3431 goto err_populate_sync_addr_list;
3434 pauiTAClientUpdateUFOAddress = psRenderContext->sSyncAddrListTAUpdate.pasFWAddrs;
3436 eError = SyncAddrListPopulate(&psRenderContext->sSyncAddrList3DFence,
3437 ui323DClientFenceCount,
3438 aps3DClientFenceSyncPrimBlock,
3439 paui323DClientFenceSyncOffset);
3440 if(eError != PVRSRV_OK)
3442 goto err_populate_sync_addr_list;
3445 paui3DClientFenceUFOAddress = psRenderContext->sSyncAddrList3DFence.pasFWAddrs;
3447 eError = SyncAddrListPopulate(&psRenderContext->sSyncAddrList3DUpdate,
3448 ui323DClientUpdateCount,
3449 aps3DClientUpdateSyncPrimBlock,
3450 paui323DClientUpdateSyncOffset);
3451 if(eError != PVRSRV_OK)
3453 goto err_populate_sync_addr_list;
3456 paui3DClientUpdateUFOAddress = psRenderContext->sSyncAddrList3DUpdate.pasFWAddrs;
3458 #if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
3459 /* Android FD fences are hardcoded to updates (IMG_TRUE below), Fences go to the TA and updates to the 3D */
3460 if (ui32NumFenceFDs)
3463 pvr_sync_append_fences("TA",
3467 ui323DClientUpdateCount,
3468 paui3DClientUpdateUFOAddress,
3469 paui323DClientUpdateValue,
3470 ui323DClientFenceCount,
3471 paui3DClientFenceUFOAddress,
3472 paui323DClientFenceValue,
3474 if (eError != PVRSRV_OK)
3478 ui323DClientUpdateCount = psFDData->nr_updates;
3479 paui3DClientUpdateUFOAddress = psFDData->update_ufo_addresses;
3480 paui323DClientUpdateValue = psFDData->update_values;
3481 ui323DClientFenceCount = psFDData->nr_checks;
3482 paui3DClientFenceUFOAddress = psFDData->check_ufo_addresses;
3483 paui323DClientFenceValue = psFDData->check_values;
3487 /* send one command through the TA */
3488 if ((ui32TAClientFenceCount + ui32TAClientUpdateCount + ui32TAServerSyncPrimsCount) > 0)
3490 eError = RGXKickSyncKM(psRenderContext->psDeviceNode,
3491 psRenderContext->sTAData.psServerCommonContext,
3494 ui32TAClientFenceCount,
3495 pauiTAClientFenceUFOAddress,
3496 paui32TAClientFenceValue,
3497 ui32TAClientUpdateCount,
3498 pauiTAClientUpdateUFOAddress,
3499 paui32TAClientUpdateValue,
3500 ui32TAServerSyncPrimsCount,
3501 paui32TAServerSyncFlags,
3505 if (eError != PVRSRV_OK)
3507 PVR_DPF((PVR_DBG_ERROR, "%s: Failed to send TA sync command (%s)", __FUNCTION__, PVRSRVGetErrorStringKM(eError)));
3512 /* and another one through the 3D */
3513 if ((ui323DClientFenceCount + ui323DClientUpdateCount + ui323DServerSyncPrimsCount) > 0)
3515 eError = RGXKickSyncKM(psRenderContext->psDeviceNode,
3516 psRenderContext->s3DData.psServerCommonContext,
3519 ui323DClientFenceCount,
3520 paui3DClientFenceUFOAddress,
3521 paui323DClientFenceValue,
3522 ui323DClientUpdateCount,
3523 paui3DClientUpdateUFOAddress,
3524 paui323DClientUpdateValue,
3525 ui323DServerSyncPrimsCount,
3526 paui323DServerSyncFlags,
3530 if (eError != PVRSRV_OK)
3532 PVR_DPF((PVR_DBG_ERROR, "%s: Failed to send 3D sync command (%s)", __FUNCTION__, PVRSRVGetErrorStringKM(eError)));
3536 #if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
3537 #if defined(NO_HARDWARE)
3538 pvr_sync_nohw_complete_fences(psFDData);
3539 #endif /* NO_HARDWARE */
3540 pvr_sync_free_append_fences_data(psFDData);
3541 #endif /* PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC */
3548 #if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
3549 pvr_sync_rollback_append_fences(psFDData);
3550 pvr_sync_free_append_fences_data(psFDData);
3553 err_populate_sync_addr_list:
3556 /******************************************************************************
3557 End of file (rgxta3d.c)
3558 ******************************************************************************/