1 /*************************************************************************/ /*!
3 @Title Services synchronisation interface
4 @Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
5 @Description Implements client side code for services synchronisation
7 @License Dual MIT/GPLv2
9 The contents of this file are subject to the MIT license as set out below.
11 Permission is hereby granted, free of charge, to any person obtaining a copy
12 of this software and associated documentation files (the "Software"), to deal
13 in the Software without restriction, including without limitation the rights
14 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 copies of the Software, and to permit persons to whom the Software is
16 furnished to do so, subject to the following conditions:
18 The above copyright notice and this permission notice shall be included in
19 all copies or substantial portions of the Software.
21 Alternatively, the contents of this file may be used under the terms of
22 the GNU General Public License Version 2 ("GPL") in which case the provisions
23 of GPL are applicable instead of those above.
25 If you wish to allow use of your version of this file only under the terms of
26 GPL, and not to allow others to use your version of this file under the terms
27 of the MIT license, indicate your decision by deleting the provisions above
28 and replace them with the notice and other provisions required by GPL as set
29 out in the file called "GPL-COPYING" included in this distribution. If you do
30 not delete the provisions above, a recipient may use your version of this file
31 under the terms of either the MIT license or GPL.
33 This License is also included in this distribution in the file called
36 EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
37 PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
38 BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
39 PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
40 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
41 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
42 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
43 */ /**************************************************************************/
45 #include "img_types.h"
46 #include "client_sync_bridge.h"
49 #include "devicemem.h"
50 #include "devicemem_pdump.h"
51 #include "pvr_debug.h"
54 #include "sync_internal.h"
56 #include "pvr_debug.h"
58 #if defined(__KERNEL__)
63 #define SYNC_BLOCK_LIST_CHUNCK_SIZE 10
64 #define LOCAL_SYNC_PRIM_RESET_VALUE 0
67 This defines the maximum amount of synchronisation memory
68 that can be allocated per SyncPrim context.
69 In reality this number is meaningless as we would run out
70 of synchronisation memory before we reach this limit, but
71 we need to provide a size to the span RA.
73 #define MAX_SYNC_MEM (4 * 1024 * 1024)
75 typedef struct _SYNC_BLOCK_LIST_
77 IMG_UINT32 ui32BlockCount; /*!< Number of contexts in the list */
78 IMG_UINT32 ui32BlockListSize; /*!< Size of the array contexts */
79 SYNC_PRIM_BLOCK **papsSyncPrimBlock; /*!< Array of syncprim blocks */
82 typedef struct _SYNC_OP_COOKIE_
84 IMG_UINT32 ui32SyncCount;
85 IMG_UINT32 ui32ClientSyncCount;
86 IMG_UINT32 ui32ServerSyncCount;
87 IMG_BOOL bHaveServerSync;
89 IMG_HANDLE hServerCookie;
91 SYNC_BLOCK_LIST *psSyncBlockList;
92 PVRSRV_CLIENT_SYNC_PRIM **papsSyncPrim;
95 If this changes update the calculation of ui32ClientAllocSize
97 IMG_UINT32 *paui32SyncBlockIndex;
98 IMG_UINT32 *paui32Index;
99 IMG_UINT32 *paui32Flags;
100 IMG_UINT32 *paui32FenceValue;
101 IMG_UINT32 *paui32UpdateValue;
105 If this changes update the calculation of ui32ServerAllocSize
107 IMG_HANDLE *pahServerSync;
108 IMG_UINT32 *paui32ServerFlags;
111 /* forward declaration */
113 _SyncPrimSetValue(SYNC_PRIM *psSyncInt, IMG_UINT32 ui32Value);
116 Internal interfaces for management of SYNC_PRIM_CONTEXT
119 _SyncPrimContextUnref(SYNC_PRIM_CONTEXT *psContext)
121 if (!OSAtomicRead(&psContext->hRefCount))
123 PVR_DPF((PVR_DBG_ERROR, "_SyncPrimContextUnref context already freed"));
125 else if (0 == OSAtomicDecrement(&psContext->hRefCount))
127 /* SyncPrimContextDestroy only when no longer referenced */
128 RA_Delete(psContext->psSpanRA);
129 RA_Delete(psContext->psSubAllocRA);
130 OSFreeMem(psContext);
135 _SyncPrimContextRef(SYNC_PRIM_CONTEXT *psContext)
137 if (!OSAtomicRead(&psContext->hRefCount))
139 PVR_DPF((PVR_DBG_ERROR, "_SyncPrimContextRef context use after free"));
143 OSAtomicIncrement(&psContext->hRefCount);
148 Internal interfaces for management of synchronisation block memory
151 AllocSyncPrimitiveBlock(SYNC_PRIM_CONTEXT *psContext,
152 SYNC_PRIM_BLOCK **ppsSyncBlock)
154 SYNC_PRIM_BLOCK *psSyncBlk;
155 DEVMEM_SERVER_EXPORTCOOKIE hServerExportCookie;
156 DEVMEM_EXPORTCOOKIE sExportCookie;
159 psSyncBlk = OSAllocMem(sizeof(SYNC_PRIM_BLOCK));
160 if (psSyncBlk == IMG_NULL)
162 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
165 psSyncBlk->psContext = psContext;
167 /* Allocate sync prim block */
168 eError = BridgeAllocSyncPrimitiveBlock(psContext->hBridge,
169 psContext->hDeviceNode,
170 &psSyncBlk->hServerSyncPrimBlock,
171 &psSyncBlk->ui32FirmwareAddr,
172 &psSyncBlk->ui32SyncBlockSize,
173 &hServerExportCookie);
174 if (eError != PVRSRV_OK)
176 goto fail_blockalloc;
179 /* Make it mappable by the client */
180 eError = DevmemMakeServerExportClientExport(psContext->hBridge,
183 if (eError != PVRSRV_OK)
188 /* Get CPU mapping of the memory block */
189 eError = DevmemImport(psContext->hBridge,
191 PVRSRV_MEMALLOCFLAG_CPU_READABLE,
192 &psSyncBlk->hMemDesc);
195 Regardless of success or failure we "undo" the export
197 DevmemUnmakeServerExportClientExport(psContext->hBridge,
200 if (eError != PVRSRV_OK)
205 eError = DevmemAcquireCpuVirtAddr(psSyncBlk->hMemDesc,
206 (IMG_PVOID *) &psSyncBlk->pui32LinAddr);
207 if (eError != PVRSRV_OK)
212 *ppsSyncBlock = psSyncBlk;
216 DevmemFree(psSyncBlk->hMemDesc);
219 BridgeFreeSyncPrimitiveBlock(psContext->hBridge,
220 psSyncBlk->hServerSyncPrimBlock);
222 OSFreeMem(psSyncBlk);
228 FreeSyncPrimitiveBlock(SYNC_PRIM_BLOCK *psSyncBlk)
230 SYNC_PRIM_CONTEXT *psContext = psSyncBlk->psContext;
232 DevmemReleaseCpuVirtAddr(psSyncBlk->hMemDesc);
233 DevmemFree(psSyncBlk->hMemDesc);
234 BridgeFreeSyncPrimitiveBlock(psContext->hBridge,
235 psSyncBlk->hServerSyncPrimBlock);
236 OSFreeMem(psSyncBlk);
240 SyncPrimBlockImport(RA_PERARENA_HANDLE hArena,
244 RA_LENGTH_T *puiActualSize,
245 RA_PERISPAN_HANDLE *phImport)
247 SYNC_PRIM_CONTEXT *psContext = hArena;
248 SYNC_PRIM_BLOCK *psSyncBlock = IMG_NULL;
249 RA_LENGTH_T uiSpanSize;
252 PVR_UNREFERENCED_PARAMETER(uFlags);
254 /* Check we've not be called with an unexpected size */
255 if (!hArena || sizeof(IMG_UINT32) != uSize)
257 PVR_DPF((PVR_DBG_ERROR, "%s: invalid input params", __FUNCTION__));
262 Ensure the synprim context doesn't go away while we have sync blocks
265 _SyncPrimContextRef(psContext);
267 /* Allocate the block of memory */
268 eError = AllocSyncPrimitiveBlock(psContext, &psSyncBlock);
269 if (eError != PVRSRV_OK)
271 PVR_DPF((PVR_DBG_ERROR, "Failed to allocation syncprim block (%d)", eError));
272 goto fail_syncblockalloc;
275 /* Allocate a span for it */
276 bRet = RA_Alloc(psContext->psSpanRA,
277 psSyncBlock->ui32SyncBlockSize,
279 psSyncBlock->ui32SyncBlockSize,
280 &psSyncBlock->uiSpanBase,
285 There is no reason the span RA should return an allocation larger
288 if (bRet == IMG_FALSE || uiSpanSize != psSyncBlock->ui32SyncBlockSize)
293 *puiBase = psSyncBlock->uiSpanBase;
294 *puiActualSize = psSyncBlock->ui32SyncBlockSize;
295 *phImport = psSyncBlock;
299 FreeSyncPrimitiveBlock(psSyncBlock);
301 _SyncPrimContextUnref(psContext);
307 SyncPrimBlockUnimport(RA_PERARENA_HANDLE hArena,
309 RA_PERISPAN_HANDLE hImport)
311 SYNC_PRIM_CONTEXT *psContext = hArena;
312 SYNC_PRIM_BLOCK *psSyncBlock = hImport;
314 if (!psContext || !psSyncBlock || uiBase != psSyncBlock->uiSpanBase)
316 PVR_DPF((PVR_DBG_ERROR, "%s: invalid input params", __FUNCTION__));
320 /* Free the span this import is using */
321 RA_Free(psContext->psSpanRA, uiBase);
323 /* Free the syncpim block */
324 FreeSyncPrimitiveBlock(psSyncBlock);
326 /* Drop our reference to the syncprim context */
327 _SyncPrimContextUnref(psContext);
330 static INLINE IMG_UINT32 SyncPrimGetOffset(SYNC_PRIM *psSyncInt)
334 PVR_ASSERT(psSyncInt->eType == SYNC_PRIM_TYPE_LOCAL);
336 /* FIXME: Subtracting a 64-bit address from another and then implicit
337 * cast to 32-bit number. Need to review all call sequences that use this
338 * function, added explicit casting for now.
340 ui64Temp = psSyncInt->u.sLocal.uiSpanAddr - psSyncInt->u.sLocal.psSyncBlock->uiSpanBase;
341 PVR_ASSERT(ui64Temp<IMG_UINT32_MAX);
342 return (IMG_UINT32)ui64Temp;
345 static IMG_VOID SyncPrimGetCPULinAddr(SYNC_PRIM *psSyncInt)
347 SYNC_PRIM_BLOCK *psSyncBlock = psSyncInt->u.sLocal.psSyncBlock;
349 psSyncInt->sCommon.pui32LinAddr = psSyncBlock->pui32LinAddr +
350 (SyncPrimGetOffset(psSyncInt)/sizeof(IMG_UINT32));
353 static IMG_VOID SyncPrimLocalFree(SYNC_PRIM *psSyncInt)
355 SYNC_PRIM_BLOCK *psSyncBlock;
356 SYNC_PRIM_CONTEXT *psContext;
358 #if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
361 /* remove this sync record */
362 eError = BridgeSyncRecordRemoveByHandle(
363 psSyncInt->u.sLocal.psSyncBlock->psContext->hBridge,
364 psSyncInt->u.sLocal.hRecord);
365 if (PVRSRV_OK != eError)
367 PVR_DPF((PVR_DBG_ERROR, "%s: failed to remove SyncRecord", __FUNCTION__));
371 /* reset the sync prim value as it is freed.
372 * this guarantees the client sync allocated to the client will
373 * have a value of zero and the client does not need to
374 * explicitly initialise the sync value to zero.
375 * the allocation of the backing memory for the sync prim block
376 * is done with ZERO_ON_ALLOC so the memory is initially all zero.
378 _SyncPrimSetValue(psSyncInt, LOCAL_SYNC_PRIM_RESET_VALUE);
380 psSyncBlock = psSyncInt->u.sLocal.psSyncBlock;
381 psContext = psSyncBlock->psContext;
383 RA_Free(psContext->psSubAllocRA, psSyncInt->u.sLocal.uiSpanAddr);
384 OSFreeMem(psSyncInt);
385 _SyncPrimContextUnref(psContext);
388 static IMG_VOID SyncPrimServerFree(SYNC_PRIM *psSyncInt)
392 eError = BridgeServerSyncFree(psSyncInt->u.sServer.hBridge,
393 psSyncInt->u.sServer.hServerSync);
394 if (eError != PVRSRV_OK)
396 PVR_DPF((PVR_DBG_ERROR, "SyncPrimServerFree failed"));
398 OSFreeMem(psSyncInt);
401 static IMG_VOID SyncPrimLocalUnref(SYNC_PRIM *psSyncInt)
403 if (!OSAtomicRead(&psSyncInt->u.sLocal.hRefCount))
405 PVR_DPF((PVR_DBG_ERROR, "SyncPrimLocalUnref sync already freed"));
407 else if (0 == OSAtomicDecrement(&psSyncInt->u.sLocal.hRefCount))
409 SyncPrimLocalFree(psSyncInt);
413 static IMG_VOID SyncPrimLocalRef(SYNC_PRIM *psSyncInt)
415 if (!OSAtomicRead(&psSyncInt->u.sLocal.hRefCount))
417 PVR_DPF((PVR_DBG_ERROR, "SyncPrimLocalRef sync use after free"));
421 OSAtomicIncrement(&psSyncInt->u.sLocal.hRefCount);
425 static IMG_UINT32 SyncPrimGetFirmwareAddrLocal(SYNC_PRIM *psSyncInt)
427 SYNC_PRIM_BLOCK *psSyncBlock;
429 psSyncBlock = psSyncInt->u.sLocal.psSyncBlock;
430 return psSyncBlock->ui32FirmwareAddr + SyncPrimGetOffset(psSyncInt);
433 static IMG_UINT32 SyncPrimGetFirmwareAddrServer(SYNC_PRIM *psSyncInt)
435 return psSyncInt->u.sServer.ui32FirmwareAddr;
438 #if !defined(__KERNEL__)
439 static SYNC_BRIDGE_HANDLE _SyncPrimGetBridgeHandleLocal(SYNC_PRIM *psSyncInt)
441 return psSyncInt->u.sLocal.psSyncBlock->psContext->hBridge;
444 static SYNC_BRIDGE_HANDLE _SyncPrimGetBridgeHandleServer(SYNC_PRIM *psSyncInt)
446 return psSyncInt->u.sServer.hBridge;
449 static SYNC_BRIDGE_HANDLE _SyncPrimGetBridgeHandle(PVRSRV_CLIENT_SYNC_PRIM *psSync)
451 SYNC_PRIM *psSyncInt;
453 psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
454 if (psSyncInt->eType == SYNC_PRIM_TYPE_LOCAL)
456 return _SyncPrimGetBridgeHandleLocal(psSyncInt);
458 else if (psSyncInt->eType == SYNC_PRIM_TYPE_SERVER)
460 return _SyncPrimGetBridgeHandleServer(psSyncInt);
464 PVR_DPF((PVR_DBG_ERROR, "_SyncPrimGetBridgeHandle: Invalid sync type"));
466 Either the client has given us a bad pointer or there is an
475 Internal interfaces for management of syncprim block lists
477 static SYNC_BLOCK_LIST *_SyncPrimBlockListCreate(IMG_VOID)
479 SYNC_BLOCK_LIST *psBlockList;
481 psBlockList = OSAllocMem(sizeof(SYNC_BLOCK_LIST));
487 psBlockList->ui32BlockCount = 0;
488 psBlockList->ui32BlockListSize = SYNC_BLOCK_LIST_CHUNCK_SIZE;
490 psBlockList->papsSyncPrimBlock = OSAllocMem(sizeof(SYNC_PRIM_BLOCK *)
491 * SYNC_BLOCK_LIST_CHUNCK_SIZE);
492 if (!psBlockList->papsSyncPrimBlock)
494 OSFreeMem(psBlockList);
498 OSCachedMemSet(psBlockList->papsSyncPrimBlock,
500 sizeof(SYNC_PRIM_BLOCK *) * psBlockList->ui32BlockListSize);
505 static PVRSRV_ERROR _SyncPrimBlockListAdd(SYNC_BLOCK_LIST *psBlockList,
506 SYNC_PRIM_BLOCK *psSyncPrimBlock)
510 /* Check the context isn't already on the list */
511 for (i=0;i<psBlockList->ui32BlockCount;i++)
513 if (psBlockList->papsSyncPrimBlock[i] == psSyncPrimBlock)
519 /* Check we have space for a new item */
520 if (psBlockList->ui32BlockCount == psBlockList->ui32BlockListSize)
522 SYNC_PRIM_BLOCK **papsNewSyncPrimBlock;
524 papsNewSyncPrimBlock = OSAllocMem(sizeof(SYNC_PRIM_BLOCK *) *
525 (psBlockList->ui32BlockListSize +
526 SYNC_BLOCK_LIST_CHUNCK_SIZE));
527 if (!papsNewSyncPrimBlock)
529 return PVRSRV_ERROR_OUT_OF_MEMORY;
532 OSCachedMemCopy(papsNewSyncPrimBlock,
533 psBlockList->papsSyncPrimBlock,
534 sizeof(SYNC_PRIM_CONTEXT *) *
535 psBlockList->ui32BlockListSize);
537 OSFreeMem(psBlockList->papsSyncPrimBlock);
539 psBlockList->papsSyncPrimBlock = papsNewSyncPrimBlock;
540 psBlockList->ui32BlockListSize += SYNC_BLOCK_LIST_CHUNCK_SIZE;
543 /* Add the context to the list */
544 psBlockList->papsSyncPrimBlock[psBlockList->ui32BlockCount++] = psSyncPrimBlock;
548 static PVRSRV_ERROR _SyncPrimBlockListBlockToIndex(SYNC_BLOCK_LIST *psBlockList,
549 SYNC_PRIM_BLOCK *psSyncPrimBlock,
550 IMG_UINT32 *pui32Index)
554 for (i=0;i<psBlockList->ui32BlockCount;i++)
556 if (psBlockList->papsSyncPrimBlock[i] == psSyncPrimBlock)
563 return PVRSRV_ERROR_INVALID_PARAMS;
566 static PVRSRV_ERROR _SyncPrimBlockListHandleArrayCreate(SYNC_BLOCK_LIST *psBlockList,
567 IMG_UINT32 *pui32BlockHandleCount,
568 IMG_HANDLE **ppahHandleList)
570 IMG_HANDLE *pahHandleList;
573 pahHandleList = OSAllocMem(sizeof(IMG_HANDLE) *
574 psBlockList->ui32BlockCount);
577 return PVRSRV_ERROR_OUT_OF_MEMORY;
580 for (i=0;i<psBlockList->ui32BlockCount;i++)
582 pahHandleList[i] = psBlockList->papsSyncPrimBlock[i]->hServerSyncPrimBlock;
585 *ppahHandleList = pahHandleList;
586 *pui32BlockHandleCount = psBlockList->ui32BlockCount;
591 static IMG_VOID _SyncPrimBlockListHandleArrayDestroy(IMG_HANDLE *pahHandleList)
593 OSFreeMem(pahHandleList);
596 static IMG_UINT32 _SyncPrimBlockListGetClientValue(SYNC_BLOCK_LIST *psBlockList,
597 IMG_UINT32 ui32BlockIndex,
598 IMG_UINT32 ui32Index)
600 return psBlockList->papsSyncPrimBlock[ui32BlockIndex]->pui32LinAddr[ui32Index];
603 static IMG_VOID _SyncPrimBlockListDestroy(SYNC_BLOCK_LIST *psBlockList)
605 OSFreeMem(psBlockList->papsSyncPrimBlock);
606 OSFreeMem(psBlockList);
610 /* TODO: implement _Log2 using __builtin_clz gcc's builtin */
611 /* TODO: factorise the log2 functions (there is a similar one in services/shared/common/ra.c) */
612 static INLINE IMG_UINT32 _Log2(IMG_UINT32 ui32Align)
614 IMG_UINT32 ui32Log2Align = 0;
615 PVR_ASSERT(ui32Align != 0); /* Log2 isn't defined on 0 (triggers an assert instead of an infinite loop) */
617 while (!(ui32Align & 1))
620 ui32Align = ui32Align >> 1;
622 PVR_ASSERT(ui32Align == 1);
624 return ui32Log2Align;
631 IMG_INTERNAL PVRSRV_ERROR
632 SyncPrimContextCreate(SYNC_BRIDGE_HANDLE hBridge,
633 IMG_HANDLE hDeviceNode,
634 PSYNC_PRIM_CONTEXT *phSyncPrimContext)
636 SYNC_PRIM_CONTEXT *psContext;
639 psContext = OSAllocMem(sizeof(SYNC_PRIM_CONTEXT));
640 if (psContext == IMG_NULL)
642 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
646 psContext->hBridge = hBridge;
647 psContext->hDeviceNode = hDeviceNode;
649 OSSNPrintf(psContext->azName, SYNC_PRIM_NAME_SIZE, "Sync Prim RA-%p", psContext);
650 OSSNPrintf(psContext->azSpanName, SYNC_PRIM_NAME_SIZE, "Sync Prim span RA-%p", psContext);
653 Create the RA for sub-allocations of the SynPrim's
656 The import size doesn't matter here as the server will pass
657 back the blocksize when does the import which overrides
658 what we specify here.
661 psContext->psSubAllocRA = RA_Create(psContext->azName,
662 /* Params for imports */
663 _Log2(sizeof(IMG_UINT32)),
666 SyncPrimBlockUnimport,
669 if (psContext->psSubAllocRA == IMG_NULL)
671 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
676 Create the span-management RA
678 The RA requires that we work with linear spans. For our use
679 here we don't require this behaviour as we're always working
680 within offsets of blocks (imports). However, we need to keep
681 the RA happy so we create the "span" management RA which
682 ensures that all are imports are added to the RA in a linear
685 psContext->psSpanRA = RA_Create(psContext->azSpanName,
686 /* Params for imports */
693 if (psContext->psSpanRA == IMG_NULL)
695 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
699 if (!RA_Add(psContext->psSpanRA, 0, MAX_SYNC_MEM, 0, IMG_NULL))
701 RA_Delete(psContext->psSpanRA);
702 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
706 OSAtomicWrite(&psContext->hRefCount, 1);
708 *phSyncPrimContext = psContext;
711 RA_Delete(psContext->psSubAllocRA);
713 OSFreeMem(psContext);
718 IMG_INTERNAL IMG_VOID SyncPrimContextDestroy(PSYNC_PRIM_CONTEXT hSyncPrimContext)
720 SYNC_PRIM_CONTEXT *psContext = hSyncPrimContext;
721 if (1 != OSAtomicRead(&psContext->hRefCount))
723 PVR_DPF((PVR_DBG_ERROR, "%s attempted with active references, may be the result of a race", __FUNCTION__));
725 _SyncPrimContextUnref(psContext);
728 static PVRSRV_ERROR _SyncPrimAlloc(PSYNC_PRIM_CONTEXT hSyncPrimContext,
729 PVRSRV_CLIENT_SYNC_PRIM **ppsSync,
730 const IMG_CHAR *pszClassName,
731 IMG_BOOL bServerSync)
733 SYNC_PRIM_CONTEXT *psContext = hSyncPrimContext;
734 SYNC_PRIM_BLOCK *psSyncBlock;
735 SYNC_PRIM *psNewSync;
737 RA_BASE_T uiSpanAddr;
739 psNewSync = OSAllocMem(sizeof(SYNC_PRIM));
740 if (psNewSync == IMG_NULL)
742 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
746 if (!RA_Alloc(psContext->psSubAllocRA,
752 (RA_PERISPAN_HANDLE *) &psSyncBlock))
754 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
757 psNewSync->eType = SYNC_PRIM_TYPE_LOCAL;
758 OSAtomicWrite(&psNewSync->u.sLocal.hRefCount, 1);
759 psNewSync->u.sLocal.uiSpanAddr = uiSpanAddr;
760 psNewSync->u.sLocal.psSyncBlock = psSyncBlock;
761 SyncPrimGetCPULinAddr(psNewSync);
762 *ppsSync = &psNewSync->sCommon;
763 _SyncPrimContextRef(psContext);
765 #if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
767 IMG_CHAR szClassName[SYNC_MAX_CLASS_NAME_LEN];
770 /* Copy the class name annotation into a fixed-size array */
771 OSStringNCopy(szClassName, pszClassName, SYNC_MAX_CLASS_NAME_LEN - 1);
772 szClassName[SYNC_MAX_CLASS_NAME_LEN - 1] = 0;
776 /* No class name annotation */
779 /* record this sync */
780 eError = BridgeSyncRecordAdd(
781 psSyncBlock->psContext->hBridge,
782 &psNewSync->u.sLocal.hRecord,
783 psSyncBlock->hServerSyncPrimBlock,
784 psSyncBlock->ui32FirmwareAddr,
785 SyncPrimGetOffset(psNewSync),
787 OSStringNLength(szClassName, SYNC_MAX_CLASS_NAME_LEN),
789 if (PVRSRV_OK != eError)
791 PVR_DPF((PVR_DBG_ERROR, "%s: failed to add SyncRecord", __FUNCTION__));
795 PVR_UNREFERENCED_PARAMETER(pszClassName);
796 PVR_UNREFERENCED_PARAMETER(bServerSync);
797 #endif /* if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING) */
802 OSFreeMem(psNewSync);
807 #if defined(__KERNEL__)
808 IMG_INTERNAL PVRSRV_ERROR SyncPrimAllocForServerSync(PSYNC_PRIM_CONTEXT hSyncPrimContext,
809 PVRSRV_CLIENT_SYNC_PRIM **ppsSync,
810 const IMG_CHAR *pszClassName)
812 return _SyncPrimAlloc(hSyncPrimContext,
819 IMG_INTERNAL PVRSRV_ERROR SyncPrimAlloc(PSYNC_PRIM_CONTEXT hSyncPrimContext,
820 PVRSRV_CLIENT_SYNC_PRIM **ppsSync,
821 const IMG_CHAR *pszClassName)
823 return _SyncPrimAlloc(hSyncPrimContext,
830 _SyncPrimSetValue(SYNC_PRIM *psSyncInt, IMG_UINT32 ui32Value)
834 if (psSyncInt->eType == SYNC_PRIM_TYPE_LOCAL)
836 SYNC_PRIM_BLOCK *psSyncBlock;
837 SYNC_PRIM_CONTEXT *psContext;
839 psSyncBlock = psSyncInt->u.sLocal.psSyncBlock;
840 psContext = psSyncBlock->psContext;
842 eError = BridgeSyncPrimSet(psContext->hBridge,
843 psSyncBlock->hServerSyncPrimBlock,
844 SyncPrimGetOffset(psSyncInt)/sizeof(IMG_UINT32),
849 eError = BridgeServerSyncPrimSet(psSyncInt->u.sServer.hBridge,
850 psSyncInt->u.sServer.hServerSync,
853 /* These functions don't actually fail */
854 if (PVRSRV_OK != eError)
856 PVR_DPF((PVR_DBG_ERROR, "%s: failed", __FUNCTION__));
860 IMG_INTERNAL IMG_VOID SyncPrimFree(PVRSRV_CLIENT_SYNC_PRIM *psSync)
862 SYNC_PRIM *psSyncInt;
866 PVR_DPF((PVR_DBG_ERROR, "%s: null sync pointer", __FUNCTION__));
870 psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
871 if (psSyncInt->eType == SYNC_PRIM_TYPE_LOCAL)
873 SyncPrimLocalUnref(psSyncInt);
875 else if (psSyncInt->eType == SYNC_PRIM_TYPE_SERVER)
877 SyncPrimServerFree(psSyncInt);
881 PVR_DPF((PVR_DBG_ERROR, "SyncPrimFree: Invalid sync type"));
883 Either the client has given us a bad pointer or there is an
890 #if defined(NO_HARDWARE)
891 IMG_INTERNAL IMG_VOID
892 SyncPrimNoHwUpdate(PVRSRV_CLIENT_SYNC_PRIM *psSync, IMG_UINT32 ui32Value)
894 SYNC_PRIM *psSyncInt;
898 PVR_DPF((PVR_DBG_ERROR, "%s: null sync pointer", __FUNCTION__));
901 psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
903 /* There is no check for the psSyncInt to be LOCAL as this call
904 substitutes the Firmware updating a sync and that sync could
907 _SyncPrimSetValue(psSyncInt, ui32Value);
911 IMG_INTERNAL IMG_VOID
912 SyncPrimSet(PVRSRV_CLIENT_SYNC_PRIM *psSync, IMG_UINT32 ui32Value)
914 SYNC_PRIM *psSyncInt;
918 PVR_DPF((PVR_DBG_ERROR, "%s: null sync pointer", __FUNCTION__));
922 psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
923 if (psSyncInt->eType != SYNC_PRIM_TYPE_LOCAL)
925 PVR_DPF((PVR_DBG_ERROR, "SyncPrimSet: Invalid sync type"));
929 _SyncPrimSetValue(psSyncInt, ui32Value);
932 SyncPrimPDump(psSync);
937 IMG_INTERNAL PVRSRV_ERROR SyncPrimLocalGetHandleAndOffset(PVRSRV_CLIENT_SYNC_PRIM *psSync,
939 IMG_UINT32 *pui32Offset)
941 PVRSRV_ERROR eError = PVRSRV_OK;
942 SYNC_PRIM *psSyncInt;
944 if(!psSync || !phBlock || !pui32Offset)
946 PVR_DPF((PVR_DBG_ERROR, "SyncPrimGetHandleAndOffset: invalid input pointer"));
947 eError = PVRSRV_ERROR_INVALID_PARAMS;
951 psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
953 if (psSyncInt->eType == SYNC_PRIM_TYPE_LOCAL)
955 *phBlock = psSyncInt->u.sLocal.psSyncBlock->hServerSyncPrimBlock;
956 *pui32Offset = psSyncInt->u.sLocal.uiSpanAddr - psSyncInt->u.sLocal.psSyncBlock->uiSpanBase;
960 PVR_DPF((PVR_DBG_ERROR, "%s: psSync not a Local sync prim (%d)",
961 __FUNCTION__, psSyncInt->eType));
962 eError = PVRSRV_ERROR_INVALID_PARAMS;
970 IMG_INTERNAL IMG_UINT32 SyncPrimGetFirmwareAddr(PVRSRV_CLIENT_SYNC_PRIM *psSync)
972 SYNC_PRIM *psSyncInt;
975 PVR_DPF((PVR_DBG_ERROR, "%s: invalid input pointer", __FUNCTION__));
979 psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
980 if (psSyncInt->eType == SYNC_PRIM_TYPE_LOCAL)
982 return SyncPrimGetFirmwareAddrLocal(psSyncInt);
984 else if (psSyncInt->eType == SYNC_PRIM_TYPE_SERVER)
986 return SyncPrimGetFirmwareAddrServer(psSyncInt);
990 PVR_DPF((PVR_DBG_ERROR, "SyncPrimGetFirmwareAddr: Invalid sync type"));
992 Either the client has given us a bad pointer or there is an
1001 #if !defined(__KERNEL__)
1002 IMG_INTERNAL PVRSRV_ERROR SyncPrimDumpSyncs(IMG_UINT32 ui32SyncCount, PVRSRV_CLIENT_SYNC_PRIM **papsSync, const IMG_CHAR *pcszExtraInfo)
1004 #if defined(PVRSRV_NEED_PVR_DPF)
1005 SYNC_PRIM *psSyncInt;
1006 PVRSRV_CLIENT_SYNC_PRIM **papsServerSync;
1007 IMG_UINT32 ui32ServerSyncs = 0;
1008 IMG_UINT32 *pui32UID = IMG_NULL;
1009 IMG_UINT32 *pui32FWAddr = IMG_NULL;
1010 IMG_UINT32 *pui32CurrentOp = IMG_NULL;
1011 IMG_UINT32 *pui32NextOp = IMG_NULL;
1013 PVRSRV_ERROR eError = PVRSRV_OK;
1015 papsServerSync = OSAllocMem(ui32SyncCount * sizeof(PVRSRV_CLIENT_SYNC_PRIM *));
1016 if (!papsServerSync)
1018 return PVRSRV_ERROR_OUT_OF_MEMORY;
1021 for (i = 0; i < ui32SyncCount; i++)
1023 psSyncInt = IMG_CONTAINER_OF(papsSync[i], SYNC_PRIM, sCommon);
1024 if (psSyncInt->eType == SYNC_PRIM_TYPE_LOCAL)
1026 PVR_DPF((PVR_DBG_ERROR, "%s: sync=local fw=0x%x curr=0x%04x",
1028 SyncPrimGetFirmwareAddrLocal(psSyncInt),
1029 *psSyncInt->sCommon.pui32LinAddr));
1031 else if (psSyncInt->eType == SYNC_PRIM_TYPE_SERVER)
1033 papsServerSync[ui32ServerSyncs++] = papsSync[i];
1037 PVR_DPF((PVR_DBG_ERROR, "SyncPrimDumpSyncs: Invalid sync type"));
1039 Either the client has given us a bad pointer or there is an
1040 error in this module
1042 eError = PVRSRV_ERROR_INVALID_PARAMS;
1047 if (ui32ServerSyncs > 0)
1049 pui32UID = OSAllocMem(ui32ServerSyncs * sizeof(IMG_UINT32));
1052 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1055 pui32FWAddr = OSAllocMem(ui32ServerSyncs * sizeof(IMG_UINT32));
1058 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1061 pui32CurrentOp = OSAllocMem(ui32ServerSyncs * sizeof(IMG_UINT32));
1062 if (!pui32CurrentOp)
1064 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1067 pui32NextOp = OSAllocMem(ui32ServerSyncs * sizeof(IMG_UINT32));
1070 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1073 eError = SyncPrimServerGetStatus(ui32ServerSyncs, papsServerSync,
1078 if (eError != PVRSRV_OK)
1080 PVR_DPF((PVR_DBG_ERROR, "SyncPrimDumpSyncs: Error querying server sync status (%d)",
1084 for (i = 0; i < ui32ServerSyncs; i++)
1086 PVR_DPF((PVR_DBG_ERROR, "%s: sync=server fw=0x%x curr=0x%04x next=0x%04x id=%u%s",
1092 (pui32NextOp[i] - pui32CurrentOp[i] == 1) ? " *" :
1093 (pui32NextOp[i] - pui32CurrentOp[i] > 1) ? " **" :
1099 OSFreeMem(papsServerSync);
1102 OSFreeMem(pui32UID);
1106 OSFreeMem(pui32FWAddr);
1110 OSFreeMem(pui32CurrentOp);
1114 OSFreeMem(pui32NextOp);
1118 PVR_UNREFERENCED_PARAMETER(ui32SyncCount);
1119 PVR_UNREFERENCED_PARAMETER(papsSync);
1120 PVR_UNREFERENCED_PARAMETER(pcszExtraInfo);
1127 PVRSRV_ERROR SyncPrimOpCreate(IMG_UINT32 ui32SyncCount,
1128 PVRSRV_CLIENT_SYNC_PRIM **papsSyncPrim,
1129 PSYNC_OP_COOKIE *ppsCookie)
1131 SYNC_OP_COOKIE *psNewCookie;
1132 SYNC_BLOCK_LIST *psSyncBlockList;
1133 IMG_UINT32 ui32ServerSyncCount = 0;
1134 IMG_UINT32 ui32ClientSyncCount = 0;
1135 IMG_UINT32 ui32ServerAllocSize;
1136 IMG_UINT32 ui32ClientAllocSize;
1137 IMG_UINT32 ui32TotalAllocSize;
1138 IMG_UINT32 ui32ServerIndex = 0;
1139 IMG_UINT32 ui32ClientIndex = 0;
1141 IMG_UINT32 ui32SyncBlockCount;
1143 IMG_HANDLE *pahHandleList;
1145 PVRSRV_ERROR eError;
1147 psSyncBlockList = _SyncPrimBlockListCreate();
1149 if (!psSyncBlockList)
1151 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1155 for (i=0;i<ui32SyncCount;i++)
1157 if (SyncPrimIsServerSync(papsSyncPrim[i]))
1159 ui32ServerSyncCount++;
1163 SYNC_PRIM *psSync = (SYNC_PRIM *) papsSyncPrim[i];
1165 ui32ClientSyncCount++;
1166 eError = _SyncPrimBlockListAdd(psSyncBlockList, psSync->u.sLocal.psSyncBlock);
1167 if (eError != PVRSRV_OK)
1174 ui32ServerAllocSize = ui32ServerSyncCount * (sizeof(IMG_HANDLE) + sizeof(IMG_UINT32));
1175 ui32ClientAllocSize = ui32ClientSyncCount * (5 * sizeof(IMG_UINT32));
1176 ui32TotalAllocSize = sizeof(SYNC_OP_COOKIE) +
1177 (sizeof(PVRSRV_CLIENT_SYNC_PRIM *) * ui32SyncCount) +
1178 ui32ServerAllocSize +
1179 ui32ClientAllocSize;
1181 psNewCookie = OSAllocMem(ui32TotalAllocSize);
1182 pcPtr = (IMG_CHAR *) psNewCookie;
1186 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1190 /* Setup the pointers */
1191 pcPtr += sizeof(SYNC_OP_COOKIE);
1192 psNewCookie->papsSyncPrim = (PVRSRV_CLIENT_SYNC_PRIM **) pcPtr;
1194 pcPtr += sizeof(PVRSRV_CLIENT_SYNC_PRIM *) * ui32SyncCount;
1195 psNewCookie->paui32SyncBlockIndex = (IMG_UINT32 *) pcPtr;
1197 pcPtr += sizeof(IMG_UINT32) * ui32ClientSyncCount;
1198 psNewCookie->paui32Index = (IMG_UINT32 *) pcPtr;
1200 pcPtr += sizeof(IMG_UINT32) * ui32ClientSyncCount;
1201 psNewCookie->paui32Flags = (IMG_UINT32 *) pcPtr;
1203 pcPtr += sizeof(IMG_UINT32) * ui32ClientSyncCount;
1204 psNewCookie->paui32FenceValue = (IMG_UINT32 *) pcPtr;
1206 pcPtr += sizeof(IMG_UINT32) * ui32ClientSyncCount;
1207 psNewCookie->paui32UpdateValue = (IMG_UINT32 *) pcPtr;
1209 pcPtr += sizeof(IMG_UINT32) * ui32ClientSyncCount;
1210 psNewCookie->pahServerSync =(IMG_HANDLE *) pcPtr;
1211 pcPtr += sizeof(IMG_HANDLE) * ui32ServerSyncCount;
1213 psNewCookie->paui32ServerFlags =(IMG_UINT32 *) pcPtr;
1214 pcPtr += sizeof(IMG_UINT32) * ui32ServerSyncCount;
1216 /* Check the pointer setup went ok */
1217 if (!(pcPtr == (((IMG_CHAR *) psNewCookie) + ui32TotalAllocSize)))
1219 PVR_DPF((PVR_DBG_ERROR, "%s: cookie setup failed", __FUNCTION__));
1220 eError = PVRSRV_ERROR_INTERNAL_ERROR;
1224 psNewCookie->ui32SyncCount = ui32SyncCount;
1225 psNewCookie->ui32ServerSyncCount = ui32ServerSyncCount;
1226 psNewCookie->ui32ClientSyncCount = ui32ClientSyncCount;
1227 psNewCookie->psSyncBlockList = psSyncBlockList;
1230 Get the bridge handle from the 1st sync.
1232 Note: We assume the all syncs have been created with the same
1233 services connection.
1235 if (SyncPrimIsServerSync(papsSyncPrim[0]))
1237 SYNC_PRIM *psSync = (SYNC_PRIM *) papsSyncPrim[0];
1239 hBridge = psSync->u.sServer.hBridge;
1243 SYNC_PRIM *psSync = (SYNC_PRIM *) papsSyncPrim[0];
1245 hBridge = psSync->u.sLocal.psSyncBlock->psContext->hBridge;
1248 psNewCookie->hBridge = hBridge;
1250 if (ui32ServerSyncCount)
1252 psNewCookie->bHaveServerSync = IMG_TRUE;
1256 psNewCookie->bHaveServerSync = IMG_FALSE;
1259 /* Fill in the server and client sync data */
1260 for (i=0;i<ui32SyncCount;i++)
1262 SYNC_PRIM *psSync = (SYNC_PRIM *) papsSyncPrim[i];
1264 if (SyncPrimIsServerSync(papsSyncPrim[i]))
1266 psNewCookie->pahServerSync[ui32ServerIndex] = psSync->u.sServer.hServerSync;
1272 /* Location of sync */
1273 eError = _SyncPrimBlockListBlockToIndex(psSyncBlockList,
1274 psSync->u.sLocal.psSyncBlock,
1275 &psNewCookie->paui32SyncBlockIndex[ui32ClientIndex]);
1276 if (eError != PVRSRV_OK)
1281 /* Workout the index to sync */
1282 psNewCookie->paui32Index[ui32ClientIndex] =
1283 SyncPrimGetOffset(psSync)/sizeof(IMG_UINT32);
1288 psNewCookie->papsSyncPrim[i] = papsSyncPrim[i];
1291 eError = _SyncPrimBlockListHandleArrayCreate(psSyncBlockList,
1292 &ui32SyncBlockCount,
1294 if (eError !=PVRSRV_OK)
1300 Create the server side cookie. Here we pass in all the unchanging
1301 data so we only need to pass in the minimum at takeop time
1303 eError = BridgeSyncPrimOpCreate(hBridge,
1306 psNewCookie->ui32ClientSyncCount,
1307 psNewCookie->paui32SyncBlockIndex,
1308 psNewCookie->paui32Index,
1309 psNewCookie->ui32ServerSyncCount,
1310 psNewCookie->pahServerSync,
1311 &psNewCookie->hServerCookie);
1313 /* Free the handle list regardless of error */
1314 _SyncPrimBlockListHandleArrayDestroy(pahHandleList);
1316 if (eError != PVRSRV_OK)
1321 /* Increase the reference count on all referenced local sync prims
1322 * so that they cannot be freed until this Op is finished with
1324 for (i=0;i<ui32SyncCount;i++)
1326 SYNC_PRIM *psSyncInt;
1327 psSyncInt = IMG_CONTAINER_OF(papsSyncPrim[i], SYNC_PRIM, sCommon);
1328 if (SYNC_PRIM_TYPE_LOCAL == psSyncInt->eType)
1330 SyncPrimLocalRef(psSyncInt);
1334 *ppsCookie = psNewCookie;
1338 OSFreeMem(psNewCookie);
1340 _SyncPrimBlockListDestroy(psSyncBlockList);
1346 PVRSRV_ERROR SyncPrimOpTake(PSYNC_OP_COOKIE psCookie,
1347 IMG_UINT32 ui32SyncCount,
1348 PVRSRV_CLIENT_SYNC_PRIM_OP *pasSyncOp)
1350 PVRSRV_ERROR eError;
1351 IMG_UINT32 ui32ServerIndex = 0;
1352 IMG_UINT32 ui32ClientIndex = 0;
1355 /* Copy client sync operations */
1356 for (i=0;i<ui32SyncCount;i++)
1359 Sanity check the client passes in the same syncs as the
1360 ones we got at create time
1362 if (psCookie->papsSyncPrim[i] != pasSyncOp[i].psSync)
1364 return PVRSRV_ERROR_INVALID_PARAMS;
1367 if (SyncPrimIsServerSync(pasSyncOp[i].psSync))
1369 psCookie->paui32ServerFlags[ui32ServerIndex] =
1370 pasSyncOp[i].ui32Flags;
1376 /* Client operation information */
1377 psCookie->paui32Flags[ui32ClientIndex] =
1378 pasSyncOp[i].ui32Flags;
1379 psCookie->paui32FenceValue[ui32ClientIndex] =
1380 pasSyncOp[i].ui32FenceValue;
1381 psCookie->paui32UpdateValue[ui32ClientIndex] =
1382 pasSyncOp[i].ui32UpdateValue;
1388 eError = BridgeSyncPrimOpTake(psCookie->hBridge,
1389 psCookie->hServerCookie,
1390 psCookie->ui32ClientSyncCount,
1391 psCookie->paui32Flags,
1392 psCookie->paui32FenceValue,
1393 psCookie->paui32UpdateValue,
1394 psCookie->ui32ServerSyncCount,
1395 psCookie->paui32ServerFlags);
1401 PVRSRV_ERROR SyncPrimOpReady(PSYNC_OP_COOKIE psCookie,
1404 PVRSRV_ERROR eError;
1407 PVR_DPF((PVR_DBG_ERROR, "%s: invalid input pointer", __FUNCTION__));
1408 eError = PVRSRV_ERROR_INVALID_PARAMS;
1413 If we have a server sync we have no choice
1414 but to do the check in the server
1416 if (psCookie->bHaveServerSync)
1418 eError = BridgeSyncPrimOpReady(psCookie->hBridge,
1419 psCookie->hServerCookie,
1421 if (eError != PVRSRV_OK)
1423 PVR_DPF((PVR_DBG_ERROR,
1424 "%s: Failed to do sync check in server (Error = %d)",
1425 __FUNCTION__, eError));
1432 IMG_UINT32 ui32SnapShot;
1433 IMG_BOOL bReady = IMG_TRUE;
1435 for (i=0;i<psCookie->ui32ClientSyncCount;i++)
1437 if ((psCookie->paui32Flags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK) == 0)
1442 ui32SnapShot = _SyncPrimBlockListGetClientValue(psCookie->psSyncBlockList,
1443 psCookie->paui32SyncBlockIndex[i],
1444 psCookie->paui32Index[i]);
1445 if (ui32SnapShot != psCookie->paui32FenceValue[i])
1461 PVRSRV_ERROR SyncPrimOpComplete(PSYNC_OP_COOKIE psCookie)
1463 PVRSRV_ERROR eError;
1465 eError = BridgeSyncPrimOpComplete(psCookie->hBridge,
1466 psCookie->hServerCookie);
1472 IMG_VOID SyncPrimOpDestroy(PSYNC_OP_COOKIE psCookie)
1474 PVRSRV_ERROR eError;
1477 /* Decrease the reference count on all referenced local sync prims
1478 * so that they can be freed now this Op is finished with
1480 for (i=0;i<psCookie->ui32SyncCount;i++)
1482 SYNC_PRIM *psSyncInt;
1483 psSyncInt = IMG_CONTAINER_OF(psCookie->papsSyncPrim[i], SYNC_PRIM, sCommon);
1484 if (SYNC_PRIM_TYPE_LOCAL == psSyncInt->eType)
1486 SyncPrimLocalUnref(psSyncInt);
1490 eError = BridgeSyncPrimOpDestroy(psCookie->hBridge, psCookie->hServerCookie);
1491 if (PVRSRV_OK != eError)
1493 PVR_DPF((PVR_DBG_ERROR,
1494 "%s: Failed to destroy SyncPrimOp (Error = %d)",
1495 __FUNCTION__, eError));
1498 _SyncPrimBlockListDestroy(psCookie->psSyncBlockList);
1499 OSFreeMem(psCookie);
1503 PVRSRV_ERROR SyncPrimOpResolve(PSYNC_OP_COOKIE psCookie,
1504 IMG_UINT32 *pui32SyncCount,
1505 PVRSRV_CLIENT_SYNC_PRIM_OP **ppsSyncOp)
1507 IMG_UINT32 ui32ServerIndex = 0;
1508 IMG_UINT32 ui32ClientIndex = 0;
1509 PVRSRV_CLIENT_SYNC_PRIM_OP *psSyncOps;
1512 psSyncOps = OSAllocMem(sizeof(PVRSRV_CLIENT_SYNC_PRIM_OP) *
1513 psCookie->ui32SyncCount);
1516 return PVRSRV_ERROR_OUT_OF_MEMORY;
1519 for (i=0; i<psCookie->ui32SyncCount; i++)
1521 psSyncOps[i].psSync = psCookie->papsSyncPrim[i];
1522 if (SyncPrimIsServerSync(psCookie->papsSyncPrim[i]))
1524 psSyncOps[i].ui32FenceValue = 0;
1525 psSyncOps[i].ui32UpdateValue = 0;
1526 psSyncOps[i].ui32Flags = psCookie->paui32ServerFlags[ui32ServerIndex];
1531 psSyncOps[i].ui32FenceValue = psCookie->paui32FenceValue[ui32ClientIndex];
1532 psSyncOps[i].ui32UpdateValue = psCookie->paui32UpdateValue[ui32ClientIndex];
1533 psSyncOps[i].ui32Flags = psCookie->paui32Flags[ui32ClientIndex];
1538 *ppsSyncOp = psSyncOps;
1539 *pui32SyncCount = psCookie->ui32SyncCount;
1544 #if !defined(__KERNEL__)
1546 PVRSRV_ERROR SyncPrimServerAlloc(SYNC_BRIDGE_HANDLE hBridge,
1547 IMG_HANDLE hDeviceNode,
1548 PVRSRV_CLIENT_SYNC_PRIM **ppsSync,
1549 const IMG_CHAR *pszClassName
1550 PVR_DBG_FILELINE_PARAM)
1552 IMG_CHAR szClassName[SYNC_MAX_CLASS_NAME_LEN];
1553 SYNC_PRIM *psNewSync;
1554 PVRSRV_ERROR eError;
1556 #if !defined(PVR_SYNC_PRIM_ALLOC_TRACE)
1557 PVR_DBG_FILELINE_UNREF();
1559 psNewSync = OSAllocMem(sizeof(SYNC_PRIM));
1560 if (psNewSync == IMG_NULL)
1562 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1565 OSCachedMemSet(psNewSync, 0, sizeof(SYNC_PRIM));
1569 /* Copy the class name annotation into a fixed-size array */
1570 OSStringNCopy(szClassName, pszClassName, SYNC_MAX_CLASS_NAME_LEN - 1);
1571 szClassName[SYNC_MAX_CLASS_NAME_LEN - 1] = 0;
1575 /* No class name annotation */
1579 eError = BridgeServerSyncAlloc(hBridge,
1581 &psNewSync->u.sServer.hServerSync,
1582 &psNewSync->u.sServer.ui32FirmwareAddr,
1583 OSStringNLength(szClassName, SYNC_MAX_CLASS_NAME_LEN),
1586 if (eError != PVRSRV_OK)
1591 #if defined(PVR_SYNC_PRIM_ALLOC_TRACE)
1592 PVR_DPF((PVR_DBG_WARNING, "Allocated sync=server fw=0x%x [%p]" PVR_DBG_FILELINE_FMT,
1593 psNewSync->u.sServer.ui32FirmwareAddr, &psNewSync->sCommon PVR_DBG_FILELINE_ARG));
1596 psNewSync->eType = SYNC_PRIM_TYPE_SERVER;
1597 psNewSync->u.sServer.hBridge = hBridge;
1598 *ppsSync = &psNewSync->sCommon;
1602 OSFreeMem(psNewSync);
1608 PVRSRV_ERROR SyncPrimServerGetStatus(IMG_UINT32 ui32SyncCount,
1609 PVRSRV_CLIENT_SYNC_PRIM **papsSync,
1610 IMG_UINT32 *pui32UID,
1611 IMG_UINT32 *pui32FWAddr,
1612 IMG_UINT32 *pui32CurrentOp,
1613 IMG_UINT32 *pui32NextOp)
1615 PVRSRV_ERROR eError;
1617 SYNC_BRIDGE_HANDLE hBridge = NULL;
1618 IMG_HANDLE *pahServerHandle;
1622 hBridge = _SyncPrimGetBridgeHandle(papsSync[0]);
1626 PVR_DPF((PVR_DBG_ERROR, "%s: invalid Sync connection\n", __FUNCTION__));
1627 eError = PVRSRV_ERROR_INVALID_SYNC_PRIM;
1631 pahServerHandle = OSAllocMem(sizeof(IMG_HANDLE) * ui32SyncCount);
1632 if (pahServerHandle == IMG_NULL)
1634 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1639 Check that all the sync we've been passed are server syncs
1640 and that they all are on the same connection.
1642 for (i=0;i<ui32SyncCount;i++)
1644 SYNC_PRIM *psIntSync = IMG_CONTAINER_OF(papsSync[i], SYNC_PRIM, sCommon);
1646 if (!SyncPrimIsServerSync(papsSync[i]))
1648 eError = PVRSRV_ERROR_INVALID_SYNC_PRIM;
1652 if (!papsSync[i] || hBridge != _SyncPrimGetBridgeHandle(papsSync[i]))
1654 PVR_DPF((PVR_DBG_ERROR, "SyncServerGetStatus: Sync connection is different\n"));
1655 eError = PVRSRV_ERROR_INVALID_SYNC_PRIM;
1659 pahServerHandle[i] = psIntSync->u.sServer.hServerSync;
1662 eError = BridgeServerSyncGetStatus(hBridge,
1669 OSFreeMem(pahServerHandle);
1671 if (eError != PVRSRV_OK)
1678 OSFreeMem(pahServerHandle);
1686 IMG_BOOL SyncPrimIsServerSync(PVRSRV_CLIENT_SYNC_PRIM *psSync)
1688 SYNC_PRIM *psSyncInt;
1692 PVR_DPF((PVR_DBG_ERROR, "%s: invalid input pointer", __FUNCTION__));
1695 psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
1696 if (psSyncInt->eType == SYNC_PRIM_TYPE_SERVER)
1706 IMG_HANDLE SyncPrimGetServerHandle(PVRSRV_CLIENT_SYNC_PRIM *psSync)
1708 SYNC_PRIM *psSyncInt;
1712 PVR_DPF((PVR_DBG_ERROR, "%s: invalid input pointer", __FUNCTION__));
1715 psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
1716 if (psSyncInt->eType == SYNC_PRIM_TYPE_SERVER)
1718 return psSyncInt->u.sServer.hServerSync;
1722 PVR_DPF((PVR_DBG_ERROR, "%s: invalid sync type (%d)",
1723 __FUNCTION__, psSyncInt->eType));
1731 PVRSRV_ERROR SyncPrimServerQueueOp(PVRSRV_CLIENT_SYNC_PRIM_OP *psSyncOp)
1733 SYNC_PRIM *psSyncInt;
1735 PVRSRV_ERROR eError;
1739 PVR_DPF((PVR_DBG_ERROR, "%s: invalid input pointer", __FUNCTION__));
1740 eError = PVRSRV_ERROR_INVALID_PARAMS;
1744 psSyncInt = IMG_CONTAINER_OF(psSyncOp->psSync, SYNC_PRIM, sCommon);
1745 if (psSyncInt->eType != SYNC_PRIM_TYPE_SERVER)
1747 PVR_DPF((PVR_DBG_ERROR, "%s: invalid sync type (%d)",
1748 __FUNCTION__, psSyncInt->eType));
1749 eError = PVRSRV_ERROR_INVALID_SYNC_PRIM;
1752 if (0 == psSyncOp->ui32Flags)
1754 PVR_DPF((PVR_DBG_ERROR, "%s: no sync flags", __FUNCTION__));
1755 eError = PVRSRV_ERROR_INVALID_SYNC_PRIM;
1759 if (psSyncOp->ui32Flags & PVRSRV_CLIENT_SYNC_PRIM_OP_UPDATE)
1764 bUpdate = IMG_FALSE;
1767 eError = BridgeServerSyncQueueHWOp(psSyncInt->u.sServer.hBridge,
1768 psSyncInt->u.sServer.hServerSync,
1770 &psSyncOp->ui32FenceValue,
1771 &psSyncOp->ui32UpdateValue);
1777 IMG_INTERNAL IMG_VOID SyncPrimPDump(PVRSRV_CLIENT_SYNC_PRIM *psSync)
1779 SYNC_PRIM *psSyncInt;
1780 SYNC_PRIM_BLOCK *psSyncBlock;
1781 SYNC_PRIM_CONTEXT *psContext;
1782 PVRSRV_ERROR eError;
1784 PVR_ASSERT(psSync != IMG_NULL);
1785 psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
1787 if (psSyncInt->eType != SYNC_PRIM_TYPE_LOCAL)
1789 PVR_DPF((PVR_DBG_ERROR, "SyncPrimPDump: Invalid sync type"));
1790 PVR_ASSERT(IMG_FALSE);
1794 psSyncBlock = psSyncInt->u.sLocal.psSyncBlock;
1795 psContext = psSyncBlock->psContext;
1797 eError = BridgeSyncPrimPDump(psContext->hBridge,
1798 psSyncBlock->hServerSyncPrimBlock,
1799 SyncPrimGetOffset(psSyncInt));
1801 if (eError != PVRSRV_OK)
1803 PVR_DPF((PVR_DBG_ERROR,
1804 "%s: failed with error %d",
1805 __FUNCTION__, eError));
1807 PVR_ASSERT(eError == PVRSRV_OK);
1810 IMG_INTERNAL IMG_VOID SyncPrimPDumpValue(PVRSRV_CLIENT_SYNC_PRIM *psSync, IMG_UINT32 ui32Value)
1812 SYNC_PRIM *psSyncInt;
1813 SYNC_PRIM_BLOCK *psSyncBlock;
1814 SYNC_PRIM_CONTEXT *psContext;
1815 PVRSRV_ERROR eError;
1817 PVR_ASSERT(psSync != IMG_NULL);
1818 psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
1820 if (psSyncInt->eType != SYNC_PRIM_TYPE_LOCAL)
1822 PVR_DPF((PVR_DBG_ERROR, "SyncPrimPDump: Invalid sync type"));
1823 PVR_ASSERT(IMG_FALSE);
1827 psSyncBlock = psSyncInt->u.sLocal.psSyncBlock;
1828 psContext = psSyncBlock->psContext;
1830 eError = BridgeSyncPrimPDumpValue(psContext->hBridge,
1831 psSyncBlock->hServerSyncPrimBlock,
1832 SyncPrimGetOffset(psSyncInt),
1835 if (eError != PVRSRV_OK)
1837 PVR_DPF((PVR_DBG_ERROR,
1838 "%s: failed with error %d",
1839 __FUNCTION__, eError));
1841 PVR_ASSERT(eError == PVRSRV_OK);
1844 IMG_INTERNAL IMG_VOID SyncPrimPDumpPol(PVRSRV_CLIENT_SYNC_PRIM *psSync,
1845 IMG_UINT32 ui32Value,
1846 IMG_UINT32 ui32Mask,
1847 PDUMP_POLL_OPERATOR eOperator,
1848 IMG_UINT32 ui32PDumpFlags)
1850 SYNC_PRIM *psSyncInt;
1851 SYNC_PRIM_BLOCK *psSyncBlock;
1852 SYNC_PRIM_CONTEXT *psContext;
1853 PVRSRV_ERROR eError;
1855 PVR_ASSERT(psSync != IMG_NULL);
1856 psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
1858 if (psSyncInt->eType != SYNC_PRIM_TYPE_LOCAL)
1860 PVR_DPF((PVR_DBG_ERROR, "SyncPrimPDumpPol: Invalid sync type (expected SYNC_PRIM_TYPE_LOCAL)"));
1861 PVR_ASSERT(IMG_FALSE);
1865 psSyncBlock = psSyncInt->u.sLocal.psSyncBlock;
1866 psContext = psSyncBlock->psContext;
1868 eError = BridgeSyncPrimPDumpPol(psContext->hBridge,
1869 psSyncBlock->hServerSyncPrimBlock,
1870 SyncPrimGetOffset(psSyncInt),
1876 if (eError != PVRSRV_OK)
1878 PVR_DPF((PVR_DBG_ERROR,
1879 "%s: failed with error %d",
1880 __FUNCTION__, eError));
1882 PVR_ASSERT(eError == PVRSRV_OK);
1885 IMG_INTERNAL IMG_VOID SyncPrimOpPDumpPol(PSYNC_OP_COOKIE psCookie,
1886 PDUMP_POLL_OPERATOR eOperator,
1887 IMG_UINT32 ui32PDumpFlags)
1889 PVRSRV_ERROR eError;
1891 PVR_ASSERT(psCookie != IMG_NULL);
1893 eError = BridgeSyncPrimOpPDumpPol(psCookie->hBridge,
1894 psCookie->hServerCookie,
1898 if (eError != PVRSRV_OK)
1900 PVR_DPF((PVR_DBG_ERROR,
1901 "%s: failed with error %d",
1902 __FUNCTION__, eError));
1905 PVR_ASSERT(eError == PVRSRV_OK);
1908 IMG_INTERNAL IMG_VOID SyncPrimPDumpCBP(PVRSRV_CLIENT_SYNC_PRIM *psSync,
1909 IMG_UINT64 uiWriteOffset,
1910 IMG_UINT64 uiPacketSize,
1911 IMG_UINT64 uiBufferSize)
1913 SYNC_PRIM *psSyncInt;
1914 SYNC_PRIM_BLOCK *psSyncBlock;
1915 SYNC_PRIM_CONTEXT *psContext;
1916 PVRSRV_ERROR eError;
1918 PVR_ASSERT(psSync != IMG_NULL);
1919 psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
1921 if (psSyncInt->eType != SYNC_PRIM_TYPE_LOCAL)
1923 PVR_DPF((PVR_DBG_ERROR, "SyncPrimPDumpCBP: Invalid sync type"));
1924 PVR_ASSERT(IMG_FALSE);
1928 psSyncBlock = psSyncInt->u.sLocal.psSyncBlock;
1929 psContext = psSyncBlock->psContext;
1931 /* FIXME: uiWriteOffset, uiPacketSize, uiBufferSize were changed to
1932 * 64-bit quantities to resolve Windows compiler warnings.
1933 * However the bridge is only 32-bit hence compiler warnings
1934 * of implicit cast and loss of data.
1935 * Added explicit cast and assert to remove warning.
1937 #if (defined(_WIN32) && !defined(_WIN64)) || (defined(LINUX) && defined(__i386__))
1938 PVR_ASSERT(uiWriteOffset<IMG_UINT32_MAX);
1939 PVR_ASSERT(uiPacketSize<IMG_UINT32_MAX);
1940 PVR_ASSERT(uiBufferSize<IMG_UINT32_MAX);
1942 eError = BridgeSyncPrimPDumpCBP(psContext->hBridge,
1943 psSyncBlock->hServerSyncPrimBlock,
1944 SyncPrimGetOffset(psSyncInt),
1945 (IMG_UINT32)uiWriteOffset,
1946 (IMG_UINT32)uiPacketSize,
1947 (IMG_UINT32)uiBufferSize);
1949 if (eError != PVRSRV_OK)
1951 PVR_DPF((PVR_DBG_ERROR,
1952 "%s: failed with error %d",
1953 __FUNCTION__, eError));
1955 PVR_ASSERT(eError == PVRSRV_OK);