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"
55 #include "ri_server.h"
58 #include "rgx_memallocflags.h"
60 #include "rgxhwperf.h"
61 #include "rgxtimerquery.h"
64 #include "rgxdefs_km.h"
65 #include "rgx_fwif_km.h"
67 #include "sync_server.h"
68 #include "sync_internal.h"
70 #include "process_stats.h"
72 #if defined(SUPPORT_BUFFER_SYNC)
73 #include "pvr_buffer_sync.h"
76 #if defined(SUPPORT_NATIVE_FENCE_SYNC)
80 #if defined(SUPPORT_PDVFS)
84 #if defined(SUPPORT_WORKLOAD_ESTIMATION)
86 #include "rgxworkest.h"
88 #define HASH_CLEAN_LIMIT 6
91 typedef struct _DEVMEM_REF_LOOKUP_
93 IMG_UINT32 ui32ZSBufferID;
94 RGX_ZSBUFFER_DATA *psZSBuffer;
97 typedef struct _DEVMEM_FREELIST_LOOKUP_
99 IMG_UINT32 ui32FreeListID;
100 RGX_FREELIST *psFreeList;
101 } DEVMEM_FREELIST_LOOKUP;
104 DEVMEM_MEMDESC *psContextStateMemDesc;
105 RGX_SERVER_COMMON_CONTEXT *psServerCommonContext;
106 IMG_UINT32 ui32Priority;
107 } RGX_SERVER_RC_TA_DATA;
110 DEVMEM_MEMDESC *psContextStateMemDesc;
111 RGX_SERVER_COMMON_CONTEXT *psServerCommonContext;
112 IMG_UINT32 ui32Priority;
113 } RGX_SERVER_RC_3D_DATA;
115 struct _RGX_SERVER_RENDER_CONTEXT_ {
116 PVRSRV_DEVICE_NODE *psDeviceNode;
117 DEVMEM_MEMDESC *psFWRenderContextMemDesc;
118 DEVMEM_MEMDESC *psFWFrameworkMemDesc;
119 RGX_SERVER_RC_TA_DATA sTAData;
120 RGX_SERVER_RC_3D_DATA s3DData;
121 IMG_UINT32 ui32CleanupStatus;
122 #define RC_CLEANUP_TA_COMPLETE (1 << 0)
123 #define RC_CLEANUP_3D_COMPLETE (1 << 1)
124 PVRSRV_CLIENT_SYNC_PRIM *psCleanupSync;
125 DLLIST_NODE sListNode;
126 SYNC_ADDR_LIST sSyncAddrListTAFence;
127 SYNC_ADDR_LIST sSyncAddrListTAUpdate;
128 SYNC_ADDR_LIST sSyncAddrList3DFence;
129 SYNC_ADDR_LIST sSyncAddrList3DUpdate;
131 #if defined(SUPPORT_WORKLOAD_ESTIMATION)
132 WORKEST_HOST_DATA sWorkEstData;
137 #if ! defined(NO_HARDWARE)
140 __attribute__((noreturn))
142 void sleep_for_ever(void)
144 #if defined(__KLOCWORK__) // klocworks would report an infinite loop because of while(1).
149 OSSleepms(~0); // sleep the maximum amount of time possible
157 Static functions used by render context code
161 PVRSRV_ERROR _DestroyTAContext(RGX_SERVER_RC_TA_DATA *psTAData,
162 PVRSRV_DEVICE_NODE *psDeviceNode,
163 PVRSRV_CLIENT_SYNC_PRIM *psCleanupSync)
167 /* Check if the FW has finished with this resource ... */
168 eError = RGXFWRequestCommonContextCleanUp(psDeviceNode,
169 psTAData->psServerCommonContext,
173 if (eError == PVRSRV_ERROR_RETRY)
177 else if (eError != PVRSRV_OK)
179 PVR_LOG(("%s: Unexpected error from RGXFWRequestCommonContextCleanUp (%s)",
181 PVRSRVGetErrorStringKM(eError)));
185 /* ... it has so we can free it's resources */
187 /* Log the number of TA context stores which occurred */
189 RGXFWIF_TACTX_STATE *psFWTAState;
191 eError = DevmemAcquireCpuVirtAddr(psTAData->psContextStateMemDesc,
192 (void**)&psFWTAState);
193 if (eError != PVRSRV_OK)
195 PVR_DPF((PVR_DBG_ERROR,"%s: Failed to map firmware render context state (%u)",
196 __FUNCTION__, eError));
200 /* Release the CPU virt addr */
201 DevmemReleaseCpuVirtAddr(psTAData->psContextStateMemDesc);
205 FWCommonContextFree(psTAData->psServerCommonContext);
206 DevmemFwFree(psDeviceNode->pvDevice, psTAData->psContextStateMemDesc);
207 psTAData->psServerCommonContext = NULL;
212 PVRSRV_ERROR _Destroy3DContext(RGX_SERVER_RC_3D_DATA *ps3DData,
213 PVRSRV_DEVICE_NODE *psDeviceNode,
214 PVRSRV_CLIENT_SYNC_PRIM *psCleanupSync)
218 /* Check if the FW has finished with this resource ... */
219 eError = RGXFWRequestCommonContextCleanUp(psDeviceNode,
220 ps3DData->psServerCommonContext,
224 if (eError == PVRSRV_ERROR_RETRY)
228 else if (eError != PVRSRV_OK)
230 PVR_LOG(("%s: Unexpected error from RGXFWRequestCommonContextCleanUp (%s)",
232 PVRSRVGetErrorStringKM(eError)));
236 /* ... it has so we can free it's resources */
238 /* Log the number of 3D context stores which occurred */
240 RGXFWIF_3DCTX_STATE *psFW3DState;
242 eError = DevmemAcquireCpuVirtAddr(ps3DData->psContextStateMemDesc,
243 (void**)&psFW3DState);
244 if (eError != PVRSRV_OK)
246 PVR_DPF((PVR_DBG_ERROR,"%s: Failed to map firmware render context state (%u)",
247 __FUNCTION__, eError));
251 /* Release the CPU virt addr */
252 DevmemReleaseCpuVirtAddr(ps3DData->psContextStateMemDesc);
257 FWCommonContextFree(ps3DData->psServerCommonContext);
258 DevmemFwFree(psDeviceNode->pvDevice, ps3DData->psContextStateMemDesc);
259 ps3DData->psServerCommonContext = NULL;
263 static void _RGXDumpPMRPageList(DLLIST_NODE *psNode)
265 RGX_PMR_NODE *psPMRNode = IMG_CONTAINER_OF(psNode, RGX_PMR_NODE, sMemoryBlock);
268 eError = PMRDumpPageList(psPMRNode->psPMR,
269 RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT);
270 if (eError != PVRSRV_OK)
272 PVR_DPF((PVR_DBG_ERROR,"Error (%u) printing pmr %p", eError, psPMRNode->psPMR));
276 IMG_BOOL RGXDumpFreeListPageList(RGX_FREELIST *psFreeList)
278 DLLIST_NODE *psNode, *psNext;
280 PVR_LOG(("Freelist FWAddr 0x%08x, ID = %d, CheckSum 0x%016llx",
281 psFreeList->sFreeListFWDevVAddr.ui32Addr,
282 psFreeList->ui32FreelistID,
283 psFreeList->ui64FreelistChecksum));
285 /* Dump Init FreeList page list */
286 PVR_LOG((" Initial Memory block"));
287 dllist_foreach_node(&psFreeList->sMemoryBlockInitHead, psNode, psNext)
289 _RGXDumpPMRPageList(psNode);
292 /* Dump Grow FreeList page list */
293 PVR_LOG((" Grow Memory blocks"));
294 dllist_foreach_node(&psFreeList->sMemoryBlockHead, psNode, psNext)
296 _RGXDumpPMRPageList(psNode);
302 static PVRSRV_ERROR _UpdateFwFreelistSize(RGX_FREELIST *psFreeList,
304 IMG_UINT32 ui32DeltaSize)
306 PVRSRV_ERROR eError = PVRSRV_OK;
307 RGXFWIF_KCCB_CMD sGPCCBCmd;
309 sGPCCBCmd.eCmdType = (bGrow) ? RGXFWIF_KCCB_CMD_FREELIST_GROW_UPDATE : RGXFWIF_KCCB_CMD_FREELIST_SHRINK_UPDATE;
310 sGPCCBCmd.uCmdData.sFreeListGSData.sFreeListFWDevVAddr.ui32Addr = psFreeList->sFreeListFWDevVAddr.ui32Addr;
311 sGPCCBCmd.uCmdData.sFreeListGSData.ui32DeltaSize = ui32DeltaSize;
312 sGPCCBCmd.uCmdData.sFreeListGSData.ui32NewSize = psFreeList->ui32CurrentFLPages;
314 PVR_DPF((PVR_DBG_MESSAGE, "Send FW update: freelist [FWAddr=0x%08x] has 0x%08x pages",
315 psFreeList->sFreeListFWDevVAddr.ui32Addr,
316 psFreeList->ui32CurrentFLPages));
318 /* Submit command to the firmware. */
319 LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
321 eError = RGXScheduleCommand(psFreeList->psDevInfo,
326 PDUMP_FLAGS_CONTINUOUS);
327 if (eError != PVRSRV_ERROR_RETRY)
331 OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
332 } END_LOOP_UNTIL_TIMEOUT();
334 if (eError != PVRSRV_OK)
336 PVR_DPF((PVR_DBG_ERROR, "_UpdateFwFreelistSize: failed to update FW freelist size. (error = %u)", eError));
343 static void _CheckFreelist(RGX_FREELIST *psFreeList,
344 IMG_UINT32 ui32NumOfPagesToCheck,
345 IMG_UINT64 ui64ExpectedCheckSum,
346 IMG_UINT64 *pui64CalculatedCheckSum)
348 #if defined(NO_HARDWARE)
349 /* No checksum needed as we have all information in the pdumps */
350 PVR_UNREFERENCED_PARAMETER(psFreeList);
351 PVR_UNREFERENCED_PARAMETER(ui32NumOfPagesToCheck);
352 PVR_UNREFERENCED_PARAMETER(ui64ExpectedCheckSum);
353 *pui64CalculatedCheckSum = 0;
357 IMG_UINT8* pui8Buffer;
358 IMG_UINT32* pui32Buffer;
359 IMG_UINT32 ui32CheckSumAdd = 0;
360 IMG_UINT32 ui32CheckSumXor = 0;
361 IMG_UINT32 ui32Entry;
362 IMG_UINT32 ui32Entry2;
363 IMG_BOOL bFreelistBad = IMG_FALSE;
365 *pui64CalculatedCheckSum = 0;
367 /* Allocate Buffer of the size of the freelist */
368 pui8Buffer = OSAllocMem(psFreeList->ui32CurrentFLPages * sizeof(IMG_UINT32));
369 if (pui8Buffer == NULL)
371 PVR_LOG(("_CheckFreelist: Failed to allocate buffer to check freelist %p!", psFreeList));
377 /* Copy freelist content into Buffer */
378 eError = PMR_ReadBytes(psFreeList->psFreeListPMR,
379 psFreeList->uiFreeListPMROffset + (psFreeList->ui32MaxFLPages - psFreeList->ui32CurrentFLPages) * sizeof(IMG_UINT32),
381 psFreeList->ui32CurrentFLPages * sizeof(IMG_UINT32),
383 if (eError != PVRSRV_OK)
385 OSFreeMem(pui8Buffer);
386 PVR_LOG(("_CheckFreelist: Failed to get freelist data for freelist %p!", psFreeList));
392 PVR_ASSERT(uiNumBytes == psFreeList->ui32CurrentFLPages * sizeof(IMG_UINT32));
393 PVR_ASSERT(ui32NumOfPagesToCheck <= psFreeList->ui32CurrentFLPages);
395 /* Generate checksum */
396 pui32Buffer = (IMG_UINT32 *)pui8Buffer;
397 for(ui32Entry = 0; ui32Entry < ui32NumOfPagesToCheck; ui32Entry++)
399 ui32CheckSumAdd += pui32Buffer[ui32Entry];
400 ui32CheckSumXor ^= pui32Buffer[ui32Entry];
402 /* Check for double entries */
403 for (ui32Entry2 = 0; ui32Entry2 < ui32NumOfPagesToCheck; ui32Entry2++)
405 if ((ui32Entry != ui32Entry2) &&
406 (pui32Buffer[ui32Entry] == pui32Buffer[ui32Entry2]))
408 PVR_LOG(("_CheckFreelist: Freelist consistency failure: FW addr: 0x%08X, Double entry found 0x%08x on idx: %d and %d of %d",
409 psFreeList->sFreeListFWDevVAddr.ui32Addr,
410 pui32Buffer[ui32Entry2],
413 psFreeList->ui32CurrentFLPages));
414 bFreelistBad = IMG_TRUE;
419 OSFreeMem(pui8Buffer);
421 /* Check the calculated checksum against the expected checksum... */
422 *pui64CalculatedCheckSum = ((IMG_UINT64)ui32CheckSumXor << 32) | ui32CheckSumAdd;
424 if (ui64ExpectedCheckSum != 0 && ui64ExpectedCheckSum != *pui64CalculatedCheckSum)
426 PVR_LOG(("_CheckFreelist: Checksum mismatch for freelist %p! Expected 0x%016llx calculated 0x%016llx",
427 psFreeList, ui64ExpectedCheckSum, *pui64CalculatedCheckSum));
428 bFreelistBad = IMG_TRUE;
433 PVR_LOG(("_CheckFreelist: Sleeping for ever!"));
435 // PVR_ASSERT(!bFreelistBad);
440 PVRSRV_ERROR RGXGrowFreeList(RGX_FREELIST *psFreeList,
441 IMG_UINT32 ui32NumPages,
442 PDLLIST_NODE pListHeader)
444 RGX_PMR_NODE *psPMRNode;
445 IMG_DEVMEM_SIZE_T uiSize;
446 IMG_UINT32 ui32MappingTable = 0;
447 IMG_DEVMEM_OFFSET_T uiOffset;
448 IMG_DEVMEM_SIZE_T uiLength;
449 IMG_DEVMEM_SIZE_T uistartPage;
451 const IMG_CHAR * pszAllocName = "Free List";
453 /* Are we allowed to grow ? */
454 if ((psFreeList->ui32MaxFLPages - psFreeList->ui32CurrentFLPages) < ui32NumPages)
456 PVR_DPF((PVR_DBG_WARNING,"Freelist [0x%p]: grow by %u pages denied. Max PB size reached (current pages %u/%u)",
459 psFreeList->ui32CurrentFLPages,
460 psFreeList->ui32MaxFLPages));
461 return PVRSRV_ERROR_PBSIZE_ALREADY_MAX;
464 /* Allocate kernel memory block structure */
465 psPMRNode = OSAllocMem(sizeof(*psPMRNode));
466 if (psPMRNode == NULL)
468 PVR_DPF((PVR_DBG_ERROR, "RGXGrowFreeList: failed to allocate host data structure"));
469 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
474 * Lock protects simultaneous manipulation of:
475 * - the memory block list
476 * - the freelist's ui32CurrentFLPages
478 OSLockAcquire(psFreeList->psDevInfo->hLockFreeList);
481 psPMRNode->ui32NumPages = ui32NumPages;
482 psPMRNode->psFreeList = psFreeList;
484 /* Allocate Memory Block */
485 PDUMPCOMMENT("Allocate PB Block (Pages %08X)", ui32NumPages);
486 uiSize = (IMG_DEVMEM_SIZE_T)ui32NumPages * RGX_BIF_PM_PHYSICAL_PAGE_SIZE;
487 eError = PhysmemNewRamBackedPMR(NULL,
488 psFreeList->psDevInfo->psDeviceNode,
494 RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT,
495 PVRSRV_MEMALLOCFLAG_GPU_READABLE,
496 OSStringLength(pszAllocName) + 1,
499 if(eError != PVRSRV_OK)
501 PVR_DPF((PVR_DBG_ERROR,
502 "RGXGrowFreeList: Failed to allocate PB block of size: 0x%016llX",
503 (IMG_UINT64)uiSize));
504 goto ErrorBlockAlloc;
507 /* Zeroing physical pages pointed by the PMR */
508 if (psFreeList->psDevInfo->ui32DeviceFlags & RGXKM_DEVICE_STATE_ZERO_FREELIST)
510 eError = PMRZeroingPMR(psPMRNode->psPMR, RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT);
511 if (eError != PVRSRV_OK)
513 PVR_DPF((PVR_DBG_ERROR,"RGXGrowFreeList: Failed to zero PMR %p of freelist %p with Error %d",
521 uiLength = psPMRNode->ui32NumPages * sizeof(IMG_UINT32);
522 uistartPage = (psFreeList->ui32MaxFLPages - psFreeList->ui32CurrentFLPages - psPMRNode->ui32NumPages);
523 uiOffset = psFreeList->uiFreeListPMROffset + (uistartPage * sizeof(IMG_UINT32));
525 #if defined(PVR_RI_DEBUG)
527 eError = RIWritePMREntryKM(psPMRNode->psPMR,
528 OSStringNLength(pszAllocName, RI_MAX_TEXT_LEN),
531 if( eError != PVRSRV_OK)
533 PVR_DPF((PVR_DBG_ERROR,
534 "%s: call to RIWritePMREntryKM failed (eError=%d)",
539 /* Attach RI information */
540 eError = RIWriteMEMDESCEntryKM(psPMRNode->psPMR,
541 OSStringNLength(pszAllocName, RI_MAX_TEXT_LEN),
548 &psPMRNode->hRIHandle);
549 if( eError != PVRSRV_OK)
551 PVR_DPF((PVR_DBG_ERROR,
552 "%s: call to RIWriteMEMDESCEntryKM failed (eError=%d)",
557 #endif /* if defined(PVR_RI_DEBUG) */
559 /* write Freelist with Memory Block physical addresses */
560 eError = PMRWritePMPageList(
561 /* Target PMR, offset, and length */
562 psFreeList->psFreeListPMR,
565 /* Referenced PMR, and "page" granularity */
567 RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT,
568 &psPMRNode->psPageList);
569 if (eError != PVRSRV_OK)
571 PVR_DPF((PVR_DBG_ERROR,
572 "RGXGrowFreeList: Failed to write pages of Node %p",
574 goto ErrorPopulateFreelist;
577 /* We add It must be added to the tail, otherwise the freelist population won't work */
578 dllist_add_to_head(pListHeader, &psPMRNode->sMemoryBlock);
580 /* Update number of available pages */
581 psFreeList->ui32CurrentFLPages += ui32NumPages;
583 /* Update statistics */
584 if (psFreeList->ui32NumHighPages < psFreeList->ui32CurrentFLPages)
586 psFreeList->ui32NumHighPages = psFreeList->ui32CurrentFLPages;
589 if (psFreeList->bCheckFreelist)
591 /* We can only do a freelist check if the list is full (e.g. at initial creation time) */
592 if (psFreeList->ui32CurrentFLPages == ui32NumPages)
594 IMG_UINT64 ui64Dummy;
595 _CheckFreelist(psFreeList, ui32NumPages, psFreeList->ui64FreelistChecksum, &ui64Dummy);
599 OSLockRelease(psFreeList->psDevInfo->hLockFreeList);
601 PVR_DPF((PVR_DBG_MESSAGE,"Freelist [%p]: grow by %u pages (current pages %u/%u)",
604 psFreeList->ui32CurrentFLPages,
605 psFreeList->ui32MaxFLPages));
610 ErrorPopulateFreelist:
611 PMRUnrefPMR(psPMRNode->psPMR);
614 OSFreeMem(psPMRNode);
615 OSLockRelease(psFreeList->psDevInfo->hLockFreeList);
618 PVR_ASSERT(eError != PVRSRV_OK);
623 static PVRSRV_ERROR RGXShrinkFreeList(PDLLIST_NODE pListHeader,
624 RGX_FREELIST *psFreeList)
627 RGX_PMR_NODE *psPMRNode;
628 PVRSRV_ERROR eError = PVRSRV_OK;
629 IMG_UINT32 ui32OldValue;
632 * Lock protects simultaneous manipulation of:
633 * - the memory block list
634 * - the freelist's ui32CurrentFLPages value
636 PVR_ASSERT(pListHeader);
637 PVR_ASSERT(psFreeList);
638 PVR_ASSERT(psFreeList->psDevInfo);
639 PVR_ASSERT(psFreeList->psDevInfo->hLockFreeList);
641 OSLockAcquire(psFreeList->psDevInfo->hLockFreeList);
643 /* Get node from head of list and remove it */
644 psNode = dllist_get_next_node(pListHeader);
647 dllist_remove_node(psNode);
649 psPMRNode = IMG_CONTAINER_OF(psNode, RGX_PMR_NODE, sMemoryBlock);
650 PVR_ASSERT(psPMRNode);
651 PVR_ASSERT(psPMRNode->psPMR);
652 PVR_ASSERT(psPMRNode->psFreeList);
654 /* remove block from freelist list */
656 /* Unwrite Freelist with Memory Block physical addresses */
657 eError = PMRUnwritePMPageList(psPMRNode->psPageList);
658 if (eError != PVRSRV_OK)
660 PVR_DPF((PVR_DBG_ERROR,
661 "RGXRemoveBlockFromFreeListKM: Failed to unwrite pages of Node %p",
663 PVR_ASSERT(IMG_FALSE);
666 #if defined(PVR_RI_DEBUG)
668 if (psPMRNode->hRIHandle)
672 eError = RIDeleteMEMDESCEntryKM(psPMRNode->hRIHandle);
673 if( eError != PVRSRV_OK)
675 PVR_DPF((PVR_DBG_ERROR, "%s: call to RIDeleteMEMDESCEntryKM failed (eError=%d)", __func__, eError));
679 #endif /* if defined(PVR_RI_DEBUG) */
681 /* Free PMR (We should be the only one that holds a ref on the PMR) */
682 eError = PMRUnrefPMR(psPMRNode->psPMR);
683 if (eError != PVRSRV_OK)
685 PVR_DPF((PVR_DBG_ERROR,
686 "RGXRemoveBlockFromFreeListKM: Failed to free PB block %p (error %u)",
689 PVR_ASSERT(IMG_FALSE);
692 /* update available pages in freelist */
693 ui32OldValue = psFreeList->ui32CurrentFLPages;
694 psFreeList->ui32CurrentFLPages -= psPMRNode->ui32NumPages;
696 /* check underflow */
697 PVR_ASSERT(ui32OldValue > psFreeList->ui32CurrentFLPages);
699 PVR_DPF((PVR_DBG_MESSAGE, "Freelist [%p]: shrink by %u pages (current pages %u/%u)",
701 psPMRNode->ui32NumPages,
702 psFreeList->ui32CurrentFLPages,
703 psFreeList->ui32MaxFLPages));
705 OSFreeMem(psPMRNode);
709 PVR_DPF((PVR_DBG_WARNING,"Freelist [0x%p]: shrink denied. PB already at initial PB size (%u pages)",
711 psFreeList->ui32InitFLPages));
712 eError = PVRSRV_ERROR_PBSIZE_ALREADY_MIN;
715 OSLockRelease(psFreeList->psDevInfo->hLockFreeList);
720 static RGX_FREELIST *FindFreeList(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32FreelistID)
722 DLLIST_NODE *psNode, *psNext;
723 RGX_FREELIST *psFreeList = NULL;
725 OSLockAcquire(psDevInfo->hLockFreeList);
727 dllist_foreach_node(&psDevInfo->sFreeListHead, psNode, psNext)
729 RGX_FREELIST *psThisFreeList = IMG_CONTAINER_OF(psNode, RGX_FREELIST, sNode);
731 if (psThisFreeList->ui32FreelistID == ui32FreelistID)
733 psFreeList = psThisFreeList;
738 OSLockRelease(psDevInfo->hLockFreeList);
742 void RGXProcessRequestGrow(PVRSRV_RGXDEV_INFO *psDevInfo,
743 IMG_UINT32 ui32FreelistID)
745 RGX_FREELIST *psFreeList = NULL;
746 RGXFWIF_KCCB_CMD s3DCCBCmd;
747 IMG_UINT32 ui32GrowValue;
750 PVR_ASSERT(psDevInfo);
752 psFreeList = FindFreeList(psDevInfo, ui32FreelistID);
756 /* Try to grow the freelist */
757 eError = RGXGrowFreeList(psFreeList,
758 psFreeList->ui32GrowFLPages,
759 &psFreeList->sMemoryBlockHead);
760 if (eError == PVRSRV_OK)
762 /* Grow successful, return size of grow size */
763 ui32GrowValue = psFreeList->ui32GrowFLPages;
765 psFreeList->ui32NumGrowReqByFW++;
767 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
769 PVRSRVStatsUpdateFreelistStats(0,
770 1, /* Add 1 to the appropriate counter (Requests by FW) */
771 psFreeList->ui32InitFLPages,
772 psFreeList->ui32NumHighPages,
773 psFreeList->ownerPid);
782 PVR_DPF((PVR_DBG_ERROR,"Grow for FreeList %p failed (error %u)",
788 s3DCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_FREELIST_GROW_UPDATE;
789 s3DCCBCmd.uCmdData.sFreeListGSData.sFreeListFWDevVAddr.ui32Addr = psFreeList->sFreeListFWDevVAddr.ui32Addr;
790 s3DCCBCmd.uCmdData.sFreeListGSData.ui32DeltaSize = ui32GrowValue;
791 s3DCCBCmd.uCmdData.sFreeListGSData.ui32NewSize = psFreeList->ui32CurrentFLPages;
793 LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
795 eError = RGXScheduleCommand(psDevInfo,
801 if (eError != PVRSRV_ERROR_RETRY)
805 OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
806 } END_LOOP_UNTIL_TIMEOUT();
807 /* Kernel CCB should never fill up, as the FW is processing them right away */
809 PVR_ASSERT(eError == PVRSRV_OK);
813 /* Should never happen */
814 PVR_DPF((PVR_DBG_ERROR,"FreeList Lookup for FreeList ID 0x%08x failed (Populate)", ui32FreelistID));
815 PVR_ASSERT(IMG_FALSE);
819 static void _RGXCheckFreeListReconstruction(PDLLIST_NODE psNode)
822 PVRSRV_RGXDEV_INFO *psDevInfo;
823 RGX_FREELIST *psFreeList;
824 RGX_PMR_NODE *psPMRNode;
826 IMG_DEVMEM_OFFSET_T uiOffset;
827 IMG_DEVMEM_SIZE_T uiLength;
828 IMG_UINT32 ui32StartPage;
830 psPMRNode = IMG_CONTAINER_OF(psNode, RGX_PMR_NODE, sMemoryBlock);
831 psFreeList = psPMRNode->psFreeList;
832 PVR_ASSERT(psFreeList);
833 psDevInfo = psFreeList->psDevInfo;
834 PVR_ASSERT(psDevInfo);
836 uiLength = psPMRNode->ui32NumPages * sizeof(IMG_UINT32);
837 ui32StartPage = (psFreeList->ui32MaxFLPages - psFreeList->ui32CurrentFLPages - psPMRNode->ui32NumPages);
838 uiOffset = psFreeList->uiFreeListPMROffset + (ui32StartPage * sizeof(IMG_UINT32));
840 PMRUnwritePMPageList(psPMRNode->psPageList);
841 psPMRNode->psPageList = NULL;
842 eError = PMRWritePMPageList(
843 /* Target PMR, offset, and length */
844 psFreeList->psFreeListPMR,
847 /* Referenced PMR, and "page" granularity */
849 RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT,
850 &psPMRNode->psPageList);
852 if (eError != PVRSRV_OK)
854 PVR_DPF((PVR_DBG_ERROR,"Error (%u) writing FL 0x%08x", eError, (IMG_UINT32)psFreeList->ui32FreelistID));
857 /* Zeroing physical pages pointed by the reconstructed freelist */
858 if (psDevInfo->ui32DeviceFlags & RGXKM_DEVICE_STATE_ZERO_FREELIST)
860 eError = PMRZeroingPMR(psPMRNode->psPMR, RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT);
861 if (eError != PVRSRV_OK)
863 PVR_DPF((PVR_DBG_ERROR,"_RGXCheckFreeListReconstruction: Failed to zero PMR %p of freelist %p with Error %d",
871 psFreeList->ui32CurrentFLPages += psPMRNode->ui32NumPages;
875 static PVRSRV_ERROR RGXReconstructFreeList(RGX_FREELIST *psFreeList)
877 DLLIST_NODE *psNode, *psNext;
878 RGXFWIF_FREELIST *psFWFreeList;
881 //PVR_DPF((PVR_DBG_ERROR, "FreeList RECONSTRUCTION: Reconstructing freelist %p (ID=%u)", psFreeList, psFreeList->ui32FreelistID));
883 /* Do the FreeList Reconstruction */
884 psFreeList->ui32CurrentFLPages = 0;
886 /* Reconstructing Init FreeList pages */
887 dllist_foreach_node(&psFreeList->sMemoryBlockInitHead, psNode, psNext)
889 _RGXCheckFreeListReconstruction(psNode);
892 /* Reconstructing Grow FreeList pages */
893 dllist_foreach_node(&psFreeList->sMemoryBlockHead, psNode, psNext)
895 _RGXCheckFreeListReconstruction(psNode);
898 /* Reset the firmware freelist structure */
899 eError = DevmemAcquireCpuVirtAddr(psFreeList->psFWFreelistMemDesc, (void **)&psFWFreeList);
900 if (eError != PVRSRV_OK)
905 psFWFreeList->ui32CurrentStackTop = psFWFreeList->ui32CurrentPages - 1;
906 psFWFreeList->ui32AllocatedPageCount = 0;
907 psFWFreeList->ui32AllocatedMMUPageCount = 0;
908 psFWFreeList->ui32HWRCounter++;
910 DevmemReleaseCpuVirtAddr(psFreeList->psFWFreelistMemDesc);
912 /* Check the Freelist checksum if required (as the list is fully populated) */
913 if (psFreeList->bCheckFreelist)
915 IMG_UINT64 ui64CheckSum;
917 _CheckFreelist(psFreeList, psFreeList->ui32CurrentFLPages, psFreeList->ui64FreelistChecksum, &ui64CheckSum);
924 void RGXProcessRequestFreelistsReconstruction(PVRSRV_RGXDEV_INFO *psDevInfo,
925 IMG_UINT32 ui32FreelistsCount,
926 IMG_UINT32 *paui32Freelists)
928 PVRSRV_ERROR eError = PVRSRV_OK;
929 DLLIST_NODE *psNode, *psNext;
931 RGXFWIF_KCCB_CMD sTACCBCmd;
933 PVR_ASSERT(psDevInfo != NULL);
934 PVR_ASSERT(ui32FreelistsCount <= (MAX_HW_TA3DCONTEXTS * RGXFW_MAX_FREELISTS));
936 //PVR_DPF((PVR_DBG_ERROR, "FreeList RECONSTRUCTION: %u freelist(s) requested for reconstruction", ui32FreelistsCount));
939 * Initialise the response command (in case we don't find a freelist ID)...
941 sTACCBCmd.eCmdType = RGXFWIF_KCCB_CMD_FREELISTS_RECONSTRUCTION_UPDATE;
942 sTACCBCmd.uCmdData.sFreeListsReconstructionData.ui32FreelistsCount = ui32FreelistsCount;
944 for (ui32Loop = 0; ui32Loop < ui32FreelistsCount; ui32Loop++)
946 sTACCBCmd.uCmdData.sFreeListsReconstructionData.aui32FreelistIDs[ui32Loop] = paui32Freelists[ui32Loop] |
947 RGXFWIF_FREELISTS_RECONSTRUCTION_FAILED_FLAG;
951 * The list of freelists we have been given for reconstruction will
952 * consist of local and global freelists (maybe MMU as well). Any
953 * local freelists will have their global list specified as well.
954 * However there may be other local freelists not listed, which are
955 * going to have their global freelist reconstructed. Therefore we
956 * have to find those freelists as well meaning we will have to
957 * iterate the entire list of freelists to find which must be reconstructed.
959 OSLockAcquire(psDevInfo->hLockFreeList);
960 dllist_foreach_node(&psDevInfo->sFreeListHead, psNode, psNext)
962 RGX_FREELIST *psFreeList = IMG_CONTAINER_OF(psNode, RGX_FREELIST, sNode);
963 IMG_BOOL bReconstruct = IMG_FALSE;
966 * Check if this freelist needs to be reconstructed (was it requested
967 * or was its global freelist requested)...
969 for (ui32Loop = 0; ui32Loop < ui32FreelistsCount; ui32Loop++)
971 if (paui32Freelists[ui32Loop] == psFreeList->ui32FreelistID ||
972 paui32Freelists[ui32Loop] == psFreeList->ui32FreelistGlobalID)
974 bReconstruct = IMG_TRUE;
981 eError = RGXReconstructFreeList(psFreeList);
982 if (eError == PVRSRV_OK)
984 for (ui32Loop = 0; ui32Loop < ui32FreelistsCount; ui32Loop++)
986 if (paui32Freelists[ui32Loop] == psFreeList->ui32FreelistID)
988 /* Reconstruction of this requested freelist was successful... */
989 sTACCBCmd.uCmdData.sFreeListsReconstructionData.aui32FreelistIDs[ui32Loop] &= ~RGXFWIF_FREELISTS_RECONSTRUCTION_FAILED_FLAG;
996 PVR_DPF((PVR_DBG_ERROR,"Reconstructing of FreeList %p failed (error %u)",
1002 OSLockRelease(psDevInfo->hLockFreeList);
1004 /* Check that all freelists were found and reconstructed... */
1005 for (ui32Loop = 0; ui32Loop < ui32FreelistsCount; ui32Loop++)
1007 PVR_ASSERT((sTACCBCmd.uCmdData.sFreeListsReconstructionData.aui32FreelistIDs[ui32Loop] &
1008 RGXFWIF_FREELISTS_RECONSTRUCTION_FAILED_FLAG) == 0);
1012 LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
1014 eError = RGXScheduleCommand(psDevInfo,
1020 if (eError != PVRSRV_ERROR_RETRY)
1024 OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
1025 } END_LOOP_UNTIL_TIMEOUT();
1027 /* Kernel CCB should never fill up, as the FW is processing them right away */
1028 PVR_ASSERT(eError == PVRSRV_OK);
1031 /* Create HWRTDataSet */
1033 PVRSRV_ERROR RGXCreateHWRTData(CONNECTION_DATA *psConnection,
1034 PVRSRV_DEVICE_NODE *psDeviceNode,
1035 IMG_UINT32 psRenderTarget, /* FIXME this should not be IMG_UINT32 */
1036 IMG_DEV_VIRTADDR psPMMListDevVAddr,
1037 IMG_DEV_VIRTADDR psVFPPageTableAddr,
1038 RGX_FREELIST *apsFreeLists[RGXFW_MAX_FREELISTS],
1039 RGX_RTDATA_CLEANUP_DATA **ppsCleanupData,
1040 DEVMEM_MEMDESC **ppsRTACtlMemDesc,
1041 IMG_UINT32 ui32PPPScreen,
1042 IMG_UINT32 ui32PPPGridOffset,
1043 IMG_UINT64 ui64PPPMultiSampleCtl,
1044 IMG_UINT32 ui32TPCStride,
1045 IMG_DEV_VIRTADDR sTailPtrsDevVAddr,
1046 IMG_UINT32 ui32TPCSize,
1047 IMG_UINT32 ui32TEScreen,
1048 IMG_UINT32 ui32TEAA,
1049 IMG_UINT32 ui32TEMTILE1,
1050 IMG_UINT32 ui32TEMTILE2,
1051 IMG_UINT32 ui32MTileStride,
1052 IMG_UINT32 ui32ISPMergeLowerX,
1053 IMG_UINT32 ui32ISPMergeLowerY,
1054 IMG_UINT32 ui32ISPMergeUpperX,
1055 IMG_UINT32 ui32ISPMergeUpperY,
1056 IMG_UINT32 ui32ISPMergeScaleX,
1057 IMG_UINT32 ui32ISPMergeScaleY,
1058 IMG_UINT16 ui16MaxRTs,
1059 DEVMEM_MEMDESC **ppsMemDesc,
1060 IMG_UINT32 *puiHWRTData)
1062 PVRSRV_ERROR eError;
1063 PVRSRV_RGXDEV_INFO *psDevInfo;
1064 RGXFWIF_DEV_VIRTADDR pFirmwareAddr;
1065 RGXFWIF_HWRTDATA *psHWRTData;
1066 RGXFWIF_RTA_CTL *psRTACtl;
1067 IMG_UINT32 ui32Loop;
1068 RGX_RTDATA_CLEANUP_DATA *psTmpCleanup;
1070 PVR_UNREFERENCED_PARAMETER(psConnection);
1072 /* Prepare cleanup struct */
1073 psTmpCleanup = OSAllocZMem(sizeof(*psTmpCleanup));
1074 if (psTmpCleanup == NULL)
1076 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1080 *ppsCleanupData = psTmpCleanup;
1082 /* Allocate cleanup sync */
1083 eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext,
1084 &psTmpCleanup->psCleanupSync,
1085 "HWRTData cleanup");
1086 if (eError != PVRSRV_OK)
1088 PVR_DPF((PVR_DBG_ERROR,"RGXCreateHWRTData: Failed to allocate cleanup sync (0x%x)",
1093 psDevInfo = psDeviceNode->pvDevice;
1096 * This FW RT-Data is only mapped into kernel for initialisation.
1097 * Otherwise this allocation is only used by the FW.
1098 * Therefore the GPU cache doesn't need coherency,
1099 * and write-combine is suffice on the CPU side (WC buffer will be flushed at the first TA-kick)
1101 eError = DevmemFwAllocate(psDevInfo,
1102 sizeof(RGXFWIF_HWRTDATA),
1103 PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
1104 PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED) |
1105 PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
1106 PVRSRV_MEMALLOCFLAG_GPU_READABLE |
1107 PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
1108 PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
1109 PVRSRV_MEMALLOCFLAG_CPU_READABLE |
1110 PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
1111 PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE |
1112 PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE,
1115 if (eError != PVRSRV_OK)
1117 PVR_DPF((PVR_DBG_ERROR, "RGXCreateHWRTData: DevmemAllocate for RGX_FWIF_HWRTDATA failed"));
1118 goto FWRTDataAllocateError;
1121 psTmpCleanup->psDeviceNode = psDeviceNode;
1122 psTmpCleanup->psFWHWRTDataMemDesc = *ppsMemDesc;
1124 RGXSetFirmwareAddress(&pFirmwareAddr, *ppsMemDesc, 0, RFW_FWADDR_FLAG_NONE);
1126 *puiHWRTData = pFirmwareAddr.ui32Addr;
1128 eError = DevmemAcquireCpuVirtAddr(*ppsMemDesc, (void **)&psHWRTData);
1129 PVR_LOGG_IF_ERROR(eError, "Devmem AcquireCpuVirtAddr", FWRTDataCpuMapError);
1131 /* FIXME: MList is something that that PM writes physical addresses to,
1132 * so ideally its best allocated in kernel */
1133 psHWRTData->psPMMListDevVAddr = psPMMListDevVAddr;
1134 psHWRTData->psParentRenderTarget.ui32Addr = psRenderTarget;
1135 #if defined(SUPPORT_VFP)
1136 psHWRTData->sVFPPageTableAddr = psVFPPageTableAddr;
1139 psHWRTData->ui32PPPScreen = ui32PPPScreen;
1140 psHWRTData->ui32PPPGridOffset = ui32PPPGridOffset;
1141 psHWRTData->ui64PPPMultiSampleCtl = ui64PPPMultiSampleCtl;
1142 psHWRTData->ui32TPCStride = ui32TPCStride;
1143 psHWRTData->sTailPtrsDevVAddr = sTailPtrsDevVAddr;
1144 psHWRTData->ui32TPCSize = ui32TPCSize;
1145 psHWRTData->ui32TEScreen = ui32TEScreen;
1146 psHWRTData->ui32TEAA = ui32TEAA;
1147 psHWRTData->ui32TEMTILE1 = ui32TEMTILE1;
1148 psHWRTData->ui32TEMTILE2 = ui32TEMTILE2;
1149 psHWRTData->ui32MTileStride = ui32MTileStride;
1150 psHWRTData->ui32ISPMergeLowerX = ui32ISPMergeLowerX;
1151 psHWRTData->ui32ISPMergeLowerY = ui32ISPMergeLowerY;
1152 psHWRTData->ui32ISPMergeUpperX = ui32ISPMergeUpperX;
1153 psHWRTData->ui32ISPMergeUpperY = ui32ISPMergeUpperY;
1154 psHWRTData->ui32ISPMergeScaleX = ui32ISPMergeScaleX;
1155 psHWRTData->ui32ISPMergeScaleY = ui32ISPMergeScaleY;
1157 OSLockAcquire(psDevInfo->hLockFreeList);
1158 for (ui32Loop = 0; ui32Loop < RGXFW_MAX_FREELISTS; ui32Loop++)
1160 psTmpCleanup->apsFreeLists[ui32Loop] = apsFreeLists[ui32Loop];
1161 psTmpCleanup->apsFreeLists[ui32Loop]->ui32RefCount++;
1162 psHWRTData->apsFreeLists[ui32Loop].ui32Addr = psTmpCleanup->apsFreeLists[ui32Loop]->sFreeListFWDevVAddr.ui32Addr;
1163 /* invalid initial snapshot value, the snapshot is always taken during first kick
1164 * and hence the value get replaced during the first kick anyway. So it's safe to set it 0.
1166 psHWRTData->aui32FreeListHWRSnapshot[ui32Loop] = 0;
1168 OSLockRelease(psDevInfo->hLockFreeList);
1170 PDUMPCOMMENT("Allocate RGXFW RTA control");
1171 eError = DevmemFwAllocate(psDevInfo,
1172 sizeof(RGXFWIF_RTA_CTL),
1173 PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
1174 PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED) |
1175 PVRSRV_MEMALLOCFLAG_GPU_READABLE |
1176 PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
1177 PVRSRV_MEMALLOCFLAG_UNCACHED |
1178 PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC,
1182 if (eError != PVRSRV_OK)
1184 PVR_DPF((PVR_DBG_ERROR,"RGXCreateHWRTData: Failed to allocate RGX RTA control (%u)",
1186 goto FWRTAAllocateError;
1188 psTmpCleanup->psRTACtlMemDesc = *ppsRTACtlMemDesc;
1189 RGXSetFirmwareAddress(&psHWRTData->psRTACtl,
1191 0, RFW_FWADDR_FLAG_NONE);
1193 eError = DevmemAcquireCpuVirtAddr(*ppsRTACtlMemDesc, (void **)&psRTACtl);
1194 PVR_LOGG_IF_ERROR(eError, "Devmem AcquireCpuVirtAddr", FWRTACpuMapError);
1195 psRTACtl->ui32RenderTargetIndex = 0;
1196 psRTACtl->ui32ActiveRenderTargets = 0;
1200 /* Allocate memory for the checks */
1201 PDUMPCOMMENT("Allocate memory for shadow render target cache");
1202 eError = DevmemFwAllocate(psDevInfo,
1203 ui16MaxRTs * sizeof(IMG_UINT32),
1204 PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
1205 PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED) |
1206 PVRSRV_MEMALLOCFLAG_GPU_READABLE |
1207 PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
1208 PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
1209 PVRSRV_MEMALLOCFLAG_UNCACHED|
1210 PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC,
1212 &psTmpCleanup->psRTArrayMemDesc);
1213 if (eError != PVRSRV_OK)
1215 PVR_DPF((PVR_DBG_ERROR,"RGXCreateHWRTData: Failed to allocate %d bytes for render target array (%u)",
1216 ui16MaxRTs, eError));
1217 goto FWAllocateRTArryError;
1220 RGXSetFirmwareAddress(&psRTACtl->sValidRenderTargets,
1221 psTmpCleanup->psRTArrayMemDesc,
1222 0, RFW_FWADDR_FLAG_NONE);
1224 /* Allocate memory for the checks */
1225 PDUMPCOMMENT("Allocate memory for tracking renders accumulation");
1226 eError = DevmemFwAllocate(psDevInfo,
1227 ui16MaxRTs * sizeof(IMG_UINT32),
1228 PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
1229 PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED) |
1230 PVRSRV_MEMALLOCFLAG_GPU_READABLE |
1231 PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
1232 PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
1233 PVRSRV_MEMALLOCFLAG_UNCACHED|
1234 PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC,
1235 "FwRendersAccumulation",
1236 &psTmpCleanup->psRendersAccArrayMemDesc);
1237 if (eError != PVRSRV_OK)
1239 PVR_DPF((PVR_DBG_ERROR,"RGXCreateHWRTData: Failed to allocate %d bytes for render target array (%u) (renders accumulation)",
1240 ui16MaxRTs, eError));
1241 goto FWAllocateRTAccArryError;
1244 RGXSetFirmwareAddress(&psRTACtl->sNumRenders,
1245 psTmpCleanup->psRendersAccArrayMemDesc,
1246 0, RFW_FWADDR_FLAG_NONE);
1247 psRTACtl->ui16MaxRTs = ui16MaxRTs;
1251 psRTACtl->sValidRenderTargets.ui32Addr = 0;
1252 psRTACtl->sNumRenders.ui32Addr = 0;
1253 psRTACtl->ui16MaxRTs = 1;
1256 PDUMPCOMMENT("Dump HWRTData 0x%08X", *puiHWRTData);
1257 DevmemPDumpLoadMem(*ppsMemDesc, 0, sizeof(*psHWRTData), PDUMP_FLAGS_CONTINUOUS);
1258 PDUMPCOMMENT("Dump RTACtl");
1259 DevmemPDumpLoadMem(*ppsRTACtlMemDesc, 0, sizeof(*psRTACtl), PDUMP_FLAGS_CONTINUOUS);
1261 DevmemReleaseCpuVirtAddr(*ppsMemDesc);
1262 DevmemReleaseCpuVirtAddr(*ppsRTACtlMemDesc);
1265 FWAllocateRTAccArryError:
1266 DevmemFwFree(psDevInfo, psTmpCleanup->psRTArrayMemDesc);
1267 FWAllocateRTArryError:
1268 DevmemReleaseCpuVirtAddr(*ppsRTACtlMemDesc);
1270 RGXUnsetFirmwareAddress(*ppsRTACtlMemDesc);
1271 DevmemFwFree(psDevInfo, *ppsRTACtlMemDesc);
1273 OSLockAcquire(psDevInfo->hLockFreeList);
1274 for (ui32Loop = 0; ui32Loop < RGXFW_MAX_FREELISTS; ui32Loop++)
1276 PVR_ASSERT(psTmpCleanup->apsFreeLists[ui32Loop]->ui32RefCount > 0);
1277 psTmpCleanup->apsFreeLists[ui32Loop]->ui32RefCount--;
1279 OSLockRelease(psDevInfo->hLockFreeList);
1280 DevmemReleaseCpuVirtAddr(*ppsMemDesc);
1281 FWRTDataCpuMapError:
1282 RGXUnsetFirmwareAddress(*ppsMemDesc);
1283 DevmemFwFree(psDevInfo, *ppsMemDesc);
1284 FWRTDataAllocateError:
1285 SyncPrimFree(psTmpCleanup->psCleanupSync);
1287 *ppsCleanupData = NULL;
1288 OSFreeMem(psTmpCleanup);
1294 /* Destroy HWRTDataSet */
1296 PVRSRV_ERROR RGXDestroyHWRTData(RGX_RTDATA_CLEANUP_DATA *psCleanupData)
1298 PVRSRV_RGXDEV_INFO *psDevInfo;
1299 PVRSRV_ERROR eError;
1300 PRGXFWIF_HWRTDATA psHWRTData;
1301 IMG_UINT32 ui32Loop;
1303 PVR_ASSERT(psCleanupData);
1305 RGXSetFirmwareAddress(&psHWRTData, psCleanupData->psFWHWRTDataMemDesc, 0, RFW_FWADDR_NOREF_FLAG);
1307 /* Cleanup HWRTData in TA */
1308 eError = RGXFWRequestHWRTDataCleanUp(psCleanupData->psDeviceNode,
1310 psCleanupData->psCleanupSync,
1312 if (eError == PVRSRV_ERROR_RETRY)
1317 psDevInfo = psCleanupData->psDeviceNode->pvDevice;
1319 /* Cleanup HWRTData in 3D */
1320 eError = RGXFWRequestHWRTDataCleanUp(psCleanupData->psDeviceNode,
1322 psCleanupData->psCleanupSync,
1324 if (eError == PVRSRV_ERROR_RETRY)
1329 /* If we got here then TA and 3D operations on this RTData have finished */
1330 if(psCleanupData->psRTACtlMemDesc)
1332 RGXUnsetFirmwareAddress(psCleanupData->psRTACtlMemDesc);
1333 DevmemFwFree(psDevInfo, psCleanupData->psRTACtlMemDesc);
1336 RGXUnsetFirmwareAddress(psCleanupData->psFWHWRTDataMemDesc);
1337 DevmemFwFree(psDevInfo, psCleanupData->psFWHWRTDataMemDesc);
1339 if(psCleanupData->psRTArrayMemDesc)
1341 RGXUnsetFirmwareAddress(psCleanupData->psRTArrayMemDesc);
1342 DevmemFwFree(psDevInfo, psCleanupData->psRTArrayMemDesc);
1345 if(psCleanupData->psRendersAccArrayMemDesc)
1347 RGXUnsetFirmwareAddress(psCleanupData->psRendersAccArrayMemDesc);
1348 DevmemFwFree(psDevInfo, psCleanupData->psRendersAccArrayMemDesc);
1351 SyncPrimFree(psCleanupData->psCleanupSync);
1353 /* decrease freelist refcount */
1354 OSLockAcquire(psDevInfo->hLockFreeList);
1355 for (ui32Loop = 0; ui32Loop < RGXFW_MAX_FREELISTS; ui32Loop++)
1357 PVR_ASSERT(psCleanupData->apsFreeLists[ui32Loop]->ui32RefCount > 0);
1358 psCleanupData->apsFreeLists[ui32Loop]->ui32RefCount--;
1360 OSLockRelease(psDevInfo->hLockFreeList);
1362 OSFreeMem(psCleanupData);
1368 PVRSRV_ERROR RGXCreateFreeList(CONNECTION_DATA *psConnection,
1369 PVRSRV_DEVICE_NODE *psDeviceNode,
1370 IMG_UINT32 ui32MaxFLPages,
1371 IMG_UINT32 ui32InitFLPages,
1372 IMG_UINT32 ui32GrowFLPages,
1373 RGX_FREELIST *psGlobalFreeList,
1374 IMG_BOOL bCheckFreelist,
1375 IMG_DEV_VIRTADDR sFreeListDevVAddr,
1377 IMG_DEVMEM_OFFSET_T uiFreeListPMROffset,
1378 RGX_FREELIST **ppsFreeList)
1380 PVRSRV_ERROR eError;
1381 RGXFWIF_FREELIST *psFWFreeList;
1382 DEVMEM_MEMDESC *psFWFreelistMemDesc;
1383 RGX_FREELIST *psFreeList;
1384 PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
1386 /* Allocate kernel freelist struct */
1387 psFreeList = OSAllocZMem(sizeof(*psFreeList));
1388 if (psFreeList == NULL)
1390 PVR_DPF((PVR_DBG_ERROR, "RGXCreateFreeList: failed to allocate host data structure"));
1391 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1392 goto ErrorAllocHost;
1395 /* Allocate cleanup sync */
1396 eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext,
1397 &psFreeList->psCleanupSync,
1398 "ta3d free list cleanup");
1399 if (eError != PVRSRV_OK)
1401 PVR_DPF((PVR_DBG_ERROR,"RGXCreateFreeList: Failed to allocate cleanup sync (0x%x)",
1407 * This FW FreeList context is only mapped into kernel for initialisation
1408 * and reconstruction (at other times it is not mapped and only used by
1409 * the FW. Therefore the GPU cache doesn't need coherency, and write-combine
1410 * is suffice on the CPU side (WC buffer will be flushed at the first TA-kick)
1412 eError = DevmemFwAllocate(psDevInfo,
1413 sizeof(*psFWFreeList),
1414 PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
1415 PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
1416 PVRSRV_MEMALLOCFLAG_GPU_READABLE |
1417 PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
1418 PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
1419 PVRSRV_MEMALLOCFLAG_CPU_READABLE |
1420 PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
1421 PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE |
1422 PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE,
1424 &psFWFreelistMemDesc);
1425 if (eError != PVRSRV_OK)
1427 PVR_DPF((PVR_DBG_ERROR, "RGXCreateFreeList: DevmemAllocate for RGXFWIF_FREELIST failed"));
1428 goto FWFreeListAlloc;
1431 /* Initialise host data structures */
1432 psFreeList->psDevInfo = psDevInfo;
1433 psFreeList->psFreeListPMR = psFreeListPMR;
1434 psFreeList->uiFreeListPMROffset = uiFreeListPMROffset;
1435 psFreeList->psFWFreelistMemDesc = psFWFreelistMemDesc;
1436 RGXSetFirmwareAddress(&psFreeList->sFreeListFWDevVAddr, psFWFreelistMemDesc, 0, RFW_FWADDR_FLAG_NONE);
1437 psFreeList->ui32FreelistID = psDevInfo->ui32FreelistCurrID++;
1438 psFreeList->ui32FreelistGlobalID = (psGlobalFreeList ? psGlobalFreeList->ui32FreelistID : 0);
1439 psFreeList->ui32MaxFLPages = ui32MaxFLPages;
1440 psFreeList->ui32InitFLPages = ui32InitFLPages;
1441 psFreeList->ui32GrowFLPages = ui32GrowFLPages;
1442 psFreeList->ui32CurrentFLPages = 0;
1443 psFreeList->ui64FreelistChecksum = 0;
1444 psFreeList->ui32RefCount = 0;
1445 psFreeList->bCheckFreelist = bCheckFreelist;
1446 dllist_init(&psFreeList->sMemoryBlockHead);
1447 dllist_init(&psFreeList->sMemoryBlockInitHead);
1450 /* Add to list of freelists */
1451 OSLockAcquire(psDevInfo->hLockFreeList);
1452 dllist_add_to_tail(&psDevInfo->sFreeListHead, &psFreeList->sNode);
1453 OSLockRelease(psDevInfo->hLockFreeList);
1456 /* Initialise FW data structure */
1457 eError = DevmemAcquireCpuVirtAddr(psFreeList->psFWFreelistMemDesc, (void **)&psFWFreeList);
1458 PVR_LOGG_IF_ERROR(eError, "Devmem AcquireCpuVirtAddr", FWFreeListCpuMap);
1460 psFWFreeList->ui32MaxPages = ui32MaxFLPages;
1461 psFWFreeList->ui32CurrentPages = ui32InitFLPages;
1462 psFWFreeList->ui32GrowPages = ui32GrowFLPages;
1463 psFWFreeList->ui32CurrentStackTop = ui32InitFLPages - 1;
1464 psFWFreeList->psFreeListDevVAddr = sFreeListDevVAddr;
1465 psFWFreeList->ui64CurrentDevVAddr = sFreeListDevVAddr.uiAddr + ((ui32MaxFLPages - ui32InitFLPages) * sizeof(IMG_UINT32));
1466 psFWFreeList->ui32FreeListID = psFreeList->ui32FreelistID;
1467 psFWFreeList->bGrowPending = IMG_FALSE;
1469 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",
1473 sFreeListDevVAddr.uiAddr,
1474 psFWFreeList->psFreeListDevVAddr.uiAddr));
1476 PDUMPCOMMENT("Dump FW FreeList");
1477 DevmemPDumpLoadMem(psFreeList->psFWFreelistMemDesc, 0, sizeof(*psFWFreeList), PDUMP_FLAGS_CONTINUOUS);
1480 * Separate dump of the Freelist's number of Pages and stack pointer.
1481 * This allows to easily modify the PB size in the out2.txt files.
1483 PDUMPCOMMENT("FreeList TotalPages");
1484 DevmemPDumpLoadMemValue32(psFreeList->psFWFreelistMemDesc,
1485 offsetof(RGXFWIF_FREELIST, ui32CurrentPages),
1486 psFWFreeList->ui32CurrentPages,
1487 PDUMP_FLAGS_CONTINUOUS);
1488 PDUMPCOMMENT("FreeList StackPointer");
1489 DevmemPDumpLoadMemValue32(psFreeList->psFWFreelistMemDesc,
1490 offsetof(RGXFWIF_FREELIST, ui32CurrentStackTop),
1491 psFWFreeList->ui32CurrentStackTop,
1492 PDUMP_FLAGS_CONTINUOUS);
1494 DevmemReleaseCpuVirtAddr(psFreeList->psFWFreelistMemDesc);
1497 /* Add initial PB block */
1498 eError = RGXGrowFreeList(psFreeList,
1500 &psFreeList->sMemoryBlockInitHead);
1501 if (eError != PVRSRV_OK)
1503 PVR_DPF((PVR_DBG_ERROR,
1504 "RGXCreateFreeList: failed to allocate initial memory block for free list 0x%016llx (error = %u)",
1505 sFreeListDevVAddr.uiAddr,
1507 goto FWFreeListCpuMap;
1509 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
1511 PVRSRVStatsUpdateFreelistStats(1, /* Add 1 to the appropriate counter (Requests by App)*/
1513 psFreeList->ui32InitFLPages,
1514 psFreeList->ui32NumHighPages,
1515 psFreeList->ownerPid);
1519 psFreeList->ownerPid = OSGetCurrentClientProcessIDKM();
1521 *ppsFreeList = psFreeList;
1525 /* Error handling */
1528 /* Remove freelists from list */
1529 OSLockAcquire(psDevInfo->hLockFreeList);
1530 dllist_remove_node(&psFreeList->sNode);
1531 OSLockRelease(psDevInfo->hLockFreeList);
1533 RGXUnsetFirmwareAddress(psFWFreelistMemDesc);
1534 DevmemFwFree(psDevInfo, psFWFreelistMemDesc);
1537 SyncPrimFree(psFreeList->psCleanupSync);
1540 OSFreeMem(psFreeList);
1543 PVR_ASSERT(eError != PVRSRV_OK);
1552 PVRSRV_ERROR RGXDestroyFreeList(RGX_FREELIST *psFreeList)
1554 PVRSRV_ERROR eError;
1556 PVR_ASSERT(psFreeList);
1558 if (psFreeList->ui32RefCount != 0)
1560 /* Freelist still busy */
1561 return PVRSRV_ERROR_RETRY;
1564 /* Freelist is not in use => start firmware cleanup */
1565 eError = RGXFWRequestFreeListCleanUp(psFreeList->psDevInfo,
1566 psFreeList->sFreeListFWDevVAddr,
1567 psFreeList->psCleanupSync);
1568 if(eError != PVRSRV_OK)
1570 /* Can happen if the firmware took too long to handle the cleanup request,
1571 * or if SLC-flushes didn't went through (due to some GPU lockup) */
1575 /* Remove FreeList from linked list before we destroy it... */
1576 OSLockAcquire(psFreeList->psDevInfo->hLockFreeList);
1577 dllist_remove_node(&psFreeList->sNode);
1578 OSLockRelease(psFreeList->psDevInfo->hLockFreeList);
1580 if (psFreeList->bCheckFreelist)
1582 RGXFWIF_FREELIST *psFWFreeList;
1583 IMG_UINT64 ui32CurrentStackTop;
1584 IMG_UINT64 ui64CheckSum;
1586 /* Get the current stack pointer for this free list */
1587 DevmemAcquireCpuVirtAddr(psFreeList->psFWFreelistMemDesc, (void **)&psFWFreeList);
1588 ui32CurrentStackTop = psFWFreeList->ui32CurrentStackTop;
1589 DevmemReleaseCpuVirtAddr(psFreeList->psFWFreelistMemDesc);
1591 if (ui32CurrentStackTop == psFreeList->ui32CurrentFLPages-1)
1593 /* Do consistency tests (as the list is fully populated) */
1594 _CheckFreelist(psFreeList, psFreeList->ui32CurrentFLPages, psFreeList->ui64FreelistChecksum, &ui64CheckSum);
1598 /* Check for duplicate pages, but don't check the checksum as the list is not fully populated */
1599 _CheckFreelist(psFreeList, ui32CurrentStackTop+1, 0, &ui64CheckSum);
1603 /* Destroy FW structures */
1604 RGXUnsetFirmwareAddress(psFreeList->psFWFreelistMemDesc);
1605 DevmemFwFree(psFreeList->psDevInfo, psFreeList->psFWFreelistMemDesc);
1607 /* Remove grow shrink blocks */
1608 while (!dllist_is_empty(&psFreeList->sMemoryBlockHead))
1610 eError = RGXShrinkFreeList(&psFreeList->sMemoryBlockHead, psFreeList);
1611 PVR_ASSERT(eError == PVRSRV_OK);
1614 /* Remove initial PB block */
1615 eError = RGXShrinkFreeList(&psFreeList->sMemoryBlockInitHead, psFreeList);
1616 PVR_ASSERT(eError == PVRSRV_OK);
1618 /* consistency checks */
1619 PVR_ASSERT(dllist_is_empty(&psFreeList->sMemoryBlockInitHead));
1620 PVR_ASSERT(psFreeList->ui32CurrentFLPages == 0);
1622 SyncPrimFree(psFreeList->psCleanupSync);
1625 OSFreeMem(psFreeList);
1633 RGXAddBlockToFreeListKM
1637 PVRSRV_ERROR RGXAddBlockToFreeListKM(RGX_FREELIST *psFreeList,
1638 IMG_UINT32 ui32NumPages)
1640 PVRSRV_ERROR eError;
1642 /* Check if we have reference to freelist's PMR */
1643 if (psFreeList->psFreeListPMR == NULL)
1645 PVR_DPF((PVR_DBG_ERROR, "Freelist is not configured for grow"));
1646 return PVRSRV_ERROR_INVALID_PARAMS;
1650 eError = RGXGrowFreeList(psFreeList,
1652 &psFreeList->sMemoryBlockHead);
1653 if(eError == PVRSRV_OK)
1655 /* update freelist data in firmware */
1656 _UpdateFwFreelistSize(psFreeList, IMG_TRUE, ui32NumPages);
1658 psFreeList->ui32NumGrowReqByApp++;
1660 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
1662 PVRSRVStatsUpdateFreelistStats(1, /* Add 1 to the appropriate counter (Requests by App)*/
1664 psFreeList->ui32InitFLPages,
1665 psFreeList->ui32NumHighPages,
1666 psFreeList->ownerPid);
1675 RGXRemoveBlockFromFreeListKM
1679 PVRSRV_ERROR RGXRemoveBlockFromFreeListKM(RGX_FREELIST *psFreeList)
1681 PVRSRV_ERROR eError;
1684 * Make sure the pages part of the memory block are not in use anymore.
1685 * Instruct the firmware to update the freelist pointers accordingly.
1688 eError = RGXShrinkFreeList(&psFreeList->sMemoryBlockHead,
1696 RGXCreateRenderTarget
1699 PVRSRV_ERROR RGXCreateRenderTarget(CONNECTION_DATA *psConnection,
1700 PVRSRV_DEVICE_NODE *psDeviceNode,
1701 IMG_DEV_VIRTADDR psVHeapTableDevVAddr,
1702 RGX_RT_CLEANUP_DATA **ppsCleanupData,
1703 IMG_UINT32 *sRenderTargetFWDevVAddr)
1705 PVRSRV_ERROR eError = PVRSRV_OK;
1706 RGXFWIF_RENDER_TARGET *psRenderTarget;
1707 RGXFWIF_DEV_VIRTADDR pFirmwareAddr;
1708 PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
1709 RGX_RT_CLEANUP_DATA *psCleanupData;
1711 PVR_UNREFERENCED_PARAMETER(psConnection);
1713 psCleanupData = OSAllocZMem(sizeof(*psCleanupData));
1714 if (psCleanupData == NULL)
1716 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1720 psCleanupData->psDeviceNode = psDeviceNode;
1722 * This FW render target context is only mapped into kernel for initialisation.
1723 * Otherwise this allocation is only used by the FW.
1724 * Therefore the GPU cache doesn't need coherency,
1725 * and write-combine is suffice on the CPU side (WC buffer will be flushed at the first TA-kick)
1727 eError = DevmemFwAllocate(psDevInfo,
1728 sizeof(*psRenderTarget),
1729 PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
1730 PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
1731 PVRSRV_MEMALLOCFLAG_GPU_READABLE |
1732 PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
1733 PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
1734 PVRSRV_MEMALLOCFLAG_CPU_READABLE |
1735 PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
1736 PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE |
1737 PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE,
1739 &psCleanupData->psRenderTargetMemDesc);
1740 if (eError != PVRSRV_OK)
1742 PVR_DPF((PVR_DBG_ERROR, "RGXCreateRenderTarget: DevmemAllocate for Render Target failed"));
1745 RGXSetFirmwareAddress(&pFirmwareAddr, psCleanupData->psRenderTargetMemDesc, 0, RFW_FWADDR_FLAG_NONE);
1746 *sRenderTargetFWDevVAddr = pFirmwareAddr.ui32Addr;
1748 eError = DevmemAcquireCpuVirtAddr(psCleanupData->psRenderTargetMemDesc, (void **)&psRenderTarget);
1749 PVR_LOGG_IF_ERROR(eError, "Devmem AcquireCpuVirtAddr", err_fwalloc);
1751 psRenderTarget->psVHeapTableDevVAddr = psVHeapTableDevVAddr;
1752 psRenderTarget->bTACachesNeedZeroing = IMG_FALSE;
1753 PDUMPCOMMENT("Dump RenderTarget");
1754 DevmemPDumpLoadMem(psCleanupData->psRenderTargetMemDesc, 0, sizeof(*psRenderTarget), PDUMP_FLAGS_CONTINUOUS);
1755 DevmemReleaseCpuVirtAddr(psCleanupData->psRenderTargetMemDesc);
1757 *ppsCleanupData = psCleanupData;
1763 OSFreeMem(psCleanupData);
1767 DevmemFwFree(psDevInfo, psCleanupData->psRenderTargetMemDesc);
1774 RGXDestroyRenderTarget
1777 PVRSRV_ERROR RGXDestroyRenderTarget(RGX_RT_CLEANUP_DATA *psCleanupData)
1779 PVRSRV_DEVICE_NODE *psDeviceNode = psCleanupData->psDeviceNode;
1781 RGXUnsetFirmwareAddress(psCleanupData->psRenderTargetMemDesc);
1785 When we get RT cleanup in the FW call that instead
1787 /* Flush the the SLC before freeing */
1789 RGXFWIF_KCCB_CMD sFlushInvalCmd;
1790 PVRSRV_ERROR eError;
1792 /* Schedule the SLC flush command ... */
1794 PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Submit SLC flush and invalidate");
1796 sFlushInvalCmd.eCmdType = RGXFWIF_KCCB_CMD_SLCFLUSHINVAL;
1797 sFlushInvalCmd.uCmdData.sSLCFlushInvalData.bInval = IMG_TRUE;
1798 sFlushInvalCmd.uCmdData.sSLCFlushInvalData.bDMContext = IMG_FALSE;
1799 sFlushInvalCmd.uCmdData.sSLCFlushInvalData.eDM = 0;
1800 sFlushInvalCmd.uCmdData.sSLCFlushInvalData.psContext.ui32Addr = 0;
1802 eError = RGXSendCommandWithPowLock(psDeviceNode->pvDevice,
1805 sizeof(sFlushInvalCmd),
1806 PDUMP_FLAGS_CONTINUOUS);
1807 if (eError != PVRSRV_OK)
1809 PVR_DPF((PVR_DBG_ERROR,"RGXDestroyRenderTarget: Failed to schedule SLC flush command with error (%u)", eError));
1813 /* Wait for the SLC flush to complete */
1814 eError = RGXWaitForFWOp(psDeviceNode->pvDevice, RGXFWIF_DM_GP, psDeviceNode->psSyncPrim, PDUMP_FLAGS_CONTINUOUS);
1815 if (eError != PVRSRV_OK)
1817 PVR_DPF((PVR_DBG_ERROR,"RGXDestroyRenderTarget: SLC flush and invalidate aborted with error (%u)", eError));
1822 DevmemFwFree(psDeviceNode->pvDevice, psCleanupData->psRenderTargetMemDesc);
1823 OSFreeMem(psCleanupData);
1831 PVRSRV_ERROR RGXCreateZSBufferKM(CONNECTION_DATA * psConnection,
1832 PVRSRV_DEVICE_NODE *psDeviceNode,
1833 DEVMEMINT_RESERVATION *psReservation,
1835 PVRSRV_MEMALLOCFLAGS_T uiMapFlags,
1836 RGX_ZSBUFFER_DATA **ppsZSBuffer,
1837 IMG_UINT32 *pui32ZSBufferFWDevVAddr)
1839 PVRSRV_ERROR eError;
1840 PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
1841 RGXFWIF_FWZSBUFFER *psFWZSBuffer;
1842 RGX_ZSBUFFER_DATA *psZSBuffer;
1843 DEVMEM_MEMDESC *psFWZSBufferMemDesc;
1844 IMG_BOOL bOnDemand = PVRSRV_CHECK_ON_DEMAND(uiMapFlags) ? IMG_TRUE : IMG_FALSE;
1846 /* Allocate host data structure */
1847 psZSBuffer = OSAllocZMem(sizeof(*psZSBuffer));
1848 if (psZSBuffer == NULL)
1850 PVR_DPF((PVR_DBG_ERROR,"RGXCreateZSBufferKM: Failed to allocate cleanup data structure for ZS-Buffer"));
1851 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1852 goto ErrorAllocCleanup;
1855 eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext,
1856 &psZSBuffer->psCleanupSync,
1857 "ta3d zs buffer cleanup");
1858 if (eError != PVRSRV_OK)
1860 PVR_DPF((PVR_DBG_ERROR,"RGXCreateZSBufferKM: Failed to allocate cleanup sync (0x%x)",
1862 goto ErrorSyncAlloc;
1865 /* Populate Host data */
1866 psZSBuffer->psDevInfo = psDevInfo;
1867 psZSBuffer->psReservation = psReservation;
1868 psZSBuffer->psPMR = psPMR;
1869 psZSBuffer->uiMapFlags = uiMapFlags;
1870 psZSBuffer->ui32RefCount = 0;
1871 psZSBuffer->bOnDemand = bOnDemand;
1874 psZSBuffer->ui32ZSBufferID = psDevInfo->ui32ZSBufferCurrID++;
1875 psZSBuffer->psMapping = NULL;
1877 OSLockAcquire(psDevInfo->hLockZSBuffer);
1878 dllist_add_to_tail(&psDevInfo->sZSBufferHead, &psZSBuffer->sNode);
1879 OSLockRelease(psDevInfo->hLockZSBuffer);
1882 /* Allocate firmware memory for ZS-Buffer. */
1883 PDUMPCOMMENT("Allocate firmware ZS-Buffer data structure");
1884 eError = DevmemFwAllocate(psDevInfo,
1885 sizeof(*psFWZSBuffer),
1886 PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
1887 PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
1888 PVRSRV_MEMALLOCFLAG_GPU_READABLE |
1889 PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
1890 PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
1891 PVRSRV_MEMALLOCFLAG_CPU_READABLE |
1892 PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
1893 PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE |
1894 PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE,
1896 &psFWZSBufferMemDesc);
1897 if (eError != PVRSRV_OK)
1899 PVR_DPF((PVR_DBG_ERROR,"RGXCreateZSBufferKM: Failed to allocate firmware ZS-Buffer (%u)", eError));
1900 goto ErrorAllocFWZSBuffer;
1902 psZSBuffer->psZSBufferMemDesc = psFWZSBufferMemDesc;
1904 /* Temporarily map the firmware render context to the kernel. */
1905 eError = DevmemAcquireCpuVirtAddr(psFWZSBufferMemDesc,
1906 (void **)&psFWZSBuffer);
1907 if (eError != PVRSRV_OK)
1909 PVR_DPF((PVR_DBG_ERROR,"RGXCreateZSBufferKM: Failed to map firmware ZS-Buffer (%u)", eError));
1910 goto ErrorAcquireFWZSBuffer;
1913 /* Populate FW ZS-Buffer data structure */
1914 psFWZSBuffer->bOnDemand = bOnDemand;
1915 psFWZSBuffer->eState = (bOnDemand) ? RGXFWIF_ZSBUFFER_UNBACKED : RGXFWIF_ZSBUFFER_BACKED;
1916 psFWZSBuffer->ui32ZSBufferID = psZSBuffer->ui32ZSBufferID;
1918 /* Get firmware address of ZS-Buffer. */
1919 RGXSetFirmwareAddress(&psZSBuffer->sZSBufferFWDevVAddr, psFWZSBufferMemDesc, 0, RFW_FWADDR_FLAG_NONE);
1921 /* Dump the ZS-Buffer and the memory content */
1922 PDUMPCOMMENT("Dump firmware ZS-Buffer");
1923 DevmemPDumpLoadMem(psFWZSBufferMemDesc, 0, sizeof(*psFWZSBuffer), PDUMP_FLAGS_CONTINUOUS);
1925 /* Release address acquired above. */
1926 DevmemReleaseCpuVirtAddr(psFWZSBufferMemDesc);
1929 /* define return value */
1930 *ppsZSBuffer = psZSBuffer;
1931 *pui32ZSBufferFWDevVAddr = psZSBuffer->sZSBufferFWDevVAddr.ui32Addr;
1933 PVR_DPF((PVR_DBG_MESSAGE, "ZS-Buffer [%p] created (%s)",
1935 (bOnDemand) ? "On-Demand": "Up-front"));
1937 psZSBuffer->owner=OSGetCurrentClientProcessIDKM();
1941 /* error handling */
1943 ErrorAcquireFWZSBuffer:
1944 DevmemFwFree(psDevInfo, psFWZSBufferMemDesc);
1946 ErrorAllocFWZSBuffer:
1947 SyncPrimFree(psZSBuffer->psCleanupSync);
1950 OSFreeMem(psZSBuffer);
1953 PVR_ASSERT(eError != PVRSRV_OK);
1962 PVRSRV_ERROR RGXDestroyZSBufferKM(RGX_ZSBUFFER_DATA *psZSBuffer)
1964 POS_LOCK hLockZSBuffer;
1965 PVRSRV_ERROR eError;
1967 PVR_ASSERT(psZSBuffer);
1968 hLockZSBuffer = psZSBuffer->psDevInfo->hLockZSBuffer;
1970 /* Request ZS Buffer cleanup */
1971 eError = RGXFWRequestZSBufferCleanUp(psZSBuffer->psDevInfo,
1972 psZSBuffer->sZSBufferFWDevVAddr,
1973 psZSBuffer->psCleanupSync);
1974 if (eError != PVRSRV_ERROR_RETRY)
1976 /* Free the firmware render context. */
1977 RGXUnsetFirmwareAddress(psZSBuffer->psZSBufferMemDesc);
1978 DevmemFwFree(psZSBuffer->psDevInfo, psZSBuffer->psZSBufferMemDesc);
1980 /* Remove Deferred Allocation from list */
1981 if (psZSBuffer->bOnDemand)
1983 OSLockAcquire(hLockZSBuffer);
1984 PVR_ASSERT(dllist_node_is_in_list(&psZSBuffer->sNode));
1985 dllist_remove_node(&psZSBuffer->sNode);
1986 OSLockRelease(hLockZSBuffer);
1989 SyncPrimFree(psZSBuffer->psCleanupSync);
1991 PVR_ASSERT(psZSBuffer->ui32RefCount == 0);
1993 PVR_DPF((PVR_DBG_MESSAGE,"ZS-Buffer [%p] destroyed",psZSBuffer));
1995 /* Free ZS-Buffer host data structure */
1996 OSFreeMem(psZSBuffer);
2004 RGXBackingZSBuffer(RGX_ZSBUFFER_DATA *psZSBuffer)
2006 POS_LOCK hLockZSBuffer;
2007 PVRSRV_ERROR eError;
2011 return PVRSRV_ERROR_INVALID_PARAMS;
2014 if (!psZSBuffer->bOnDemand)
2016 /* Only deferred allocations can be populated */
2017 return PVRSRV_ERROR_INVALID_PARAMS;
2020 PVR_DPF((PVR_DBG_MESSAGE,"ZS Buffer [%p, ID=0x%08x]: Physical backing requested",
2022 psZSBuffer->ui32ZSBufferID));
2023 hLockZSBuffer = psZSBuffer->psDevInfo->hLockZSBuffer;
2025 OSLockAcquire(hLockZSBuffer);
2027 if (psZSBuffer->ui32RefCount == 0)
2029 if (psZSBuffer->bOnDemand)
2031 IMG_HANDLE hDevmemHeap;
2033 PVR_ASSERT(psZSBuffer->psMapping == NULL);
2036 eError = DevmemServerGetHeapHandle(psZSBuffer->psReservation, &hDevmemHeap);
2037 PVR_ASSERT(psZSBuffer->psMapping == NULL);
2039 eError = DevmemIntMapPMR(hDevmemHeap,
2040 psZSBuffer->psReservation,
2042 psZSBuffer->uiMapFlags,
2043 &psZSBuffer->psMapping);
2044 if (eError != PVRSRV_OK)
2046 PVR_DPF((PVR_DBG_ERROR,"Unable populate ZS Buffer [%p, ID=0x%08x] with error %u",
2048 psZSBuffer->ui32ZSBufferID,
2050 OSLockRelease(hLockZSBuffer);
2054 PVR_DPF((PVR_DBG_MESSAGE, "ZS Buffer [%p, ID=0x%08x]: Physical backing acquired",
2056 psZSBuffer->ui32ZSBufferID));
2060 /* Increase refcount*/
2061 psZSBuffer->ui32RefCount++;
2063 OSLockRelease(hLockZSBuffer);
2070 RGXPopulateZSBufferKM(RGX_ZSBUFFER_DATA *psZSBuffer,
2071 RGX_POPULATION **ppsPopulation)
2073 RGX_POPULATION *psPopulation;
2074 PVRSRV_ERROR eError;
2076 psZSBuffer->ui32NumReqByApp++;
2078 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
2079 PVRSRVStatsUpdateZSBufferStats(1,0,psZSBuffer->owner);
2082 /* Do the backing */
2083 eError = RGXBackingZSBuffer(psZSBuffer);
2084 if (eError != PVRSRV_OK)
2086 goto OnErrorBacking;
2089 /* Create the handle to the backing */
2090 psPopulation = OSAllocMem(sizeof(*psPopulation));
2091 if (psPopulation == NULL)
2093 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
2097 psPopulation->psZSBuffer = psZSBuffer;
2100 *ppsPopulation = psPopulation;
2105 RGXUnbackingZSBuffer(psZSBuffer);
2108 PVR_ASSERT(eError != PVRSRV_OK);
2113 RGXUnbackingZSBuffer(RGX_ZSBUFFER_DATA *psZSBuffer)
2115 POS_LOCK hLockZSBuffer;
2116 PVRSRV_ERROR eError;
2120 return PVRSRV_ERROR_INVALID_PARAMS;
2123 PVR_ASSERT(psZSBuffer->ui32RefCount);
2125 PVR_DPF((PVR_DBG_MESSAGE,"ZS Buffer [%p, ID=0x%08x]: Physical backing removal requested",
2127 psZSBuffer->ui32ZSBufferID));
2129 hLockZSBuffer = psZSBuffer->psDevInfo->hLockZSBuffer;
2131 OSLockAcquire(hLockZSBuffer);
2133 if (psZSBuffer->bOnDemand)
2135 if (psZSBuffer->ui32RefCount == 1)
2137 PVR_ASSERT(psZSBuffer->psMapping);
2139 eError = DevmemIntUnmapPMR(psZSBuffer->psMapping);
2140 if (eError != PVRSRV_OK)
2142 PVR_DPF((PVR_DBG_ERROR,"Unable to unpopulate ZS Buffer [%p, ID=0x%08x] with error %u",
2144 psZSBuffer->ui32ZSBufferID,
2146 OSLockRelease(hLockZSBuffer);
2150 PVR_DPF((PVR_DBG_MESSAGE, "ZS Buffer [%p, ID=0x%08x]: Physical backing removed",
2152 psZSBuffer->ui32ZSBufferID));
2156 /* Decrease refcount*/
2157 psZSBuffer->ui32RefCount--;
2159 OSLockRelease(hLockZSBuffer);
2165 RGXUnpopulateZSBufferKM(RGX_POPULATION *psPopulation)
2167 PVRSRV_ERROR eError;
2171 return PVRSRV_ERROR_INVALID_PARAMS;
2174 eError = RGXUnbackingZSBuffer(psPopulation->psZSBuffer);
2175 if (eError != PVRSRV_OK)
2180 OSFreeMem(psPopulation);
2185 static RGX_ZSBUFFER_DATA *FindZSBuffer(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32ZSBufferID)
2187 DLLIST_NODE *psNode, *psNext;
2188 RGX_ZSBUFFER_DATA *psZSBuffer = NULL;
2190 OSLockAcquire(psDevInfo->hLockZSBuffer);
2192 dllist_foreach_node(&psDevInfo->sZSBufferHead, psNode, psNext)
2194 RGX_ZSBUFFER_DATA *psThisZSBuffer = IMG_CONTAINER_OF(psNode, RGX_ZSBUFFER_DATA, sNode);
2196 if (psThisZSBuffer->ui32ZSBufferID == ui32ZSBufferID)
2198 psZSBuffer = psThisZSBuffer;
2203 OSLockRelease(psDevInfo->hLockZSBuffer);
2207 void RGXProcessRequestZSBufferBacking(PVRSRV_RGXDEV_INFO *psDevInfo,
2208 IMG_UINT32 ui32ZSBufferID)
2210 RGX_ZSBUFFER_DATA *psZSBuffer;
2211 RGXFWIF_KCCB_CMD sTACCBCmd;
2212 PVRSRV_ERROR eError;
2214 PVR_ASSERT(psDevInfo);
2216 /* scan all deferred allocations */
2217 psZSBuffer = FindZSBuffer(psDevInfo, ui32ZSBufferID);
2221 IMG_BOOL bBackingDone = IMG_TRUE;
2224 eError = RGXBackingZSBuffer(psZSBuffer);
2225 if (eError != PVRSRV_OK)
2227 PVR_DPF((PVR_DBG_ERROR,"Populating ZS-Buffer failed with error %u (ID = 0x%08x)", eError, ui32ZSBufferID));
2228 bBackingDone = IMG_FALSE;
2231 /* send confirmation */
2232 sTACCBCmd.eCmdType = RGXFWIF_KCCB_CMD_ZSBUFFER_BACKING_UPDATE;
2233 sTACCBCmd.uCmdData.sZSBufferBackingData.sZSBufferFWDevVAddr.ui32Addr = psZSBuffer->sZSBufferFWDevVAddr.ui32Addr;
2234 sTACCBCmd.uCmdData.sZSBufferBackingData.bDone = bBackingDone;
2236 LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
2238 eError = RGXScheduleCommand(psDevInfo,
2244 if (eError != PVRSRV_ERROR_RETRY)
2248 OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
2249 } END_LOOP_UNTIL_TIMEOUT();
2251 /* Kernel CCB should never fill up, as the FW is processing them right away */
2252 PVR_ASSERT(eError == PVRSRV_OK);
2254 psZSBuffer->ui32NumReqByFW++;
2256 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
2257 PVRSRVStatsUpdateZSBufferStats(0,1,psZSBuffer->owner);
2263 PVR_DPF((PVR_DBG_ERROR,"ZS Buffer Lookup for ZS Buffer ID 0x%08x failed (Populate)", ui32ZSBufferID));
2267 void RGXProcessRequestZSBufferUnbacking(PVRSRV_RGXDEV_INFO *psDevInfo,
2268 IMG_UINT32 ui32ZSBufferID)
2270 RGX_ZSBUFFER_DATA *psZSBuffer;
2271 RGXFWIF_KCCB_CMD sTACCBCmd;
2272 PVRSRV_ERROR eError;
2274 PVR_ASSERT(psDevInfo);
2276 /* scan all deferred allocations */
2277 psZSBuffer = FindZSBuffer(psDevInfo, ui32ZSBufferID);
2281 /* Unpopulate ZLS */
2282 eError = RGXUnbackingZSBuffer(psZSBuffer);
2283 if (eError != PVRSRV_OK)
2285 PVR_DPF((PVR_DBG_ERROR,"UnPopulating ZS-Buffer failed failed with error %u (ID = 0x%08x)", eError, ui32ZSBufferID));
2286 PVR_ASSERT(IMG_FALSE);
2289 /* send confirmation */
2290 sTACCBCmd.eCmdType = RGXFWIF_KCCB_CMD_ZSBUFFER_UNBACKING_UPDATE;
2291 sTACCBCmd.uCmdData.sZSBufferBackingData.sZSBufferFWDevVAddr.ui32Addr = psZSBuffer->sZSBufferFWDevVAddr.ui32Addr;
2292 sTACCBCmd.uCmdData.sZSBufferBackingData.bDone = IMG_TRUE;
2294 LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
2296 eError = RGXScheduleCommand(psDevInfo,
2302 if (eError != PVRSRV_ERROR_RETRY)
2306 OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
2307 } END_LOOP_UNTIL_TIMEOUT();
2309 /* Kernel CCB should never fill up, as the FW is processing them right away */
2310 PVR_ASSERT(eError == PVRSRV_OK);
2315 PVR_DPF((PVR_DBG_ERROR,"ZS Buffer Lookup for ZS Buffer ID 0x%08x failed (UnPopulate)", ui32ZSBufferID));
2320 PVRSRV_ERROR _CreateTAContext(CONNECTION_DATA *psConnection,
2321 PVRSRV_DEVICE_NODE *psDeviceNode,
2322 DEVMEM_MEMDESC *psAllocatedMemDesc,
2323 IMG_UINT32 ui32AllocatedOffset,
2324 DEVMEM_MEMDESC *psFWMemContextMemDesc,
2325 IMG_DEV_VIRTADDR sVDMCallStackAddr,
2326 IMG_UINT32 ui32Priority,
2327 RGX_COMMON_CONTEXT_INFO *psInfo,
2328 RGX_SERVER_RC_TA_DATA *psTAData)
2330 PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
2331 RGXFWIF_TACTX_STATE *psContextState;
2332 PVRSRV_ERROR eError;
2334 Allocate device memory for the firmware GPU context suspend state.
2335 Note: the FW reads/writes the state to memory by accessing the GPU register interface.
2337 PDUMPCOMMENT("Allocate RGX firmware TA context suspend state");
2339 eError = DevmemFwAllocate(psDevInfo,
2340 sizeof(RGXFWIF_TACTX_STATE),
2341 RGX_FWCOMCTX_ALLOCFLAGS,
2343 &psTAData->psContextStateMemDesc);
2344 if (eError != PVRSRV_OK)
2346 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRenderContextKM: Failed to allocate firmware GPU context suspend state (%u)",
2348 goto fail_tacontextsuspendalloc;
2351 eError = DevmemAcquireCpuVirtAddr(psTAData->psContextStateMemDesc,
2352 (void **)&psContextState);
2353 if (eError != PVRSRV_OK)
2355 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRenderContextKM: Failed to map firmware render context state (%u)",
2357 goto fail_suspendcpuvirtacquire;
2359 psContextState->uTAReg_VDM_CALL_STACK_POINTER_Init = sVDMCallStackAddr.uiAddr;
2360 DevmemReleaseCpuVirtAddr(psTAData->psContextStateMemDesc);
2362 eError = FWCommonContextAllocate(psConnection,
2367 ui32AllocatedOffset,
2368 psFWMemContextMemDesc,
2369 psTAData->psContextStateMemDesc,
2370 RGX_TA_CCB_SIZE_LOG2,
2373 &psTAData->psServerCommonContext);
2374 if (eError != PVRSRV_OK)
2376 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRenderContextKM: Failed to init TA fw common context (%u)",
2378 goto fail_tacommoncontext;
2382 * Dump the FW 3D context suspend state buffer
2384 PDUMPCOMMENT("Dump the TA context suspend state buffer");
2385 DevmemPDumpLoadMem(psTAData->psContextStateMemDesc,
2387 sizeof(RGXFWIF_TACTX_STATE),
2388 PDUMP_FLAGS_CONTINUOUS);
2390 psTAData->ui32Priority = ui32Priority;
2393 fail_tacommoncontext:
2394 fail_suspendcpuvirtacquire:
2395 DevmemFwFree(psDevInfo, psTAData->psContextStateMemDesc);
2396 fail_tacontextsuspendalloc:
2397 PVR_ASSERT(eError != PVRSRV_OK);
2403 PVRSRV_ERROR _Create3DContext(CONNECTION_DATA *psConnection,
2404 PVRSRV_DEVICE_NODE *psDeviceNode,
2405 DEVMEM_MEMDESC *psAllocatedMemDesc,
2406 IMG_UINT32 ui32AllocatedOffset,
2407 DEVMEM_MEMDESC *psFWMemContextMemDesc,
2408 IMG_UINT32 ui32Priority,
2409 RGX_COMMON_CONTEXT_INFO *psInfo,
2410 RGX_SERVER_RC_3D_DATA *ps3DData)
2412 PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
2413 PVRSRV_ERROR eError;
2416 Allocate device memory for the firmware GPU context suspend state.
2417 Note: the FW reads/writes the state to memory by accessing the GPU register interface.
2419 PDUMPCOMMENT("Allocate RGX firmware 3D context suspend state");
2421 eError = DevmemFwAllocate(psDevInfo,
2422 sizeof(RGXFWIF_3DCTX_STATE),
2423 RGX_FWCOMCTX_ALLOCFLAGS,
2425 &ps3DData->psContextStateMemDesc);
2426 if (eError != PVRSRV_OK)
2428 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRenderContextKM: Failed to allocate firmware GPU context suspend state (%u)",
2430 goto fail_3dcontextsuspendalloc;
2433 eError = FWCommonContextAllocate(psConnection,
2438 ui32AllocatedOffset,
2439 psFWMemContextMemDesc,
2440 ps3DData->psContextStateMemDesc,
2441 RGX_3D_CCB_SIZE_LOG2,
2444 &ps3DData->psServerCommonContext);
2445 if (eError != PVRSRV_OK)
2447 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRenderContextKM: Failed to init 3D fw common context (%u)",
2449 goto fail_3dcommoncontext;
2453 * Dump the FW 3D context suspend state buffer
2455 PDUMPCOMMENT("Dump the 3D context suspend state buffer");
2456 DevmemPDumpLoadMem(ps3DData->psContextStateMemDesc,
2458 sizeof(RGXFWIF_3DCTX_STATE),
2459 PDUMP_FLAGS_CONTINUOUS);
2461 ps3DData->ui32Priority = ui32Priority;
2464 fail_3dcommoncontext:
2465 DevmemFwFree(psDevInfo, ps3DData->psContextStateMemDesc);
2466 fail_3dcontextsuspendalloc:
2467 PVR_ASSERT(eError != PVRSRV_OK);
2474 * PVRSRVRGXCreateRenderContextKM
2477 PVRSRV_ERROR PVRSRVRGXCreateRenderContextKM(CONNECTION_DATA *psConnection,
2478 PVRSRV_DEVICE_NODE *psDeviceNode,
2479 IMG_UINT32 ui32Priority,
2480 IMG_DEV_VIRTADDR sMCUFenceAddr,
2481 IMG_DEV_VIRTADDR sVDMCallStackAddr,
2482 IMG_UINT32 ui32FrameworkRegisterSize,
2483 IMG_PBYTE pabyFrameworkRegisters,
2484 IMG_HANDLE hMemCtxPrivData,
2485 RGX_SERVER_RENDER_CONTEXT **ppsRenderContext)
2487 PVRSRV_ERROR eError;
2488 PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
2489 RGX_SERVER_RENDER_CONTEXT *psRenderContext;
2490 DEVMEM_MEMDESC *psFWMemContextMemDesc = RGXGetFWMemDescFromMemoryContextHandle(hMemCtxPrivData);
2491 RGX_COMMON_CONTEXT_INFO sInfo;
2493 /* Prepare cleanup structure */
2494 *ppsRenderContext = NULL;
2495 psRenderContext = OSAllocZMem(sizeof(*psRenderContext));
2496 if (psRenderContext == NULL)
2498 return PVRSRV_ERROR_OUT_OF_MEMORY;
2501 psRenderContext->psDeviceNode = psDeviceNode;
2504 Create the FW render context, this has the TA and 3D FW common
2505 contexts embedded within it
2507 eError = DevmemFwAllocate(psDevInfo,
2508 sizeof(RGXFWIF_FWRENDERCONTEXT),
2509 RGX_FWCOMCTX_ALLOCFLAGS,
2511 &psRenderContext->psFWRenderContextMemDesc);
2512 if (eError != PVRSRV_OK)
2514 goto fail_fwrendercontext;
2517 #if defined(SUPPORT_WORKLOAD_ESTIMATION)
2518 WorkEstRCInit(&(psRenderContext->sWorkEstData));
2521 /* Allocate cleanup sync */
2522 eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext,
2523 &psRenderContext->psCleanupSync,
2524 "ta3d render context cleanup");
2525 if (eError != PVRSRV_OK)
2527 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRenderContextKM: Failed to allocate cleanup sync (0x%x)",
2529 goto fail_syncalloc;
2533 * Create the FW framework buffer
2535 eError = PVRSRVRGXFrameworkCreateKM(psDeviceNode,
2536 &psRenderContext->psFWFrameworkMemDesc,
2537 ui32FrameworkRegisterSize);
2538 if (eError != PVRSRV_OK)
2540 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRenderContextKM: Failed to allocate firmware GPU framework state (%u)",
2542 goto fail_frameworkcreate;
2545 /* Copy the Framework client data into the framework buffer */
2546 eError = PVRSRVRGXFrameworkCopyCommand(psRenderContext->psFWFrameworkMemDesc,
2547 pabyFrameworkRegisters,
2548 ui32FrameworkRegisterSize);
2549 if (eError != PVRSRV_OK)
2551 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRenderContextKM: Failed to populate the framework buffer (%u)",
2553 goto fail_frameworkcopy;
2556 sInfo.psFWFrameworkMemDesc = psRenderContext->psFWFrameworkMemDesc;
2557 sInfo.psMCUFenceAddr = &sMCUFenceAddr;
2559 eError = _CreateTAContext(psConnection,
2561 psRenderContext->psFWRenderContextMemDesc,
2562 offsetof(RGXFWIF_FWRENDERCONTEXT, sTAContext),
2563 psFWMemContextMemDesc,
2567 &psRenderContext->sTAData);
2568 if (eError != PVRSRV_OK)
2570 goto fail_tacontext;
2573 eError = _Create3DContext(psConnection,
2575 psRenderContext->psFWRenderContextMemDesc,
2576 offsetof(RGXFWIF_FWRENDERCONTEXT, s3DContext),
2577 psFWMemContextMemDesc,
2580 &psRenderContext->s3DData);
2581 if (eError != PVRSRV_OK)
2583 goto fail_3dcontext;
2586 SyncAddrListInit(&psRenderContext->sSyncAddrListTAFence);
2587 SyncAddrListInit(&psRenderContext->sSyncAddrListTAUpdate);
2588 SyncAddrListInit(&psRenderContext->sSyncAddrList3DFence);
2589 SyncAddrListInit(&psRenderContext->sSyncAddrList3DUpdate);
2592 PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
2594 OSWRLockAcquireWrite(psDevInfo->hRenderCtxListLock);
2595 dllist_add_to_tail(&(psDevInfo->sRenderCtxtListHead), &(psRenderContext->sListNode));
2596 OSWRLockReleaseWrite(psDevInfo->hRenderCtxListLock);
2599 *ppsRenderContext= psRenderContext;
2603 _DestroyTAContext(&psRenderContext->sTAData,
2605 psRenderContext->psCleanupSync);
2608 DevmemFwFree(psDevInfo, psRenderContext->psFWFrameworkMemDesc);
2609 fail_frameworkcreate:
2610 SyncPrimFree(psRenderContext->psCleanupSync);
2612 DevmemFwFree(psDevInfo, psRenderContext->psFWRenderContextMemDesc);
2613 fail_fwrendercontext:
2614 OSFreeMem(psRenderContext);
2615 PVR_ASSERT(eError != PVRSRV_OK);
2621 * PVRSRVRGXDestroyRenderContextKM
2624 PVRSRV_ERROR PVRSRVRGXDestroyRenderContextKM(RGX_SERVER_RENDER_CONTEXT *psRenderContext)
2626 PVRSRV_ERROR eError;
2627 PVRSRV_RGXDEV_INFO *psDevInfo = psRenderContext->psDeviceNode->pvDevice;
2628 RGXFWIF_FWRENDERCONTEXT *psFWRenderContext;
2629 #if defined(SUPPORT_WORKLOAD_ESTIMATION)
2630 IMG_UINT32 ui32WorkEstCCBSubmitted;
2633 /* remove node from list before calling destroy - as destroy, if successful
2634 * will invalidate the node
2635 * must be re-added if destroy fails
2637 OSWRLockAcquireWrite(psDevInfo->hRenderCtxListLock);
2638 dllist_remove_node(&(psRenderContext->sListNode));
2639 OSWRLockReleaseWrite(psDevInfo->hRenderCtxListLock);
2641 /* Cleanup the TA if we haven't already */
2642 if ((psRenderContext->ui32CleanupStatus & RC_CLEANUP_TA_COMPLETE) == 0)
2644 eError = _DestroyTAContext(&psRenderContext->sTAData,
2645 psRenderContext->psDeviceNode,
2646 psRenderContext->psCleanupSync);
2647 if (eError == PVRSRV_OK)
2649 psRenderContext->ui32CleanupStatus |= RC_CLEANUP_TA_COMPLETE;
2657 /* Cleanup the 3D if we haven't already */
2658 if ((psRenderContext->ui32CleanupStatus & RC_CLEANUP_3D_COMPLETE) == 0)
2660 eError = _Destroy3DContext(&psRenderContext->s3DData,
2661 psRenderContext->psDeviceNode,
2662 psRenderContext->psCleanupSync);
2663 if (eError == PVRSRV_OK)
2665 psRenderContext->ui32CleanupStatus |= RC_CLEANUP_3D_COMPLETE;
2673 #if defined(SUPPORT_WORKLOAD_ESTIMATION)
2674 eError = DevmemAcquireCpuVirtAddr(psRenderContext->psFWRenderContextMemDesc,
2675 (void **)&psFWRenderContext);
2676 if(eError != PVRSRV_OK)
2678 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXDestroyRenderContextKM: Failed to map firmware render context (%u)",
2683 ui32WorkEstCCBSubmitted = psFWRenderContext->ui32WorkEstCCBSubmitted;
2685 DevmemReleaseCpuVirtAddr(psRenderContext->psFWRenderContextMemDesc);
2687 /* Check if all of the workload estimation CCB commands for this workload
2690 if(ui32WorkEstCCBSubmitted != psRenderContext->sWorkEstData.ui32WorkEstCCBReceived)
2692 eError = PVRSRV_ERROR_RETRY;
2698 Only if both TA and 3D contexts have been cleaned up can we
2699 free the shared resources
2701 if (psRenderContext->ui32CleanupStatus == (RC_CLEANUP_3D_COMPLETE | RC_CLEANUP_TA_COMPLETE))
2704 /* Update SPM statistics */
2705 eError = DevmemAcquireCpuVirtAddr(psRenderContext->psFWRenderContextMemDesc,
2706 (void **)&psFWRenderContext);
2707 if (eError == PVRSRV_OK)
2709 DevmemReleaseCpuVirtAddr(psRenderContext->psFWRenderContextMemDesc);
2713 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXDestroyRenderContextKM: Failed to map firmware render context (%u)",
2717 /* Free the framework buffer */
2718 DevmemFwFree(psDevInfo, psRenderContext->psFWFrameworkMemDesc);
2720 /* Free the firmware render context */
2721 DevmemFwFree(psDevInfo, psRenderContext->psFWRenderContextMemDesc);
2723 /* Free the cleanup sync */
2724 SyncPrimFree(psRenderContext->psCleanupSync);
2726 SyncAddrListDeinit(&psRenderContext->sSyncAddrListTAFence);
2727 SyncAddrListDeinit(&psRenderContext->sSyncAddrListTAUpdate);
2728 SyncAddrListDeinit(&psRenderContext->sSyncAddrList3DFence);
2729 SyncAddrListDeinit(&psRenderContext->sSyncAddrList3DUpdate);
2731 #if defined(SUPPORT_WORKLOAD_ESTIMATION)
2732 WorkEstRCDeInit(&(psRenderContext->sWorkEstData),
2736 OSFreeMem(psRenderContext);
2742 OSWRLockAcquireWrite(psDevInfo->hRenderCtxListLock);
2743 dllist_add_to_tail(&(psDevInfo->sRenderCtxtListHead), &(psRenderContext->sListNode));
2744 OSWRLockReleaseWrite(psDevInfo->hRenderCtxListLock);
2749 /* TODO !!! this was local on the stack, and we managed to blow the stack for the kernel.
2750 * THIS - 46 argument function needs to be sorted out.
2752 /* 1 command for the TA */
2753 static RGX_CCB_CMD_HELPER_DATA asTACmdHelperData[1];
2754 /* Up to 3 commands for the 3D (partial render fence, partial reader, and render) */
2755 static RGX_CCB_CMD_HELPER_DATA as3DCmdHelperData[3];
2758 * PVRSRVRGXKickTA3DKM
2761 PVRSRV_ERROR PVRSRVRGXKickTA3DKM(RGX_SERVER_RENDER_CONTEXT *psRenderContext,
2762 IMG_UINT32 ui32ClientCacheOpSeqNum,
2763 IMG_UINT32 ui32ClientTAFenceCount,
2764 SYNC_PRIMITIVE_BLOCK **apsClientTAFenceSyncPrimBlock,
2765 IMG_UINT32 *paui32ClientTAFenceSyncOffset,
2766 IMG_UINT32 *paui32ClientTAFenceValue,
2767 IMG_UINT32 ui32ClientTAUpdateCount,
2768 SYNC_PRIMITIVE_BLOCK **apsClientTAUpdateSyncPrimBlock,
2769 IMG_UINT32 *paui32ClientTAUpdateSyncOffset,
2770 IMG_UINT32 *paui32ClientTAUpdateValue,
2771 IMG_UINT32 ui32ServerTASyncPrims,
2772 IMG_UINT32 *paui32ServerTASyncFlags,
2773 SERVER_SYNC_PRIMITIVE **pasServerTASyncs,
2774 IMG_UINT32 ui32Client3DFenceCount,
2775 SYNC_PRIMITIVE_BLOCK **apsClient3DFenceSyncPrimBlock,
2776 IMG_UINT32 *paui32Client3DFenceSyncOffset,
2777 IMG_UINT32 *paui32Client3DFenceValue,
2778 IMG_UINT32 ui32Client3DUpdateCount,
2779 SYNC_PRIMITIVE_BLOCK **apsClient3DUpdateSyncPrimBlock,
2780 IMG_UINT32 *paui32Client3DUpdateSyncOffset,
2781 IMG_UINT32 *paui32Client3DUpdateValue,
2782 IMG_UINT32 ui32Server3DSyncPrims,
2783 IMG_UINT32 *paui32Server3DSyncFlags,
2784 SERVER_SYNC_PRIMITIVE **pasServer3DSyncs,
2785 SYNC_PRIMITIVE_BLOCK *psPRFenceSyncPrimBlock,
2786 IMG_UINT32 ui32PRFenceSyncOffset,
2787 IMG_UINT32 ui32PRFenceValue,
2788 IMG_INT32 i32CheckFenceFD,
2789 IMG_INT32 i32UpdateTimelineFD,
2790 IMG_INT32 *pi32UpdateFenceFD,
2791 IMG_CHAR szFenceName[32],
2792 IMG_UINT32 ui32TACmdSize,
2793 IMG_PBYTE pui8TADMCmd,
2794 IMG_UINT32 ui323DPRCmdSize,
2795 IMG_PBYTE pui83DPRDMCmd,
2796 IMG_UINT32 ui323DCmdSize,
2797 IMG_PBYTE pui83DDMCmd,
2798 IMG_UINT32 ui32ExtJobRef,
2799 IMG_BOOL bLastTAInScene,
2804 IMG_UINT32 ui32PDumpFlags,
2805 RGX_RTDATA_CLEANUP_DATA *psRTDataCleanup,
2806 RGX_ZSBUFFER_DATA *psZBuffer,
2807 RGX_ZSBUFFER_DATA *psSBuffer,
2808 IMG_BOOL bCommitRefCountsTA,
2809 IMG_BOOL bCommitRefCounts3D,
2810 IMG_BOOL *pbCommittedRefCountsTA,
2811 IMG_BOOL *pbCommittedRefCounts3D,
2812 IMG_UINT32 ui32SyncPMRCount,
2813 IMG_UINT32 *paui32SyncPMRFlags,
2815 IMG_UINT32 ui32RenderTargetSize,
2816 IMG_UINT32 ui32NumberOfDrawCalls,
2817 IMG_UINT32 ui32NumberOfIndices,
2818 IMG_UINT32 ui32NumberOfMRTs,
2819 IMG_UINT64 ui64DeadlineInus)
2822 IMG_UINT32 ui32TACmdCount=0;
2823 IMG_UINT32 ui323DCmdCount=0;
2824 IMG_UINT32 ui32TACmdOffset=0;
2825 IMG_UINT32 ui323DCmdOffset=0;
2828 PVRSRV_ERROR eError = PVRSRV_OK;
2829 PVRSRV_ERROR eError2;
2830 IMG_INT32 i32UpdateFenceFD = -1;
2831 IMG_UINT32 ui32JobId;
2833 IMG_UINT32 ui32ClientPRUpdateCount = 0;
2834 PRGXFWIF_UFO_ADDR *pauiClientPRUpdateUFOAddress = NULL;
2835 IMG_UINT32 *paui32ClientPRUpdateValue = NULL;
2837 PRGXFWIF_TIMESTAMP_ADDR pPreAddr;
2838 PRGXFWIF_TIMESTAMP_ADDR pPostAddr;
2839 PRGXFWIF_UFO_ADDR pRMWUFOAddr;
2841 PRGXFWIF_UFO_ADDR *pauiClientTAFenceUFOAddress;
2842 PRGXFWIF_UFO_ADDR *pauiClientTAUpdateUFOAddress;
2843 PRGXFWIF_UFO_ADDR *pauiClient3DFenceUFOAddress;
2844 PRGXFWIF_UFO_ADDR *pauiClient3DUpdateUFOAddress;
2845 PRGXFWIF_UFO_ADDR uiPRFenceUFOAddress;
2847 #if defined(SUPPORT_WORKLOAD_ESTIMATION)
2848 RGXFWIF_WORKEST_KICK_DATA sWorkloadKickDataTA;
2849 RGXFWIF_WORKEST_KICK_DATA sWorkloadKickData3D;
2850 IMG_UINT32 ui32TACommandOffset = 0;
2851 IMG_UINT32 ui323DCommandOffset = 0;
2852 IMG_UINT32 ui32TACmdHeaderOffset = 0;
2853 IMG_UINT32 ui323DCmdHeaderOffset = 0;
2854 IMG_UINT32 ui323DFullRenderCommandOffset = 0;
2855 IMG_UINT32 ui32TACmdOffsetWrapCheck = 0;
2856 IMG_UINT32 ui323DCmdOffsetWrapCheck = 0;
2859 #if defined(SUPPORT_BUFFER_SYNC)
2860 struct pvr_buffer_sync_append_data *psAppendData = NULL;
2863 #if defined(SUPPORT_NATIVE_FENCE_SYNC)
2864 /* Android fd sync update info */
2865 struct pvr_sync_append_data *psFDData = NULL;
2866 if (i32UpdateTimelineFD >= 0 && !pi32UpdateFenceFD)
2868 return PVRSRV_ERROR_INVALID_PARAMS;
2871 if (i32UpdateTimelineFD >= 0)
2873 PVR_DPF((PVR_DBG_WARNING, "%s: Providing native sync timeline (%d) in non native sync enabled driver",
2874 __func__, i32UpdateTimelineFD));
2876 if (i32CheckFenceFD >= 0)
2878 PVR_DPF((PVR_DBG_WARNING, "%s: Providing native check sync (%d) in non native sync enabled driver",
2879 __func__, i32CheckFenceFD));
2883 #if defined(SUPPORT_WORKLOAD_ESTIMATION)
2884 sWorkloadKickDataTA.ui64ReturnDataIndex = 0;
2885 sWorkloadKickData3D.ui64ReturnDataIndex = 0;
2888 ui32JobId = OSAtomicIncrement(&psRenderContext->hJobId);
2890 /* Ensure the string is null-terminated (Required for safety) */
2891 szFenceName[31] = '\0';
2892 *pbCommittedRefCountsTA = IMG_FALSE;
2893 *pbCommittedRefCounts3D = IMG_FALSE;
2895 eError = SyncAddrListPopulate(&psRenderContext->sSyncAddrListTAFence,
2896 ui32ClientTAFenceCount,
2897 apsClientTAFenceSyncPrimBlock,
2898 paui32ClientTAFenceSyncOffset);
2899 if(eError != PVRSRV_OK)
2901 goto err_populate_sync_addr_list;
2904 pauiClientTAFenceUFOAddress = psRenderContext->sSyncAddrListTAFence.pasFWAddrs;
2906 eError = SyncAddrListPopulate(&psRenderContext->sSyncAddrListTAUpdate,
2907 ui32ClientTAUpdateCount,
2908 apsClientTAUpdateSyncPrimBlock,
2909 paui32ClientTAUpdateSyncOffset);
2910 if(eError != PVRSRV_OK)
2912 goto err_populate_sync_addr_list;
2915 pauiClientTAUpdateUFOAddress = psRenderContext->sSyncAddrListTAUpdate.pasFWAddrs;
2917 eError = SyncAddrListPopulate(&psRenderContext->sSyncAddrList3DFence,
2918 ui32Client3DFenceCount,
2919 apsClient3DFenceSyncPrimBlock,
2920 paui32Client3DFenceSyncOffset);
2921 if(eError != PVRSRV_OK)
2923 goto err_populate_sync_addr_list;
2926 pauiClient3DFenceUFOAddress = psRenderContext->sSyncAddrList3DFence.pasFWAddrs;
2928 eError = SyncAddrListPopulate(&psRenderContext->sSyncAddrList3DUpdate,
2929 ui32Client3DUpdateCount,
2930 apsClient3DUpdateSyncPrimBlock,
2931 paui32Client3DUpdateSyncOffset);
2932 if(eError != PVRSRV_OK)
2934 goto err_populate_sync_addr_list;
2937 pauiClient3DUpdateUFOAddress = psRenderContext->sSyncAddrList3DUpdate.pasFWAddrs;
2939 eError = SyncPrimitiveBlockToFWAddr(psPRFenceSyncPrimBlock,
2940 ui32PRFenceSyncOffset,
2941 &uiPRFenceUFOAddress);
2943 if(eError != PVRSRV_OK)
2945 goto err_pr_fence_address;
2950 /* Sanity check the server fences */
2951 for (i=0;i<ui32ServerTASyncPrims;i++)
2953 if (!(paui32ServerTASyncFlags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK))
2955 PVR_DPF((PVR_DBG_ERROR, "%s: Server fence (on TA) must fence", __FUNCTION__));
2956 return PVRSRV_ERROR_INVALID_SYNC_PRIM_OP;
2960 for (i=0;i<ui32Server3DSyncPrims;i++)
2962 if (!(paui32Server3DSyncFlags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK))
2964 PVR_DPF((PVR_DBG_ERROR, "%s: Server fence (on 3D) must fence", __FUNCTION__));
2965 return PVRSRV_ERROR_INVALID_SYNC_PRIM_OP;
2969 RGX_GetTimestampCmdHelper((PVRSRV_RGXDEV_INFO*) psRenderContext->psDeviceNode->pvDevice,
2975 Sanity check we have a PR kick if there are client or server fences
2977 if (!bKickPR && ((ui32Client3DFenceCount != 0) || (ui32Server3DSyncPrims != 0)))
2979 PVR_DPF((PVR_DBG_ERROR, "%s: 3D fence (client or server) passed without a PR kick", __FUNCTION__));
2980 return PVRSRV_ERROR_INVALID_PARAMS;
2983 if (ui32SyncPMRCount)
2985 #if defined(SUPPORT_BUFFER_SYNC)
2986 PVRSRV_DEVICE_NODE *psDeviceNode = psRenderContext->psDeviceNode;
2987 IMG_UINT32 ui32ClientIntUpdateCount = 0;
2988 PRGXFWIF_UFO_ADDR *pauiClientIntUpdateUFOAddress = NULL;
2989 IMG_UINT32 *paui32ClientIntUpdateValue = NULL;
2994 PVR_DPF((PVR_DBG_ERROR, "%s: Buffer sync only supported for kicks including a TA",
2996 return PVRSRV_ERROR_INVALID_PARAMS;
3001 PVR_DPF((PVR_DBG_ERROR, "%s: Buffer sync only supported for kicks including a PR",
3003 return PVRSRV_ERROR_INVALID_PARAMS;
3008 ui32ClientIntUpdateCount = ui32Client3DUpdateCount;
3009 pauiClientIntUpdateUFOAddress = pauiClient3DUpdateUFOAddress;
3010 paui32ClientIntUpdateValue = paui32Client3DUpdateValue;
3014 ui32ClientIntUpdateCount = ui32ClientPRUpdateCount;
3015 pauiClientIntUpdateUFOAddress = pauiClientPRUpdateUFOAddress;
3016 paui32ClientIntUpdateValue = paui32ClientPRUpdateValue;
3019 err = pvr_buffer_sync_append_start(psDeviceNode->psBufferSyncContext,
3023 ui32ClientTAFenceCount,
3024 pauiClientTAFenceUFOAddress,
3025 paui32ClientTAFenceValue,
3026 ui32ClientIntUpdateCount,
3027 pauiClientIntUpdateUFOAddress,
3028 paui32ClientIntUpdateValue,
3032 eError = (err == -ENOMEM) ? PVRSRV_ERROR_OUT_OF_MEMORY : PVRSRV_ERROR_INVALID_PARAMS;
3033 goto fail_sync_append;
3036 pvr_buffer_sync_append_checks_get(psAppendData,
3037 &ui32ClientTAFenceCount,
3038 &pauiClientTAFenceUFOAddress,
3039 &paui32ClientTAFenceValue);
3043 pvr_buffer_sync_append_updates_get(psAppendData,
3044 &ui32Client3DUpdateCount,
3045 &pauiClient3DUpdateUFOAddress,
3046 &paui32Client3DUpdateValue);
3050 pvr_buffer_sync_append_updates_get(psAppendData,
3051 &ui32ClientPRUpdateCount,
3052 &pauiClientPRUpdateUFOAddress,
3053 &paui32ClientPRUpdateValue);
3056 PVR_DPF((PVR_DBG_ERROR, "%s: Buffer sync not supported but got %u buffers", __FUNCTION__, ui32SyncPMRCount));
3057 return PVRSRV_ERROR_INVALID_PARAMS;
3058 #endif /* defined(SUPPORT_BUFFER_SYNC) */
3061 #if defined(SUPPORT_NATIVE_FENCE_SYNC)
3063 * The hardware requires a PR to be submitted if there is a TA (otherwise
3064 * it can wedge if we run out of PB space with no PR to run)
3066 * If we only have a TA, attach native checks to the TA and updates to the PR
3067 * If we have a TA and 3D, attach checks to TA, updates to 3D
3068 * If we only have a 3D, attach checks and updates to the 3D
3070 * Note that 'updates' includes the cleanup syncs for 'check' fence FDs, in
3071 * addition to the update fence FD (if supplied)
3073 * Currently, the client driver never kicks only the 3D, so we only support
3074 * that for the time being.
3076 if (i32CheckFenceFD >= 0 || i32UpdateTimelineFD >= 0)
3078 IMG_UINT32 ui32ClientIntUpdateCount = 0;
3079 PRGXFWIF_UFO_ADDR *pauiClientIntUpdateUFOAddress = NULL;
3080 IMG_UINT32 *paui32ClientIntUpdateValue = NULL;
3084 PVR_DPF((PVR_DBG_ERROR, "%s: Native syncs only supported for kicks including a TA",
3086 eError = PVRSRV_ERROR_INVALID_PARAMS;
3091 PVR_DPF((PVR_DBG_ERROR, "%s: Native syncs require a PR for all kicks",
3093 eError = PVRSRV_ERROR_INVALID_PARAMS;
3096 /* If we have a 3D, attach updates to that. Otherwise, we attach it to a PR */
3099 ui32ClientIntUpdateCount = ui32Client3DUpdateCount;
3100 pauiClientIntUpdateUFOAddress = pauiClient3DUpdateUFOAddress;
3101 paui32ClientIntUpdateValue = paui32Client3DUpdateValue;
3105 ui32ClientIntUpdateCount = ui32ClientPRUpdateCount;
3106 pauiClientIntUpdateUFOAddress = pauiClientPRUpdateUFOAddress;
3107 paui32ClientIntUpdateValue = paui32ClientPRUpdateValue;
3111 pvr_sync_append_fences(szFenceName,
3113 i32UpdateTimelineFD,
3114 ui32ClientIntUpdateCount,
3115 pauiClientIntUpdateUFOAddress,
3116 paui32ClientIntUpdateValue,
3117 ui32ClientTAFenceCount,
3118 pauiClientTAFenceUFOAddress,
3119 paui32ClientTAFenceValue,
3121 if (eError != PVRSRV_OK)
3125 /* If we have a 3D, attach updates to that. Otherwise, we attach it to a PR */
3128 pvr_sync_get_updates(psFDData, &ui32Client3DUpdateCount,
3129 &pauiClient3DUpdateUFOAddress, &paui32Client3DUpdateValue);
3133 pvr_sync_get_updates(psFDData, &ui32ClientPRUpdateCount,
3134 &pauiClientPRUpdateUFOAddress, &paui32ClientPRUpdateValue);
3136 pvr_sync_get_checks(psFDData, &ui32ClientTAFenceCount,
3137 &pauiClientTAFenceUFOAddress, &paui32ClientTAFenceValue);
3138 if (ui32ClientPRUpdateCount)
3140 PVR_ASSERT(pauiClientPRUpdateUFOAddress);
3141 PVR_ASSERT(paui32ClientPRUpdateValue);
3143 if (ui32Client3DUpdateCount)
3145 PVR_ASSERT(pauiClient3DUpdateUFOAddress);
3146 PVR_ASSERT(paui32Client3DUpdateValue);
3149 #endif /* SUPPORT_NATIVE_FENCE_SYNC */
3151 /* Init and acquire to TA command if required */
3154 RGX_SERVER_RC_TA_DATA *psTAData = &psRenderContext->sTAData;
3156 #if defined(SUPPORT_WORKLOAD_ESTIMATION)
3157 /* Prepare workload estimation */
3158 WorkEstPrepare(psRenderContext->psDeviceNode->pvDevice,
3159 &(psRenderContext->sWorkEstData),
3160 &(psRenderContext->sWorkEstData.sWorkloadMatchingDataTA),
3161 ui32RenderTargetSize,
3162 ui32NumberOfDrawCalls,
3163 ui32NumberOfIndices,
3166 &sWorkloadKickDataTA);
3169 /* Init the TA command helper */
3170 eError = RGXCmdHelperInitCmdCCB(FWCommonContextGetClientCCB(psTAData->psServerCommonContext),
3171 ui32ClientTAFenceCount,
3172 pauiClientTAFenceUFOAddress,
3173 paui32ClientTAFenceValue,
3174 ui32ClientTAUpdateCount,
3175 pauiClientTAUpdateUFOAddress,
3176 paui32ClientTAUpdateValue,
3177 ui32ServerTASyncPrims,
3178 paui32ServerTASyncFlags,
3184 (bKick3D ? NULL : & pPostAddr),
3185 (bKick3D ? NULL : & pRMWUFOAddr),
3186 RGXFWIF_CCB_CMD_TYPE_TA,
3190 #if defined(SUPPORT_WORKLOAD_ESTIMATION)
3191 &sWorkloadKickDataTA,
3197 if (eError != PVRSRV_OK)
3199 goto fail_tacmdinit;
3202 #if defined(SUPPORT_WORKLOAD_ESTIMATION)
3203 /* The following is used to determine the offset of the command header
3204 * containing the workload estimation data so that can be accessed when
3207 ui32TACmdHeaderOffset = RGXCmdHelperGetDMCommandHeaderOffset(asTACmdHelperData);
3210 eError = RGXCmdHelperAcquireCmdCCB(IMG_ARR_NUM_ELEMS(asTACmdHelperData),
3212 if (eError != PVRSRV_OK)
3214 goto fail_taacquirecmd;
3222 /* Only kick the 3D if required */
3225 RGX_SERVER_RC_3D_DATA *ps3DData = &psRenderContext->s3DData;
3228 The command helper doesn't know about the PR fence so create
3229 the command with all the fences against it and later create
3230 the PR command itself which _must_ come after the PR fence.
3232 sPRUFO.puiAddrUFO = uiPRFenceUFOAddress;
3233 sPRUFO.ui32Value = ui32PRFenceValue;
3235 /* Init the PR fence command helper */
3236 eError = RGXCmdHelperInitCmdCCB(FWCommonContextGetClientCCB(ps3DData->psServerCommonContext),
3237 ui32Client3DFenceCount,
3238 pauiClient3DFenceUFOAddress,
3239 paui32Client3DFenceValue,
3243 (bKick3D ? ui32Server3DSyncPrims : 0),
3244 paui32Server3DSyncFlags,
3245 PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK,
3248 (IMG_UINT8*) &sPRUFO,
3252 RGXFWIF_CCB_CMD_TYPE_FENCE_PR,
3258 &as3DCmdHelperData[ui323DCmdCount++]);
3259 if (eError != PVRSRV_OK)
3261 goto fail_prfencecmdinit;
3264 /* Init the 3D PR command helper */
3266 See note above PVRFDSyncQueryFencesKM as to why updates for android
3267 syncs are passed in with the PR
3269 eError = RGXCmdHelperInitCmdCCB(FWCommonContextGetClientCCB(ps3DData->psServerCommonContext),
3273 ui32ClientPRUpdateCount,
3274 pauiClientPRUpdateUFOAddress,
3275 paui32ClientPRUpdateValue,
3285 RGXFWIF_CCB_CMD_TYPE_3D_PR,
3291 &as3DCmdHelperData[ui323DCmdCount++]);
3292 if (eError != PVRSRV_OK)
3294 goto fail_prcmdinit;
3298 if (bKick3D || bAbort)
3300 RGX_SERVER_RC_3D_DATA *ps3DData = &psRenderContext->s3DData;
3302 #if defined(SUPPORT_WORKLOAD_ESTIMATION)
3303 /* Prepare workload estimation */
3304 WorkEstPrepare(psRenderContext->psDeviceNode->pvDevice,
3305 &(psRenderContext->sWorkEstData),
3306 &(psRenderContext->sWorkEstData.sWorkloadMatchingData3D),
3307 ui32RenderTargetSize,
3308 ui32NumberOfDrawCalls,
3309 ui32NumberOfIndices,
3312 &sWorkloadKickData3D);
3314 /* Init the 3D command helper */
3315 eError = RGXCmdHelperInitCmdCCB(FWCommonContextGetClientCCB(ps3DData->psServerCommonContext),
3319 ui32Client3DUpdateCount,
3320 pauiClient3DUpdateUFOAddress,
3321 paui32Client3DUpdateValue,
3322 ui32Server3DSyncPrims,
3323 paui32Server3DSyncFlags,
3324 PVRSRV_CLIENT_SYNC_PRIM_OP_UPDATE,
3328 (bKickTA ? NULL : & pPreAddr),
3331 RGXFWIF_CCB_CMD_TYPE_3D,
3335 #if defined(SUPPORT_WORKLOAD_ESTIMATION)
3336 &sWorkloadKickData3D,
3341 &as3DCmdHelperData[ui323DCmdCount++]);
3342 if (eError != PVRSRV_OK)
3344 goto fail_3dcmdinit;
3347 #if defined(SUPPORT_WORKLOAD_ESTIMATION)
3348 /* The following are used to determine the offset of the command header
3349 * containing the workload estimation data so that can be accessed when
3352 ui323DCmdHeaderOffset =
3353 RGXCmdHelperGetDMCommandHeaderOffset(&as3DCmdHelperData[ui323DCmdCount - 1]);
3354 ui323DFullRenderCommandOffset =
3355 RGXCmdHelperGetCommandOffset(as3DCmdHelperData,
3356 ui323DCmdCount - 1);
3360 /* Protect against array overflow in RGXCmdHelperAcquireCmdCCB() */
3361 if (ui323DCmdCount > IMG_ARR_NUM_ELEMS(as3DCmdHelperData))
3363 goto fail_3dcmdinit;
3368 PVR_ASSERT(bKickPR || bKick3D);
3370 /* Acquire space for all the 3D command(s) */
3371 eError = RGXCmdHelperAcquireCmdCCB(ui323DCmdCount,
3373 if (eError != PVRSRV_OK)
3375 /* If RGXCmdHelperAcquireCmdCCB fails we skip the scheduling
3376 * of a new TA command with the same Write offset in Kernel CCB.
3378 goto fail_3dacquirecmd;
3383 We should acquire the space in the kernel CCB here as after this point
3384 we release the commands which will take operations on server syncs
3385 which can't be undone
3389 Everything is ready to go now, release the commands
3393 ui32TACmdOffset = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psRenderContext->sTAData.psServerCommonContext));
3394 RGXCmdHelperReleaseCmdCCB(ui32TACmdCount,
3397 FWCommonContextGetFWAddress(psRenderContext->sTAData.psServerCommonContext).ui32Addr);
3399 #if defined(SUPPORT_WORKLOAD_ESTIMATION)
3400 ui32TACmdOffsetWrapCheck =
3401 RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psRenderContext->sTAData.psServerCommonContext));
3403 /* This checks if the command would wrap around at the end of the CCB
3404 * and therefore would start at an offset of 0 rather than the current
3407 if(ui32TACmdOffset < ui32TACmdOffsetWrapCheck)
3409 ui32TACommandOffset = ui32TACmdOffset;
3413 ui32TACommandOffset = 0;
3420 ui323DCmdOffset = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psRenderContext->s3DData.psServerCommonContext));
3421 RGXCmdHelperReleaseCmdCCB(ui323DCmdCount,
3424 FWCommonContextGetFWAddress(psRenderContext->s3DData.psServerCommonContext).ui32Addr);
3425 #if defined(SUPPORT_WORKLOAD_ESTIMATION)
3426 ui323DCmdOffsetWrapCheck = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psRenderContext->s3DData.psServerCommonContext));
3428 if(ui323DCmdOffset < ui323DCmdOffsetWrapCheck)
3430 ui323DCommandOffset = ui323DCmdOffset;
3434 ui323DCommandOffset = 0;
3441 RGXFWIF_KCCB_CMD sTAKCCBCmd;
3442 IMG_UINT32 ui32FWCtx = FWCommonContextGetFWAddress(psRenderContext->sTAData.psServerCommonContext).ui32Addr;
3444 /* Construct the kernel TA CCB command. */
3445 sTAKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_KICK;
3446 sTAKCCBCmd.uCmdData.sCmdKickData.psContext = FWCommonContextGetFWAddress(psRenderContext->sTAData.psServerCommonContext);
3447 sTAKCCBCmd.uCmdData.sCmdKickData.ui32CWoffUpdate = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psRenderContext->sTAData.psServerCommonContext));
3449 /* Add the Workload data into the KCCB kick */
3450 sTAKCCBCmd.uCmdData.sCmdKickData.sWorkloadDataFWAddress.ui32Addr = 0;
3451 sTAKCCBCmd.uCmdData.sCmdKickData.ui32WorkEstCmdHeaderOffset = 0;
3453 #if defined(SUPPORT_WORKLOAD_ESTIMATION)
3454 /* Store the offset to the CCCB command header so that it can be
3455 * referenced when the KCCB command reaches the FW
3457 sTAKCCBCmd.uCmdData.sCmdKickData.ui32WorkEstCmdHeaderOffset =
3458 ui32TACommandOffset + ui32TACmdHeaderOffset;
3461 if(bCommitRefCountsTA)
3463 AttachKickResourcesCleanupCtls((PRGXFWIF_CLEANUP_CTL *) &sTAKCCBCmd.uCmdData.sCmdKickData.apsCleanupCtl,
3464 &sTAKCCBCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl,
3470 *pbCommittedRefCountsTA = IMG_TRUE;
3474 sTAKCCBCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl = 0;
3477 HTBLOGK(HTB_SF_MAIN_KICK_TA,
3478 sTAKCCBCmd.uCmdData.sCmdKickData.psContext,
3481 RGX_HWPERF_HOST_ENQ(psRenderContext, OSGetCurrentClientProcessIDKM(),
3482 ui32FWCtx, ui32ExtJobRef, ui32JobId,
3483 RGX_HWPERF_KICK_TYPE_TA3D);
3485 LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
3487 eError2 = RGXScheduleCommand(psRenderContext->psDeviceNode->pvDevice,
3491 ui32ClientCacheOpSeqNum,
3493 if (eError2 != PVRSRV_ERROR_RETRY)
3497 OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
3498 } END_LOOP_UNTIL_TIMEOUT();
3500 #if defined(SUPPORT_GPUTRACE_EVENTS)
3501 RGXHWPerfFTraceGPUEnqueueEvent(psRenderContext->psDeviceNode->pvDevice,
3502 ui32FWCtx, ui32JobId, RGX_HWPERF_KICK_TYPE_TA3D);
3508 RGXFWIF_KCCB_CMD s3DKCCBCmd;
3510 /* Construct the kernel 3D CCB command. */
3511 s3DKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_KICK;
3512 s3DKCCBCmd.uCmdData.sCmdKickData.psContext = FWCommonContextGetFWAddress(psRenderContext->s3DData.psServerCommonContext);
3513 s3DKCCBCmd.uCmdData.sCmdKickData.ui32CWoffUpdate = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psRenderContext->s3DData.psServerCommonContext));
3515 /* Add the Workload data into the KCCB kick */
3516 s3DKCCBCmd.uCmdData.sCmdKickData.sWorkloadDataFWAddress.ui32Addr = 0;
3517 s3DKCCBCmd.uCmdData.sCmdKickData.ui32WorkEstCmdHeaderOffset = 0;
3519 #if defined(SUPPORT_WORKLOAD_ESTIMATION)
3520 /* Store the offset to the CCCB command header so that it can be
3521 * referenced when the KCCB command reaches the FW
3523 s3DKCCBCmd.uCmdData.sCmdKickData.ui32WorkEstCmdHeaderOffset = ui323DCommandOffset + ui323DCmdHeaderOffset + ui323DFullRenderCommandOffset;
3526 if(bCommitRefCounts3D)
3528 AttachKickResourcesCleanupCtls((PRGXFWIF_CLEANUP_CTL *) &s3DKCCBCmd.uCmdData.sCmdKickData.apsCleanupCtl,
3529 &s3DKCCBCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl,
3535 *pbCommittedRefCounts3D = IMG_TRUE;
3539 s3DKCCBCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl = 0;
3543 HTBLOGK(HTB_SF_MAIN_KICK_3D,
3544 s3DKCCBCmd.uCmdData.sCmdKickData.psContext,
3547 LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
3549 eError2 = RGXScheduleCommand(psRenderContext->psDeviceNode->pvDevice,
3553 ui32ClientCacheOpSeqNum,
3555 if (eError2 != PVRSRV_ERROR_RETRY)
3559 OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
3560 } END_LOOP_UNTIL_TIMEOUT();
3564 * Now check eError (which may have returned an error from our earlier calls
3565 * to RGXCmdHelperAcquireCmdCCB) - we needed to process any flush command first
3566 * so we check it now...
3568 if (eError != PVRSRV_OK )
3570 goto fail_3dacquirecmd;
3573 #if defined(SUPPORT_NATIVE_FENCE_SYNC)
3574 if (i32UpdateTimelineFD >= 0)
3576 /* If we get here, this should never fail. Hitting that likely implies
3577 * a code error above */
3578 i32UpdateFenceFD = pvr_sync_get_update_fd(psFDData);
3579 if (i32UpdateFenceFD < 0)
3581 PVR_DPF((PVR_DBG_ERROR, "%s: Failed to get install update sync fd",
3583 /* If we fail here, we cannot rollback the syncs as the hw already
3584 * has references to resources they may be protecting in the kick
3587 eError = PVRSRV_ERROR_INVALID_PARAMS;
3588 goto fail_3dacquirecmd;
3591 #if defined(NO_HARDWARE)
3592 pvr_sync_nohw_complete_fences(psFDData);
3594 pvr_sync_free_append_fences_data(psFDData);
3598 #if defined(SUPPORT_BUFFER_SYNC)
3601 pvr_buffer_sync_append_finish(psAppendData);
3605 *pi32UpdateFenceFD = i32UpdateFenceFD;
3612 fail_prfencecmdinit:
3615 #if defined(SUPPORT_NATIVE_FENCE_SYNC)
3616 pvr_sync_rollback_append_fences(psFDData);
3617 pvr_sync_free_append_fences_data(psFDData);
3620 #if defined(SUPPORT_BUFFER_SYNC)
3621 pvr_buffer_sync_append_abort(psAppendData);
3624 err_pr_fence_address:
3625 err_populate_sync_addr_list:
3626 PVR_ASSERT(eError != PVRSRV_OK);
3630 PVRSRV_ERROR PVRSRVRGXSetRenderContextPriorityKM(CONNECTION_DATA *psConnection,
3631 PVRSRV_DEVICE_NODE * psDeviceNode,
3632 RGX_SERVER_RENDER_CONTEXT *psRenderContext,
3633 IMG_UINT32 ui32Priority)
3635 PVRSRV_ERROR eError;
3637 PVR_UNREFERENCED_PARAMETER(psDeviceNode);
3639 if (psRenderContext->sTAData.ui32Priority != ui32Priority)
3641 eError = ContextSetPriority(psRenderContext->sTAData.psServerCommonContext,
3643 psRenderContext->psDeviceNode->pvDevice,
3646 if (eError != PVRSRV_OK)
3648 PVR_DPF((PVR_DBG_ERROR, "%s: Failed to set the priority of the TA part of the rendercontext (%s)", __FUNCTION__, PVRSRVGetErrorStringKM(eError)));
3649 goto fail_tacontext;
3651 psRenderContext->sTAData.ui32Priority = ui32Priority;
3654 if (psRenderContext->s3DData.ui32Priority != ui32Priority)
3656 eError = ContextSetPriority(psRenderContext->s3DData.psServerCommonContext,
3658 psRenderContext->psDeviceNode->pvDevice,
3661 if (eError != PVRSRV_OK)
3663 PVR_DPF((PVR_DBG_ERROR, "%s: Failed to set the priority of the 3D part of the rendercontext (%s)", __FUNCTION__, PVRSRVGetErrorStringKM(eError)));
3664 goto fail_3dcontext;
3666 psRenderContext->s3DData.ui32Priority = ui32Priority;
3672 PVR_ASSERT(eError != PVRSRV_OK);
3678 * PVRSRVRGXGetLastRenderContextResetReasonKM
3680 PVRSRV_ERROR PVRSRVRGXGetLastRenderContextResetReasonKM(RGX_SERVER_RENDER_CONTEXT *psRenderContext,
3681 IMG_UINT32 *peLastResetReason,
3682 IMG_UINT32 *pui32LastResetJobRef)
3684 RGX_SERVER_RC_TA_DATA *psRenderCtxTAData;
3685 RGX_SERVER_RC_3D_DATA *psRenderCtx3DData;
3686 RGX_SERVER_COMMON_CONTEXT *psCurrentServerTACommonCtx, *psCurrentServer3DCommonCtx;
3687 RGXFWIF_CONTEXT_RESET_REASON eLastTAResetReason, eLast3DResetReason;
3688 IMG_UINT32 ui32LastTAResetJobRef, ui32Last3DResetJobRef;
3690 PVR_ASSERT(psRenderContext != NULL);
3691 PVR_ASSERT(peLastResetReason != NULL);
3692 PVR_ASSERT(pui32LastResetJobRef != NULL);
3694 psRenderCtxTAData = &(psRenderContext->sTAData);
3695 psCurrentServerTACommonCtx = psRenderCtxTAData->psServerCommonContext;
3696 psRenderCtx3DData = &(psRenderContext->s3DData);
3697 psCurrentServer3DCommonCtx = psRenderCtx3DData->psServerCommonContext;
3699 /* Get the last reset reasons from both the TA and 3D so they are reset... */
3700 eLastTAResetReason = FWCommonContextGetLastResetReason(psCurrentServerTACommonCtx, &ui32LastTAResetJobRef);
3701 eLast3DResetReason = FWCommonContextGetLastResetReason(psCurrentServer3DCommonCtx, &ui32Last3DResetJobRef);
3703 /* Combine the reset reason from TA and 3D into one... */
3704 *peLastResetReason = (IMG_UINT32) eLast3DResetReason;
3705 *pui32LastResetJobRef = ui32Last3DResetJobRef;
3706 if (eLast3DResetReason == RGXFWIF_CONTEXT_RESET_REASON_NONE ||
3707 ((eLast3DResetReason == RGXFWIF_CONTEXT_RESET_REASON_INNOCENT_LOCKUP ||
3708 eLast3DResetReason == RGXFWIF_CONTEXT_RESET_REASON_INNOCENT_OVERRUNING) &&
3709 (eLastTAResetReason == RGXFWIF_CONTEXT_RESET_REASON_GUILTY_LOCKUP ||
3710 eLastTAResetReason == RGXFWIF_CONTEXT_RESET_REASON_GUILTY_OVERRUNING)))
3712 *peLastResetReason = eLastTAResetReason;
3713 *pui32LastResetJobRef = ui32LastTAResetJobRef;
3721 * PVRSRVRGXGetPartialRenderCountKM
3723 PVRSRV_ERROR PVRSRVRGXGetPartialRenderCountKM(DEVMEM_MEMDESC *psHWRTDataMemDesc,
3724 IMG_UINT32 *pui32NumPartialRenders)
3726 RGXFWIF_HWRTDATA *psHWRTData;
3727 PVRSRV_ERROR eError;
3729 eError = DevmemAcquireCpuVirtAddr(psHWRTDataMemDesc, (void **)&psHWRTData);
3731 if (eError != PVRSRV_OK)
3733 PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXGetPartialRenderCountKM: Failed to map Firmware Render Target Data (%u)", eError));
3737 *pui32NumPartialRenders = psHWRTData->ui32NumPartialRenders;
3739 DevmemReleaseCpuVirtAddr(psHWRTDataMemDesc);
3744 void CheckForStalledRenderCtxt(PVRSRV_RGXDEV_INFO *psDevInfo,
3745 DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
3746 void *pvDumpDebugFile)
3748 DLLIST_NODE *psNode, *psNext;
3749 OSWRLockAcquireRead(psDevInfo->hRenderCtxListLock);
3750 dllist_foreach_node(&psDevInfo->sRenderCtxtListHead, psNode, psNext)
3752 RGX_SERVER_RENDER_CONTEXT *psCurrentServerRenderCtx =
3753 IMG_CONTAINER_OF(psNode, RGX_SERVER_RENDER_CONTEXT, sListNode);
3755 DumpStalledFWCommonContext(psCurrentServerRenderCtx->sTAData.psServerCommonContext,
3756 pfnDumpDebugPrintf, pvDumpDebugFile);
3757 DumpStalledFWCommonContext(psCurrentServerRenderCtx->s3DData.psServerCommonContext,
3758 pfnDumpDebugPrintf, pvDumpDebugFile);
3760 OSWRLockReleaseRead(psDevInfo->hRenderCtxListLock);
3763 IMG_UINT32 CheckForStalledClientRenderCtxt(PVRSRV_RGXDEV_INFO *psDevInfo)
3765 DLLIST_NODE *psNode, *psNext;
3766 IMG_UINT32 ui32ContextBitMask = 0;
3768 OSWRLockAcquireRead(psDevInfo->hRenderCtxListLock);
3770 dllist_foreach_node(&psDevInfo->sRenderCtxtListHead, psNode, psNext)
3772 RGX_SERVER_RENDER_CONTEXT *psCurrentServerRenderCtx =
3773 IMG_CONTAINER_OF(psNode, RGX_SERVER_RENDER_CONTEXT, sListNode);
3774 if(NULL != psCurrentServerRenderCtx->sTAData.psServerCommonContext)
3776 if (CheckStalledClientCommonContext(psCurrentServerRenderCtx->sTAData.psServerCommonContext, RGX_KICK_TYPE_DM_TA) == PVRSRV_ERROR_CCCB_STALLED)
3778 ui32ContextBitMask |= RGX_KICK_TYPE_DM_TA;
3782 if(NULL != psCurrentServerRenderCtx->s3DData.psServerCommonContext)
3784 if (CheckStalledClientCommonContext(psCurrentServerRenderCtx->s3DData.psServerCommonContext, RGX_KICK_TYPE_DM_3D) == PVRSRV_ERROR_CCCB_STALLED)
3786 ui32ContextBitMask |= RGX_KICK_TYPE_DM_3D;
3791 OSWRLockReleaseRead(psDevInfo->hRenderCtxListLock);
3792 return ui32ContextBitMask;
3795 /******************************************************************************
3796 End of file (rgxta3d.c)
3797 ******************************************************************************/