| /*************************************************************************/ /*! |
| @File |
| @Title Services synchronisation interface |
| @Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved |
| @Description Implements client side code for services synchronisation |
| interface |
| @License Dual MIT/GPLv2 |
| |
| The contents of this file are subject to the MIT license as set out below. |
| |
| Permission is hereby granted, free of charge, to any person obtaining a copy |
| of this software and associated documentation files (the "Software"), to deal |
| in the Software without restriction, including without limitation the rights |
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| copies of the Software, and to permit persons to whom the Software is |
| furnished to do so, subject to the following conditions: |
| |
| The above copyright notice and this permission notice shall be included in |
| all copies or substantial portions of the Software. |
| |
| Alternatively, the contents of this file may be used under the terms of |
| the GNU General Public License Version 2 ("GPL") in which case the provisions |
| of GPL are applicable instead of those above. |
| |
| If you wish to allow use of your version of this file only under the terms of |
| GPL, and not to allow others to use your version of this file under the terms |
| of the MIT license, indicate your decision by deleting the provisions above |
| and replace them with the notice and other provisions required by GPL as set |
| out in the file called "GPL-COPYING" included in this distribution. If you do |
| not delete the provisions above, a recipient may use your version of this file |
| under the terms of either the MIT license or GPL. |
| |
| This License is also included in this distribution in the file called |
| "MIT-COPYING". |
| |
| EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS |
| PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING |
| BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR |
| PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR |
| COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER |
| IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| */ /**************************************************************************/ |
| |
| #include "img_types.h" |
| #include "img_defs.h" |
| #include "client_sync_bridge.h" |
| #include "client_synctracking_bridge.h" |
| #include "info_page_client.h" |
| #include "pvr_bridge.h" |
| #include "allocmem.h" |
| #include "osfunc.h" |
| #include "devicemem.h" |
| #include "devicemem_pdump.h" |
| #include "pvr_debug.h" |
| #include "dllist.h" |
| #include "sync.h" |
| #include "sync_internal.h" |
| #include "lock.h" |
| #include "log2.h" |
| /* FIXME */ |
| #if defined(__KERNEL__) |
| #include "pvrsrv.h" |
| #endif |
| |
| |
| #define SYNC_BLOCK_LIST_CHUNCK_SIZE 10 |
| |
| /* |
| This defines the maximum amount of synchronisation memory |
| that can be allocated per SyncPrim context. |
| In reality this number is meaningless as we would run out |
| of synchronisation memory before we reach this limit, but |
| we need to provide a size to the span RA. |
| */ |
| #define MAX_SYNC_MEM (4 * 1024 * 1024) |
| |
| #if defined(SUPPORT_SERVER_SYNC_IMPL) |
| typedef struct _SYNC_BLOCK_LIST_ |
| { |
| IMG_UINT32 ui32BlockCount; /*!< Number of contexts in the list */ |
| IMG_UINT32 ui32BlockListSize; /*!< Size of the array contexts */ |
| SYNC_PRIM_BLOCK **papsSyncPrimBlock; /*!< Array of syncprim blocks */ |
| } SYNC_BLOCK_LIST; |
| |
| typedef struct _SYNC_OP_COOKIE_ |
| { |
| IMG_UINT32 ui32SyncCount; |
| IMG_UINT32 ui32ClientSyncCount; |
| IMG_UINT32 ui32ServerSyncCount; |
| IMG_BOOL bHaveServerSync; |
| IMG_HANDLE hBridge; |
| IMG_HANDLE hServerCookie; |
| |
| SYNC_BLOCK_LIST *psSyncBlockList; |
| PVRSRV_CLIENT_SYNC_PRIM **papsSyncPrim; |
| /* |
| Client sync(s) info. |
| If this changes update the calculation of ui32ClientAllocSize |
| */ |
| IMG_UINT32 *paui32SyncBlockIndex; |
| IMG_UINT32 *paui32Index; |
| IMG_UINT32 *paui32Flags; |
| IMG_UINT32 *paui32FenceValue; |
| IMG_UINT32 *paui32UpdateValue; |
| |
| /* |
| Server sync(s) info |
| If this changes update the calculation of ui32ServerAllocSize |
| */ |
| IMG_HANDLE *pahServerSync; |
| IMG_UINT32 *paui32ServerFlags; |
| } SYNC_OP_COOKIE; |
| #endif |
| |
| /* forward declaration */ |
| static PVRSRV_ERROR |
| _SyncPrimSetValue(SYNC_PRIM *psSyncInt, IMG_UINT32 ui32Value); |
| |
| /* |
| Internal interfaces for management of SYNC_PRIM_CONTEXT |
| */ |
| static void |
| _SyncPrimContextUnref(SYNC_PRIM_CONTEXT *psContext) |
| { |
| if (!OSAtomicRead(&psContext->hRefCount)) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "_SyncPrimContextUnref context already freed")); |
| } |
| else if (0 == OSAtomicDecrement(&psContext->hRefCount)) |
| { |
| /* SyncPrimContextDestroy only when no longer referenced */ |
| RA_Delete(psContext->psSpanRA); |
| RA_Delete(psContext->psSubAllocRA); |
| OSFreeMem(psContext); |
| } |
| } |
| |
| static void |
| _SyncPrimContextRef(SYNC_PRIM_CONTEXT *psContext) |
| { |
| if (!OSAtomicRead(&psContext->hRefCount)) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "_SyncPrimContextRef context use after free")); |
| } |
| else |
| { |
| OSAtomicIncrement(&psContext->hRefCount); |
| } |
| } |
| |
| /* |
| Internal interfaces for management of synchronisation block memory |
| */ |
| static PVRSRV_ERROR |
| AllocSyncPrimitiveBlock(SYNC_PRIM_CONTEXT *psContext, |
| SYNC_PRIM_BLOCK **ppsSyncBlock) |
| { |
| SYNC_PRIM_BLOCK *psSyncBlk; |
| IMG_HANDLE hSyncPMR; |
| IMG_HANDLE hSyncImportHandle; |
| IMG_DEVMEM_SIZE_T uiImportSize; |
| PVRSRV_ERROR eError; |
| |
| psSyncBlk = OSAllocMem(sizeof(SYNC_PRIM_BLOCK)); |
| if (psSyncBlk == NULL) |
| { |
| eError = PVRSRV_ERROR_OUT_OF_MEMORY; |
| goto fail_alloc; |
| } |
| psSyncBlk->psContext = psContext; |
| |
| /* Allocate sync prim block */ |
| eError = BridgeAllocSyncPrimitiveBlock(GetBridgeHandle(psContext->hDevConnection), |
| &psSyncBlk->hServerSyncPrimBlock, |
| &psSyncBlk->ui32FirmwareAddr, |
| &psSyncBlk->ui32SyncBlockSize, |
| &hSyncPMR); |
| if (eError != PVRSRV_OK) |
| { |
| goto fail_blockalloc; |
| } |
| |
| /* Make it mappable by the client */ |
| eError = DevmemMakeLocalImportHandle(psContext->hDevConnection, |
| hSyncPMR, |
| &hSyncImportHandle); |
| if (eError != PVRSRV_OK) |
| { |
| goto fail_export; |
| } |
| |
| /* Get CPU mapping of the memory block */ |
| eError = DevmemLocalImport(psContext->hDevConnection, |
| hSyncImportHandle, |
| PVRSRV_MEMALLOCFLAG_CPU_READABLE, |
| &psSyncBlk->hMemDesc, |
| &uiImportSize, |
| "SyncPrimitiveBlock"); |
| |
| /* |
| Regardless of success or failure we "undo" the export |
| */ |
| DevmemUnmakeLocalImportHandle(psContext->hDevConnection, |
| hSyncImportHandle); |
| |
| if (eError != PVRSRV_OK) |
| { |
| goto fail_import; |
| } |
| |
| eError = DevmemAcquireCpuVirtAddr(psSyncBlk->hMemDesc, |
| (void **) &psSyncBlk->pui32LinAddr); |
| if (eError != PVRSRV_OK) |
| { |
| goto fail_cpuvaddr; |
| } |
| |
| *ppsSyncBlock = psSyncBlk; |
| return PVRSRV_OK; |
| |
| fail_cpuvaddr: |
| DevmemFree(psSyncBlk->hMemDesc); |
| fail_import: |
| fail_export: |
| BridgeFreeSyncPrimitiveBlock(GetBridgeHandle(psContext->hDevConnection), |
| psSyncBlk->hServerSyncPrimBlock); |
| fail_blockalloc: |
| OSFreeMem(psSyncBlk); |
| fail_alloc: |
| return eError; |
| } |
| |
| static void |
| FreeSyncPrimitiveBlock(SYNC_PRIM_BLOCK *psSyncBlk) |
| { |
| SYNC_PRIM_CONTEXT *psContext = psSyncBlk->psContext; |
| |
| DevmemReleaseCpuVirtAddr(psSyncBlk->hMemDesc); |
| DevmemFree(psSyncBlk->hMemDesc); |
| BridgeFreeSyncPrimitiveBlock(GetBridgeHandle(psContext->hDevConnection), |
| psSyncBlk->hServerSyncPrimBlock); |
| OSFreeMem(psSyncBlk); |
| } |
| |
| static PVRSRV_ERROR |
| SyncPrimBlockImport(RA_PERARENA_HANDLE hArena, |
| RA_LENGTH_T uSize, |
| RA_FLAGS_T uFlags, |
| const IMG_CHAR *pszAnnotation, |
| RA_BASE_T *puiBase, |
| RA_LENGTH_T *puiActualSize, |
| RA_PERISPAN_HANDLE *phImport) |
| { |
| SYNC_PRIM_CONTEXT *psContext = hArena; |
| SYNC_PRIM_BLOCK *psSyncBlock = NULL; |
| RA_LENGTH_T uiSpanSize; |
| PVRSRV_ERROR eError; |
| PVR_UNREFERENCED_PARAMETER(uFlags); |
| |
| /* Check we've not been called with an unexpected size */ |
| if (!hArena || sizeof(IMG_UINT32) != uSize) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "%s: invalid input params", __func__)); |
| eError = PVRSRV_ERROR_INVALID_PARAMS; |
| goto e0; |
| } |
| |
| /* |
| Ensure the synprim context doesn't go away while we have sync blocks |
| attached to it |
| */ |
| _SyncPrimContextRef(psContext); |
| |
| /* Allocate the block of memory */ |
| eError = AllocSyncPrimitiveBlock(psContext, &psSyncBlock); |
| if (eError != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_ERROR, |
| "%s: Failed to allocate syncprim block (%d)", |
| __func__, eError)); |
| goto fail_syncblockalloc; |
| } |
| |
| /* Allocate a span for it */ |
| eError = RA_Alloc(psContext->psSpanRA, |
| psSyncBlock->ui32SyncBlockSize, |
| RA_NO_IMPORT_MULTIPLIER, |
| 0, |
| psSyncBlock->ui32SyncBlockSize, |
| pszAnnotation, |
| &psSyncBlock->uiSpanBase, |
| &uiSpanSize, |
| NULL); |
| if (eError != PVRSRV_OK) |
| { |
| goto fail_spanalloc; |
| } |
| |
| /* |
| There is no reason the span RA should return an allocation larger |
| then we request |
| */ |
| PVR_ASSERT(uiSpanSize == psSyncBlock->ui32SyncBlockSize); |
| |
| *puiBase = psSyncBlock->uiSpanBase; |
| *puiActualSize = psSyncBlock->ui32SyncBlockSize; |
| *phImport = psSyncBlock; |
| return PVRSRV_OK; |
| |
| fail_spanalloc: |
| FreeSyncPrimitiveBlock(psSyncBlock); |
| fail_syncblockalloc: |
| _SyncPrimContextUnref(psContext); |
| e0: |
| return eError; |
| } |
| |
| static void |
| SyncPrimBlockUnimport(RA_PERARENA_HANDLE hArena, |
| RA_BASE_T uiBase, |
| RA_PERISPAN_HANDLE hImport) |
| { |
| SYNC_PRIM_CONTEXT *psContext = hArena; |
| SYNC_PRIM_BLOCK *psSyncBlock = hImport; |
| |
| if (!psContext || !psSyncBlock || uiBase != psSyncBlock->uiSpanBase) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "%s: invalid input params", __func__)); |
| return; |
| } |
| |
| /* Free the span this import is using */ |
| RA_Free(psContext->psSpanRA, uiBase); |
| |
| /* Free the syncpim block */ |
| FreeSyncPrimitiveBlock(psSyncBlock); |
| |
| /* Drop our reference to the syncprim context */ |
| _SyncPrimContextUnref(psContext); |
| } |
| |
| static INLINE IMG_UINT32 SyncPrimGetOffset(SYNC_PRIM *psSyncInt) |
| { |
| IMG_UINT64 ui64Temp; |
| |
| PVR_ASSERT(psSyncInt->eType == SYNC_PRIM_TYPE_LOCAL); |
| |
| /* FIXME: Subtracting a 64-bit address from another and then implicit |
| * cast to 32-bit number. Need to review all call sequences that use this |
| * function, added explicit casting for now. |
| */ |
| ui64Temp = psSyncInt->u.sLocal.uiSpanAddr - psSyncInt->u.sLocal.psSyncBlock->uiSpanBase; |
| PVR_ASSERT(ui64Temp<IMG_UINT32_MAX); |
| return (IMG_UINT32)ui64Temp; |
| } |
| |
| static void SyncPrimGetCPULinAddr(SYNC_PRIM *psSyncInt) |
| { |
| SYNC_PRIM_BLOCK *psSyncBlock = psSyncInt->u.sLocal.psSyncBlock; |
| |
| psSyncInt->sCommon.pui32LinAddr = psSyncBlock->pui32LinAddr + |
| (SyncPrimGetOffset(psSyncInt)/sizeof(IMG_UINT32)); |
| } |
| |
| static void SyncPrimLocalFree(SYNC_PRIM *psSyncInt) |
| { |
| SYNC_PRIM_BLOCK *psSyncBlock; |
| SYNC_PRIM_CONTEXT *psContext; |
| |
| psSyncBlock = psSyncInt->u.sLocal.psSyncBlock; |
| psContext = psSyncBlock->psContext; |
| |
| { |
| PVRSRV_ERROR eError; |
| IMG_HANDLE hBridge = |
| GetBridgeHandle(psSyncInt->u.sLocal.psSyncBlock->psContext->hDevConnection); |
| |
| if (GetInfoPageDebugFlags(psSyncInt->u.sLocal.psSyncBlock->psContext->hDevConnection) & DEBUG_FEATURE_FULL_SYNC_TRACKING_ENABLED) |
| { |
| if (psSyncInt->u.sLocal.hRecord) |
| { |
| /* remove this sync record */ |
| eError = BridgeSyncRecordRemoveByHandle(hBridge, |
| psSyncInt->u.sLocal.hRecord); |
| if (PVRSRV_OK != eError) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "%s: failed to remove SyncRecord", __func__)); |
| } |
| } |
| } |
| else |
| { |
| IMG_UINT32 ui32FWAddr = psSyncBlock->ui32FirmwareAddr + |
| SyncPrimGetOffset(psSyncInt); |
| |
| eError = BridgeSyncFreeEvent(hBridge, ui32FWAddr); |
| if (eError != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_WARNING, |
| "%s: BridgeSyncFreeEvent failed with error: %d", |
| __func__, eError)); |
| } |
| } |
| } |
| #if defined(PVRSRV_ENABLE_SYNC_POISONING) |
| (void) _SyncPrimSetValue(psSyncInt, LOCAL_SYNC_PRIM_POISON_VALUE); |
| #else |
| /* reset the sync prim value as it is freed. |
| * this guarantees the client sync allocated to the client will |
| * have a value of zero and the client does not need to |
| * explicitly initialise the sync value to zero. |
| * the allocation of the backing memory for the sync prim block |
| * is done with ZERO_ON_ALLOC so the memory is initially all zero. |
| */ |
| (void) _SyncPrimSetValue(psSyncInt, LOCAL_SYNC_PRIM_RESET_VALUE); |
| #endif |
| |
| RA_Free(psContext->psSubAllocRA, psSyncInt->u.sLocal.uiSpanAddr); |
| OSFreeMem(psSyncInt); |
| _SyncPrimContextUnref(psContext); |
| } |
| #if defined(SUPPORT_SERVER_SYNC_IMPL) |
| static void SyncPrimServerFree(SYNC_PRIM *psSyncInt) |
| { |
| PVRSRV_ERROR eError; |
| |
| eError = BridgeServerSyncFree(psSyncInt->u.sServer.hBridge, |
| psSyncInt->u.sServer.hServerSync); |
| if (eError != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "SyncPrimServerFree failed")); |
| } |
| OSFreeMem(psSyncInt); |
| } |
| #endif |
| static void SyncPrimLocalUnref(SYNC_PRIM *psSyncInt) |
| { |
| if (!OSAtomicRead(&psSyncInt->u.sLocal.hRefCount)) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "SyncPrimLocalUnref sync already freed")); |
| } |
| else if (0 == OSAtomicDecrement(&psSyncInt->u.sLocal.hRefCount)) |
| { |
| SyncPrimLocalFree(psSyncInt); |
| } |
| } |
| |
| #if defined(SUPPORT_SERVER_SYNC_IMPL) |
| static void SyncPrimLocalRef(SYNC_PRIM *psSyncInt) |
| { |
| if (!OSAtomicRead(&psSyncInt->u.sLocal.hRefCount)) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "SyncPrimLocalRef sync use after free")); |
| } |
| else |
| { |
| OSAtomicIncrement(&psSyncInt->u.sLocal.hRefCount); |
| } |
| } |
| #endif |
| |
| static IMG_UINT32 SyncPrimGetFirmwareAddrLocal(SYNC_PRIM *psSyncInt) |
| { |
| SYNC_PRIM_BLOCK *psSyncBlock; |
| |
| psSyncBlock = psSyncInt->u.sLocal.psSyncBlock; |
| return psSyncBlock->ui32FirmwareAddr + SyncPrimGetOffset(psSyncInt); |
| } |
| #if defined(SUPPORT_SERVER_SYNC_IMPL) |
| static IMG_UINT32 SyncPrimGetFirmwareAddrServer(SYNC_PRIM *psSyncInt) |
| { |
| return psSyncInt->u.sServer.ui32FirmwareAddr; |
| } |
| |
| #if !defined(__KERNEL__) |
| |
| static SYNC_BRIDGE_HANDLE _SyncPrimGetBridgeHandleLocal(SYNC_PRIM *psSyncInt) |
| { |
| return GetBridgeHandle(psSyncInt->u.sLocal.psSyncBlock->psContext->hDevConnection); |
| } |
| |
| static SYNC_BRIDGE_HANDLE _SyncPrimGetBridgeHandleServer(SYNC_PRIM *psSyncInt) |
| { |
| return psSyncInt->u.sServer.hBridge; |
| } |
| |
| static SYNC_BRIDGE_HANDLE _SyncPrimGetBridgeHandle(PVRSRV_CLIENT_SYNC_PRIM *psSync) |
| { |
| SYNC_PRIM *psSyncInt; |
| |
| psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon); |
| if (psSyncInt->eType == SYNC_PRIM_TYPE_LOCAL) |
| { |
| return _SyncPrimGetBridgeHandleLocal(psSyncInt); |
| } |
| else if (psSyncInt->eType == SYNC_PRIM_TYPE_SERVER) |
| { |
| return _SyncPrimGetBridgeHandleServer(psSyncInt); |
| } |
| else |
| { |
| PVR_DPF((PVR_DBG_ERROR, "_SyncPrimGetBridgeHandle: Invalid sync type")); |
| /* |
| Either the client has given us a bad pointer or there is an |
| error in this module |
| */ |
| return 0; |
| } |
| } |
| #endif |
| |
| /* |
| Internal interfaces for management of syncprim block lists |
| */ |
| static SYNC_BLOCK_LIST *_SyncPrimBlockListCreate(void) |
| { |
| SYNC_BLOCK_LIST *psBlockList; |
| |
| psBlockList = OSAllocMem(sizeof(SYNC_BLOCK_LIST)); |
| if (!psBlockList) |
| { |
| return NULL; |
| } |
| |
| psBlockList->ui32BlockCount = 0; |
| psBlockList->ui32BlockListSize = SYNC_BLOCK_LIST_CHUNCK_SIZE; |
| |
| psBlockList->papsSyncPrimBlock = OSAllocZMem(sizeof(SYNC_PRIM_BLOCK *) |
| * SYNC_BLOCK_LIST_CHUNCK_SIZE); |
| if (!psBlockList->papsSyncPrimBlock) |
| { |
| OSFreeMem(psBlockList); |
| return NULL; |
| } |
| |
| return psBlockList; |
| } |
| |
| static PVRSRV_ERROR _SyncPrimBlockListAdd(SYNC_BLOCK_LIST *psBlockList, |
| SYNC_PRIM_BLOCK *psSyncPrimBlock) |
| { |
| IMG_UINT32 i; |
| |
| /* Check the context isn't already on the list */ |
| for (i=0;i<psBlockList->ui32BlockCount;i++) |
| { |
| if (psBlockList->papsSyncPrimBlock[i] == psSyncPrimBlock) |
| { |
| return PVRSRV_OK; |
| } |
| } |
| |
| /* Check we have space for a new item */ |
| if (psBlockList->ui32BlockCount == psBlockList->ui32BlockListSize) |
| { |
| SYNC_PRIM_BLOCK **papsNewSyncPrimBlock; |
| |
| papsNewSyncPrimBlock = OSAllocMem(sizeof(SYNC_PRIM_BLOCK *) * |
| (psBlockList->ui32BlockListSize + |
| SYNC_BLOCK_LIST_CHUNCK_SIZE)); |
| if (!papsNewSyncPrimBlock) |
| { |
| return PVRSRV_ERROR_OUT_OF_MEMORY; |
| } |
| |
| OSCachedMemCopy(papsNewSyncPrimBlock, |
| psBlockList->papsSyncPrimBlock, |
| sizeof(SYNC_PRIM_CONTEXT *) * |
| psBlockList->ui32BlockListSize); |
| |
| OSFreeMem(psBlockList->papsSyncPrimBlock); |
| |
| psBlockList->papsSyncPrimBlock = papsNewSyncPrimBlock; |
| psBlockList->ui32BlockListSize += SYNC_BLOCK_LIST_CHUNCK_SIZE; |
| } |
| |
| /* Add the context to the list */ |
| psBlockList->papsSyncPrimBlock[psBlockList->ui32BlockCount++] = psSyncPrimBlock; |
| return PVRSRV_OK; |
| } |
| |
| static PVRSRV_ERROR _SyncPrimBlockListBlockToIndex(SYNC_BLOCK_LIST *psBlockList, |
| SYNC_PRIM_BLOCK *psSyncPrimBlock, |
| IMG_UINT32 *pui32Index) |
| { |
| IMG_UINT32 i; |
| |
| for (i=0;i<psBlockList->ui32BlockCount;i++) |
| { |
| if (psBlockList->papsSyncPrimBlock[i] == psSyncPrimBlock) |
| { |
| *pui32Index = i; |
| return PVRSRV_OK; |
| } |
| } |
| |
| return PVRSRV_ERROR_INVALID_PARAMS; |
| } |
| |
| static PVRSRV_ERROR _SyncPrimBlockListHandleArrayCreate(SYNC_BLOCK_LIST *psBlockList, |
| IMG_UINT32 *pui32BlockHandleCount, |
| IMG_HANDLE **ppahHandleList) |
| { |
| IMG_HANDLE *pahHandleList; |
| IMG_UINT32 i; |
| |
| pahHandleList = OSAllocMem(sizeof(IMG_HANDLE) * |
| psBlockList->ui32BlockCount); |
| if (!pahHandleList) |
| { |
| return PVRSRV_ERROR_OUT_OF_MEMORY; |
| } |
| |
| for (i=0;i<psBlockList->ui32BlockCount;i++) |
| { |
| pahHandleList[i] = psBlockList->papsSyncPrimBlock[i]->hServerSyncPrimBlock; |
| } |
| |
| *ppahHandleList = pahHandleList; |
| *pui32BlockHandleCount = psBlockList->ui32BlockCount; |
| |
| return PVRSRV_OK; |
| } |
| |
| static void _SyncPrimBlockListHandleArrayDestroy(IMG_HANDLE *pahHandleList) |
| { |
| OSFreeMem(pahHandleList); |
| } |
| |
| static IMG_UINT32 _SyncPrimBlockListGetClientValue(SYNC_BLOCK_LIST *psBlockList, |
| IMG_UINT32 ui32BlockIndex, |
| IMG_UINT32 ui32Index) |
| { |
| return *((IMG_UINT32 __force *)(psBlockList->papsSyncPrimBlock[ui32BlockIndex]->pui32LinAddr)+ui32Index); |
| } |
| |
| static void _SyncPrimBlockListDestroy(SYNC_BLOCK_LIST *psBlockList) |
| { |
| OSFreeMem(psBlockList->papsSyncPrimBlock); |
| OSFreeMem(psBlockList); |
| } |
| #endif |
| |
| static INLINE IMG_UINT32 _Log2(IMG_UINT32 ui32Align) |
| { |
| PVR_ASSERT(IsPower2(ui32Align)); |
| return ExactLog2(ui32Align); |
| } |
| |
| /* |
| External interfaces |
| */ |
| |
| IMG_INTERNAL PVRSRV_ERROR |
| SyncPrimContextCreate(SHARED_DEV_CONNECTION hDevConnection, |
| PSYNC_PRIM_CONTEXT *phSyncPrimContext) |
| { |
| SYNC_PRIM_CONTEXT *psContext; |
| PVRSRV_ERROR eError; |
| |
| psContext = OSAllocMem(sizeof(SYNC_PRIM_CONTEXT)); |
| if (psContext == NULL) |
| { |
| eError = PVRSRV_ERROR_OUT_OF_MEMORY; |
| goto fail_alloc; |
| } |
| |
| psContext->hDevConnection = hDevConnection; |
| |
| OSSNPrintf(psContext->azName, SYNC_PRIM_NAME_SIZE, "Sync Prim RA-%p", psContext); |
| OSSNPrintf(psContext->azSpanName, SYNC_PRIM_NAME_SIZE, "Sync Prim span RA-%p", psContext); |
| |
| /* |
| Create the RA for sub-allocations of the SynPrim's |
| |
| Note: |
| The import size doesn't matter here as the server will pass |
| back the blocksize when does the import which overrides |
| what we specify here. |
| */ |
| |
| psContext->psSubAllocRA = RA_Create(psContext->azName, |
| /* Params for imports */ |
| _Log2(sizeof(IMG_UINT32)), |
| RA_LOCKCLASS_2, |
| SyncPrimBlockImport, |
| SyncPrimBlockUnimport, |
| psContext, |
| IMG_FALSE); |
| if (psContext->psSubAllocRA == NULL) |
| { |
| eError = PVRSRV_ERROR_OUT_OF_MEMORY; |
| goto fail_suballoc; |
| } |
| |
| /* |
| Create the span-management RA |
| |
| The RA requires that we work with linear spans. For our use |
| here we don't require this behaviour as we're always working |
| within offsets of blocks (imports). However, we need to keep |
| the RA happy so we create the "span" management RA which |
| ensures that all are imports are added to the RA in a linear |
| fashion |
| */ |
| psContext->psSpanRA = RA_Create(psContext->azSpanName, |
| /* Params for imports */ |
| 0, |
| RA_LOCKCLASS_1, |
| NULL, |
| NULL, |
| NULL, |
| IMG_FALSE); |
| if (psContext->psSpanRA == NULL) |
| { |
| eError = PVRSRV_ERROR_OUT_OF_MEMORY; |
| goto fail_span; |
| } |
| |
| if (!RA_Add(psContext->psSpanRA, 0, MAX_SYNC_MEM, 0, NULL)) |
| { |
| RA_Delete(psContext->psSpanRA); |
| eError = PVRSRV_ERROR_OUT_OF_MEMORY; |
| goto fail_span; |
| } |
| |
| OSAtomicWrite(&psContext->hRefCount, 1); |
| |
| *phSyncPrimContext = psContext; |
| return PVRSRV_OK; |
| fail_span: |
| RA_Delete(psContext->psSubAllocRA); |
| fail_suballoc: |
| OSFreeMem(psContext); |
| fail_alloc: |
| return eError; |
| } |
| |
| IMG_INTERNAL void SyncPrimContextDestroy(PSYNC_PRIM_CONTEXT hSyncPrimContext) |
| { |
| SYNC_PRIM_CONTEXT *psContext = hSyncPrimContext; |
| if (1 != OSAtomicRead(&psContext->hRefCount)) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "%s attempted with active references, may be the result of a race", __func__)); |
| } |
| #if defined(PVRSRV_FORCE_UNLOAD_IF_BAD_STATE) |
| #if defined(__KERNEL__) |
| if (PVRSRVGetPVRSRVData()->eServicesState != PVRSRV_SERVICES_STATE_OK) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "%s: Forcing context destruction due to bad driver state", __func__)); |
| OSAtomicWrite(&psContext->hRefCount, 1); |
| } |
| #endif |
| #endif |
| _SyncPrimContextUnref(psContext); |
| } |
| |
| static PVRSRV_ERROR _SyncPrimAlloc(PSYNC_PRIM_CONTEXT hSyncPrimContext, |
| PVRSRV_CLIENT_SYNC_PRIM **ppsSync, |
| const IMG_CHAR *pszClassName, |
| IMG_BOOL bServerSync) |
| { |
| SYNC_PRIM_CONTEXT *psContext = hSyncPrimContext; |
| SYNC_PRIM_BLOCK *psSyncBlock; |
| SYNC_PRIM *psNewSync; |
| PVRSRV_ERROR eError; |
| RA_BASE_T uiSpanAddr; |
| |
| if (!hSyncPrimContext) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "%s: invalid context", __func__)); |
| return PVRSRV_ERROR_INVALID_PARAMS; |
| } |
| |
| psNewSync = OSAllocMem(sizeof(SYNC_PRIM)); |
| if (psNewSync == NULL) |
| { |
| eError = PVRSRV_ERROR_OUT_OF_MEMORY; |
| goto fail_alloc; |
| } |
| |
| eError = RA_Alloc(psContext->psSubAllocRA, |
| sizeof(IMG_UINT32), |
| RA_NO_IMPORT_MULTIPLIER, |
| 0, |
| sizeof(IMG_UINT32), |
| "Sync_Prim", |
| &uiSpanAddr, |
| NULL, |
| (RA_PERISPAN_HANDLE *) &psSyncBlock); |
| if (PVRSRV_OK != eError) |
| { |
| goto fail_raalloc; |
| } |
| psNewSync->eType = SYNC_PRIM_TYPE_LOCAL; |
| OSAtomicWrite(&psNewSync->u.sLocal.hRefCount, 1); |
| psNewSync->u.sLocal.uiSpanAddr = uiSpanAddr; |
| psNewSync->u.sLocal.psSyncBlock = psSyncBlock; |
| SyncPrimGetCPULinAddr(psNewSync); |
| *ppsSync = &psNewSync->sCommon; |
| _SyncPrimContextRef(psContext); |
| #if defined(PVRSRV_ENABLE_SYNC_POISONING) |
| (void) _SyncPrimSetValue(psNewSync, LOCAL_SYNC_PRIM_RESET_VALUE); |
| #endif |
| |
| if (GetInfoPageDebugFlags(psSyncBlock->psContext->hDevConnection) & DEBUG_FEATURE_FULL_SYNC_TRACKING_ENABLED) |
| { |
| IMG_CHAR szClassName[SYNC_MAX_CLASS_NAME_LEN]; |
| size_t uiSize; |
| |
| if (pszClassName) |
| { |
| uiSize = OSStringNLength(pszClassName, SYNC_MAX_CLASS_NAME_LEN); |
| /* Copy the class name annotation into a fixed-size array */ |
| OSCachedMemCopy(szClassName, pszClassName, uiSize); |
| if (uiSize == SYNC_MAX_CLASS_NAME_LEN) |
| szClassName[SYNC_MAX_CLASS_NAME_LEN-1] = '\0'; |
| else |
| szClassName[uiSize++] = '\0'; |
| } |
| else |
| { |
| /* No class name annotation */ |
| uiSize = 0; |
| szClassName[0] = '\0'; |
| } |
| |
| /* record this sync */ |
| eError = BridgeSyncRecordAdd( |
| GetBridgeHandle(psSyncBlock->psContext->hDevConnection), |
| &psNewSync->u.sLocal.hRecord, |
| psSyncBlock->hServerSyncPrimBlock, |
| psSyncBlock->ui32FirmwareAddr, |
| SyncPrimGetOffset(psNewSync), |
| bServerSync, |
| uiSize, |
| szClassName); |
| if (PVRSRV_OK != eError) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "%s: failed to add SyncRecord \"%s\" (%s)", |
| __func__, |
| szClassName, |
| PVRSRVGETERRORSTRING(eError))); |
| psNewSync->u.sLocal.hRecord = NULL; |
| } |
| } |
| else |
| { |
| size_t uiSize; |
| |
| uiSize = OSStringNLength(pszClassName, SYNC_MAX_CLASS_NAME_LEN); |
| |
| if (uiSize < SYNC_MAX_CLASS_NAME_LEN) |
| uiSize++; |
| /* uiSize now reflects size used for pszClassName + NUL byte */ |
| |
| eError = BridgeSyncAllocEvent(GetBridgeHandle(hSyncPrimContext->hDevConnection), |
| bServerSync, |
| psSyncBlock->ui32FirmwareAddr + SyncPrimGetOffset(psNewSync), |
| uiSize, |
| pszClassName); |
| if (eError != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_WARNING, |
| "%s: BridgeSyncAllocEvent failed with error: %d", |
| __func__, |
| eError)); |
| } |
| } |
| |
| return PVRSRV_OK; |
| |
| fail_raalloc: |
| OSFreeMem(psNewSync); |
| fail_alloc: |
| return eError; |
| } |
| |
| #if defined(SUPPORT_SERVER_SYNC_IMPL) |
| #if defined(__KERNEL__) |
| IMG_INTERNAL PVRSRV_ERROR SyncPrimAllocForServerSync(PSYNC_PRIM_CONTEXT hSyncPrimContext, |
| PVRSRV_CLIENT_SYNC_PRIM **ppsSync, |
| const IMG_CHAR *pszClassName) |
| { |
| return _SyncPrimAlloc(hSyncPrimContext, |
| ppsSync, |
| pszClassName, |
| IMG_TRUE); |
| } |
| #endif |
| #endif |
| |
| IMG_INTERNAL PVRSRV_ERROR SyncPrimAlloc(PSYNC_PRIM_CONTEXT hSyncPrimContext, |
| PVRSRV_CLIENT_SYNC_PRIM **ppsSync, |
| const IMG_CHAR *pszClassName) |
| { |
| return _SyncPrimAlloc(hSyncPrimContext, |
| ppsSync, |
| pszClassName, |
| IMG_FALSE); |
| } |
| |
| static PVRSRV_ERROR |
| _SyncPrimSetValue(SYNC_PRIM *psSyncInt, IMG_UINT32 ui32Value) |
| { |
| PVRSRV_ERROR eError; |
| |
| if (psSyncInt->eType == SYNC_PRIM_TYPE_LOCAL) |
| { |
| SYNC_PRIM_BLOCK *psSyncBlock; |
| SYNC_PRIM_CONTEXT *psContext; |
| |
| psSyncBlock = psSyncInt->u.sLocal.psSyncBlock; |
| psContext = psSyncBlock->psContext; |
| |
| eError = BridgeSyncPrimSet(GetBridgeHandle(psContext->hDevConnection), |
| psSyncBlock->hServerSyncPrimBlock, |
| SyncPrimGetOffset(psSyncInt)/sizeof(IMG_UINT32), |
| ui32Value); |
| } |
| else |
| { |
| #if defined(SUPPORT_SERVER_SYNC_IMPL) |
| eError = BridgeServerSyncPrimSet(psSyncInt->u.sServer.hBridge, |
| psSyncInt->u.sServer.hServerSync, |
| ui32Value); |
| #else |
| PVR_DPF((PVR_DBG_ERROR, "%s: Server sync not supported, attempted use of server sync", __func__)); |
| return PVRSRV_ERROR_NOT_SUPPORTED; |
| #endif |
| } |
| return eError; |
| } |
| |
| IMG_INTERNAL PVRSRV_ERROR SyncPrimFree(PVRSRV_CLIENT_SYNC_PRIM *psSync) |
| { |
| PVRSRV_ERROR eError = PVRSRV_OK; |
| SYNC_PRIM *psSyncInt; |
| |
| if (!psSync) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "%s: null sync pointer", __func__)); |
| eError = PVRSRV_ERROR_INVALID_PARAMS; |
| goto err_out; |
| } |
| |
| psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon); |
| if (psSyncInt->eType == SYNC_PRIM_TYPE_LOCAL) |
| { |
| SyncPrimLocalUnref(psSyncInt); |
| } |
| else if (psSyncInt->eType == SYNC_PRIM_TYPE_SERVER) |
| { |
| #if defined(SUPPORT_SERVER_SYNC_IMPL) |
| SyncPrimServerFree(psSyncInt); |
| #else |
| PVR_DPF((PVR_DBG_ERROR, "%s: Server sync not supported, attempted use of server sync", __func__)); |
| return PVRSRV_ERROR_NOT_SUPPORTED; |
| #endif |
| } |
| else |
| { |
| /* |
| Either the client has given us a bad pointer or there is an |
| error in this module |
| */ |
| PVR_DPF((PVR_DBG_ERROR, "%s: Invalid sync type", __func__)); |
| eError = PVRSRV_ERROR_INVALID_SYNC_PRIM; |
| goto err_out; |
| } |
| |
| err_out: |
| return eError; |
| } |
| |
| #if defined(NO_HARDWARE) |
| IMG_INTERNAL PVRSRV_ERROR |
| SyncPrimNoHwUpdate(PVRSRV_CLIENT_SYNC_PRIM *psSync, IMG_UINT32 ui32Value) |
| { |
| PVRSRV_ERROR eError = PVRSRV_OK; |
| SYNC_PRIM *psSyncInt; |
| |
| if (!psSync) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "%s: null sync pointer", __func__)); |
| eError = PVRSRV_ERROR_INVALID_PARAMS; |
| goto err_out; |
| } |
| psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon); |
| |
| /* There is no check for the psSyncInt to be LOCAL as this call |
| substitutes the Firmware updating a sync and that sync could |
| be a server one */ |
| |
| eError = _SyncPrimSetValue(psSyncInt, ui32Value); |
| |
| err_out: |
| return eError; |
| } |
| #endif |
| |
| IMG_INTERNAL PVRSRV_ERROR |
| SyncPrimSet(PVRSRV_CLIENT_SYNC_PRIM *psSync, IMG_UINT32 ui32Value) |
| { |
| PVRSRV_ERROR eError = PVRSRV_OK; |
| SYNC_PRIM *psSyncInt; |
| |
| if (!psSync) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "%s: null sync pointer", __func__)); |
| eError = PVRSRV_ERROR_INVALID_PARAMS; |
| goto err_out; |
| } |
| |
| psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon); |
| if (psSyncInt->eType != SYNC_PRIM_TYPE_LOCAL) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "%s: Invalid sync type", __func__)); |
| eError = PVRSRV_ERROR_INVALID_SYNC_PRIM; |
| goto err_out; |
| } |
| |
| eError = _SyncPrimSetValue(psSyncInt, ui32Value); |
| |
| #if defined(PDUMP) |
| SyncPrimPDump(psSync); |
| #endif |
| err_out: |
| return eError; |
| } |
| |
| IMG_INTERNAL PVRSRV_ERROR SyncPrimLocalGetHandleAndOffset(PVRSRV_CLIENT_SYNC_PRIM *psSync, |
| IMG_HANDLE *phBlock, |
| IMG_UINT32 *pui32Offset) |
| { |
| PVRSRV_ERROR eError = PVRSRV_OK; |
| SYNC_PRIM *psSyncInt; |
| |
| if (unlikely(!psSync || !phBlock || !pui32Offset)) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "%s: invalid input pointer", |
| __func__)); |
| eError = PVRSRV_ERROR_INVALID_PARAMS; |
| goto err_out; |
| } |
| |
| psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon); |
| |
| if (likely(psSyncInt->eType == SYNC_PRIM_TYPE_LOCAL)) |
| { |
| *phBlock = psSyncInt->u.sLocal.psSyncBlock->hServerSyncPrimBlock; |
| *pui32Offset = psSyncInt->u.sLocal.uiSpanAddr - psSyncInt->u.sLocal.psSyncBlock->uiSpanBase; |
| } |
| else |
| { |
| PVR_DPF((PVR_DBG_ERROR, "%s: psSync not a Local sync prim (%d)", |
| __func__, psSyncInt->eType)); |
| eError = PVRSRV_ERROR_INVALID_PARAMS; |
| goto err_out; |
| } |
| |
| err_out: |
| return eError; |
| } |
| |
| IMG_INTERNAL PVRSRV_ERROR |
| SyncPrimGetFirmwareAddr(PVRSRV_CLIENT_SYNC_PRIM *psSync, IMG_UINT32 *pui32FwAddr) |
| { |
| PVRSRV_ERROR eError = PVRSRV_OK; |
| SYNC_PRIM *psSyncInt; |
| |
| *pui32FwAddr = 0; |
| if (unlikely(!psSync)) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "%s: invalid input pointer", __func__)); |
| eError = PVRSRV_ERROR_INVALID_PARAMS; |
| goto err_out; |
| } |
| |
| psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon); |
| if (psSyncInt->eType == SYNC_PRIM_TYPE_LOCAL) |
| { |
| *pui32FwAddr = SyncPrimGetFirmwareAddrLocal(psSyncInt); |
| } |
| else if (psSyncInt->eType == SYNC_PRIM_TYPE_SERVER) |
| { |
| #if defined(SUPPORT_SERVER_SYNC_IMPL) |
| *pui32FwAddr = SyncPrimGetFirmwareAddrServer(psSyncInt); |
| #else |
| PVR_DPF((PVR_DBG_ERROR, "%s: Server sync not supported, attempted use of server sync", __func__)); |
| return PVRSRV_ERROR_NOT_SUPPORTED; |
| #endif |
| } |
| else |
| { |
| /* Either the client has given us a bad pointer or there is an |
| * error in this module |
| */ |
| PVR_DPF((PVR_DBG_ERROR, "%s: Invalid sync type", __func__)); |
| eError = PVRSRV_ERROR_INVALID_SYNC_PRIM; |
| goto err_out; |
| } |
| |
| err_out: |
| return eError; |
| } |
| |
| #if defined(SUPPORT_SERVER_SYNC_IMPL) |
| IMG_INTERNAL |
| PVRSRV_ERROR SyncPrimOpCreate(IMG_UINT32 ui32SyncCount, |
| PVRSRV_CLIENT_SYNC_PRIM **papsSyncPrim, |
| PSYNC_OP_COOKIE *ppsCookie) |
| { |
| SYNC_OP_COOKIE *psNewCookie; |
| SYNC_BLOCK_LIST *psSyncBlockList; |
| IMG_UINT32 ui32ServerSyncCount = 0; |
| IMG_UINT32 ui32ClientSyncCount = 0; |
| IMG_UINT32 ui32ServerAllocSize; |
| IMG_UINT32 ui32ClientAllocSize; |
| IMG_UINT32 ui32TotalAllocSize; |
| IMG_UINT32 ui32ServerIndex = 0; |
| IMG_UINT32 ui32ClientIndex = 0; |
| IMG_UINT32 i; |
| IMG_UINT32 ui32SyncBlockCount; |
| IMG_HANDLE hBridge; |
| IMG_HANDLE *pahHandleList; |
| IMG_CHAR *pcPtr; |
| PVRSRV_ERROR eError; |
| IMG_BOOL bServerSync; |
| |
| psSyncBlockList = _SyncPrimBlockListCreate(); |
| |
| if (!psSyncBlockList) |
| { |
| eError = PVRSRV_ERROR_OUT_OF_MEMORY; |
| goto e0; |
| } |
| |
| for (i=0;i<ui32SyncCount;i++) |
| { |
| eError = SyncPrimIsServerSync(papsSyncPrim[i], &bServerSync); |
| if (PVRSRV_OK != eError) goto e1; |
| if (bServerSync) |
| { |
| ui32ServerSyncCount++; |
| } |
| else |
| { |
| SYNC_PRIM *psSync = (SYNC_PRIM *) papsSyncPrim[i]; |
| |
| ui32ClientSyncCount++; |
| eError = _SyncPrimBlockListAdd(psSyncBlockList, psSync->u.sLocal.psSyncBlock); |
| if (eError != PVRSRV_OK) |
| { |
| goto e1; |
| } |
| } |
| } |
| |
| ui32ServerAllocSize = ui32ServerSyncCount * (sizeof(IMG_HANDLE) + sizeof(IMG_UINT32)); |
| ui32ClientAllocSize = ui32ClientSyncCount * (5 * sizeof(IMG_UINT32)); |
| ui32TotalAllocSize = sizeof(SYNC_OP_COOKIE) + |
| (sizeof(PVRSRV_CLIENT_SYNC_PRIM *) * ui32SyncCount) + |
| ui32ServerAllocSize + |
| ui32ClientAllocSize; |
| |
| psNewCookie = OSAllocMem(ui32TotalAllocSize); |
| pcPtr = (IMG_CHAR *) psNewCookie; |
| |
| if (!psNewCookie) |
| { |
| eError = PVRSRV_ERROR_OUT_OF_MEMORY; |
| goto e1; |
| } |
| |
| /* Setup the pointers */ |
| pcPtr += sizeof(SYNC_OP_COOKIE); |
| psNewCookie->papsSyncPrim = (PVRSRV_CLIENT_SYNC_PRIM **) pcPtr; |
| |
| pcPtr += sizeof(PVRSRV_CLIENT_SYNC_PRIM *) * ui32SyncCount; |
| psNewCookie->paui32SyncBlockIndex = (IMG_UINT32 *) pcPtr; |
| |
| pcPtr += sizeof(IMG_UINT32) * ui32ClientSyncCount; |
| psNewCookie->paui32Index = (IMG_UINT32 *) pcPtr; |
| |
| pcPtr += sizeof(IMG_UINT32) * ui32ClientSyncCount; |
| psNewCookie->paui32Flags = (IMG_UINT32 *) pcPtr; |
| |
| pcPtr += sizeof(IMG_UINT32) * ui32ClientSyncCount; |
| psNewCookie->paui32FenceValue = (IMG_UINT32 *) pcPtr; |
| |
| pcPtr += sizeof(IMG_UINT32) * ui32ClientSyncCount; |
| psNewCookie->paui32UpdateValue = (IMG_UINT32 *) pcPtr; |
| |
| pcPtr += sizeof(IMG_UINT32) * ui32ClientSyncCount; |
| psNewCookie->pahServerSync =(IMG_HANDLE *) pcPtr; |
| pcPtr += sizeof(IMG_HANDLE) * ui32ServerSyncCount; |
| |
| psNewCookie->paui32ServerFlags =(IMG_UINT32 *) pcPtr; |
| pcPtr += sizeof(IMG_UINT32) * ui32ServerSyncCount; |
| |
| /* Check the pointer setup went ok */ |
| if (!(pcPtr == (((IMG_CHAR *) psNewCookie) + ui32TotalAllocSize))) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "%s: cookie setup failed", __func__)); |
| eError = PVRSRV_ERROR_INTERNAL_ERROR; |
| goto e2; |
| } |
| |
| psNewCookie->ui32SyncCount = ui32SyncCount; |
| psNewCookie->ui32ServerSyncCount = ui32ServerSyncCount; |
| psNewCookie->ui32ClientSyncCount = ui32ClientSyncCount; |
| psNewCookie->psSyncBlockList = psSyncBlockList; |
| |
| /* |
| Get the bridge handle from the 1st sync. |
| |
| Note: We assume the all syncs have been created with the same |
| services connection. |
| */ |
| eError = SyncPrimIsServerSync(papsSyncPrim[0], &bServerSync); |
| if (PVRSRV_OK != eError) goto e2; |
| if (bServerSync) |
| { |
| SYNC_PRIM *psSync = (SYNC_PRIM *) papsSyncPrim[0]; |
| |
| hBridge = psSync->u.sServer.hBridge; |
| } |
| else |
| { |
| SYNC_PRIM *psSync = (SYNC_PRIM *) papsSyncPrim[0]; |
| |
| hBridge = GetBridgeHandle(psSync->u.sLocal.psSyncBlock->psContext->hDevConnection); |
| } |
| |
| psNewCookie->hBridge = hBridge; |
| |
| if (ui32ServerSyncCount) |
| { |
| psNewCookie->bHaveServerSync = IMG_TRUE; |
| } |
| else |
| { |
| psNewCookie->bHaveServerSync = IMG_FALSE; |
| } |
| |
| /* Fill in the server and client sync data */ |
| for (i=0;i<ui32SyncCount;i++) |
| { |
| SYNC_PRIM *psSync = (SYNC_PRIM *) papsSyncPrim[i]; |
| |
| eError = SyncPrimIsServerSync(papsSyncPrim[i], &bServerSync); |
| if (PVRSRV_OK != eError) goto e2; |
| if (bServerSync) |
| { |
| psNewCookie->pahServerSync[ui32ServerIndex] = psSync->u.sServer.hServerSync; |
| |
| ui32ServerIndex++; |
| } |
| else |
| { |
| /* Location of sync */ |
| eError = _SyncPrimBlockListBlockToIndex(psSyncBlockList, |
| psSync->u.sLocal.psSyncBlock, |
| &psNewCookie->paui32SyncBlockIndex[ui32ClientIndex]); |
| if (eError != PVRSRV_OK) |
| { |
| goto e2; |
| } |
| |
| /* Workout the index to sync */ |
| psNewCookie->paui32Index[ui32ClientIndex] = |
| SyncPrimGetOffset(psSync)/sizeof(IMG_UINT32); |
| |
| ui32ClientIndex++; |
| } |
| |
| psNewCookie->papsSyncPrim[i] = papsSyncPrim[i]; |
| } |
| |
| eError = _SyncPrimBlockListHandleArrayCreate(psSyncBlockList, |
| &ui32SyncBlockCount, |
| &pahHandleList); |
| if (eError !=PVRSRV_OK) |
| { |
| goto e2; |
| } |
| |
| /* |
| Create the server side cookie. Here we pass in all the unchanging |
| data so we only need to pass in the minimum at takeop time |
| */ |
| eError = BridgeSyncPrimOpCreate(hBridge, |
| ui32SyncBlockCount, |
| pahHandleList, |
| psNewCookie->ui32ClientSyncCount, |
| psNewCookie->paui32SyncBlockIndex, |
| psNewCookie->paui32Index, |
| psNewCookie->ui32ServerSyncCount, |
| psNewCookie->pahServerSync, |
| &psNewCookie->hServerCookie); |
| |
| /* Free the handle list regardless of error */ |
| _SyncPrimBlockListHandleArrayDestroy(pahHandleList); |
| |
| if (eError != PVRSRV_OK) |
| { |
| goto e2; |
| } |
| |
| /* Increase the reference count on all referenced local sync prims |
| * so that they cannot be freed until this Op is finished with |
| */ |
| for (i=0;i<ui32SyncCount;i++) |
| { |
| SYNC_PRIM *psSyncInt; |
| psSyncInt = IMG_CONTAINER_OF(papsSyncPrim[i], SYNC_PRIM, sCommon); |
| if (SYNC_PRIM_TYPE_LOCAL == psSyncInt->eType) |
| { |
| SyncPrimLocalRef(psSyncInt); |
| } |
| } |
| |
| *ppsCookie = psNewCookie; |
| return PVRSRV_OK; |
| |
| e2: |
| OSFreeMem(psNewCookie); |
| e1: |
| _SyncPrimBlockListDestroy(psSyncBlockList); |
| e0: |
| return eError; |
| } |
| |
| IMG_INTERNAL |
| PVRSRV_ERROR SyncPrimOpTake(PSYNC_OP_COOKIE psCookie, |
| IMG_UINT32 ui32SyncCount, |
| PVRSRV_CLIENT_SYNC_PRIM_OP *pasSyncOp) |
| { |
| PVRSRV_ERROR eError = PVRSRV_OK; |
| IMG_UINT32 ui32ServerIndex = 0; |
| IMG_UINT32 ui32ClientIndex = 0; |
| IMG_UINT32 i; |
| IMG_BOOL bServerSync; |
| |
| /* Copy client sync operations */ |
| for (i=0;i<ui32SyncCount;i++) |
| { |
| /* |
| Sanity check the client passes in the same syncs as the |
| ones we got at create time |
| */ |
| if (psCookie->papsSyncPrim[i] != pasSyncOp[i].psSync) |
| { |
| eError = PVRSRV_ERROR_INVALID_PARAMS; |
| goto e0; |
| } |
| |
| eError = SyncPrimIsServerSync(pasSyncOp[i].psSync, &bServerSync); |
| if (PVRSRV_OK != eError) goto e0; |
| if (bServerSync) |
| { |
| psCookie->paui32ServerFlags[ui32ServerIndex] = |
| pasSyncOp[i].ui32Flags; |
| |
| ui32ServerIndex++; |
| } |
| else |
| { |
| /* Client operation information */ |
| psCookie->paui32Flags[ui32ClientIndex] = |
| pasSyncOp[i].ui32Flags; |
| psCookie->paui32FenceValue[ui32ClientIndex] = |
| pasSyncOp[i].ui32FenceValue; |
| psCookie->paui32UpdateValue[ui32ClientIndex] = |
| pasSyncOp[i].ui32UpdateValue; |
| |
| ui32ClientIndex++; |
| } |
| } |
| |
| eError = BridgeSyncPrimOpTake(psCookie->hBridge, |
| psCookie->hServerCookie, |
| psCookie->ui32ClientSyncCount, |
| psCookie->paui32Flags, |
| psCookie->paui32FenceValue, |
| psCookie->paui32UpdateValue, |
| psCookie->ui32ServerSyncCount, |
| psCookie->paui32ServerFlags); |
| |
| e0: |
| return eError; |
| } |
| |
| IMG_INTERNAL |
| PVRSRV_ERROR SyncPrimOpReady(PSYNC_OP_COOKIE psCookie, |
| IMG_BOOL *pbReady) |
| { |
| PVRSRV_ERROR eError; |
| if (!psCookie) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "%s: invalid input pointer", __func__)); |
| eError = PVRSRV_ERROR_INVALID_PARAMS; |
| goto e0; |
| } |
| |
| /* |
| If we have a server sync we have no choice |
| but to do the check in the server |
| */ |
| if (psCookie->bHaveServerSync) |
| { |
| eError = BridgeSyncPrimOpReady(psCookie->hBridge, |
| psCookie->hServerCookie, |
| pbReady); |
| if (eError != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_ERROR, |
| "%s: Failed to do sync check in server (Error = %d)", |
| __func__, eError)); |
| goto e0; |
| } |
| } |
| else |
| { |
| IMG_UINT32 i; |
| IMG_UINT32 ui32SnapShot; |
| IMG_BOOL bReady = IMG_TRUE; |
| |
| for (i=0;i<psCookie->ui32ClientSyncCount;i++) |
| { |
| if ((psCookie->paui32Flags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK) == 0) |
| { |
| continue; |
| } |
| |
| ui32SnapShot = _SyncPrimBlockListGetClientValue(psCookie->psSyncBlockList, |
| psCookie->paui32SyncBlockIndex[i], |
| psCookie->paui32Index[i]); |
| if (ui32SnapShot != psCookie->paui32FenceValue[i]) |
| { |
| bReady = IMG_FALSE; |
| break; |
| } |
| } |
| |
| *pbReady = bReady; |
| } |
| |
| return PVRSRV_OK; |
| e0: |
| return eError; |
| } |
| |
| IMG_INTERNAL |
| PVRSRV_ERROR SyncPrimOpComplete(PSYNC_OP_COOKIE psCookie) |
| { |
| PVRSRV_ERROR eError; |
| |
| eError = BridgeSyncPrimOpComplete(psCookie->hBridge, |
| psCookie->hServerCookie); |
| |
| return eError; |
| } |
| |
| IMG_INTERNAL |
| PVRSRV_ERROR SyncPrimOpDestroy(PSYNC_OP_COOKIE psCookie) |
| { |
| PVRSRV_ERROR eError = PVRSRV_OK; |
| IMG_UINT32 i; |
| |
| eError = BridgeSyncPrimOpDestroy(psCookie->hBridge, psCookie->hServerCookie); |
| if (PVRSRV_OK != eError) |
| { |
| PVR_DPF((PVR_DBG_ERROR, |
| "%s: Failed to destroy SyncPrimOp (Error = %d)", |
| __func__, eError)); |
| goto err_out; |
| } |
| |
| /* Decrease the reference count on all referenced local sync prims |
| * so that they can be freed now this Op is finished with |
| */ |
| for (i=0;i<psCookie->ui32SyncCount;i++) |
| { |
| SYNC_PRIM *psSyncInt; |
| psSyncInt = IMG_CONTAINER_OF(psCookie->papsSyncPrim[i], SYNC_PRIM, sCommon); |
| if (SYNC_PRIM_TYPE_LOCAL == psSyncInt->eType) |
| { |
| SyncPrimLocalUnref(psSyncInt); |
| } |
| } |
| |
| _SyncPrimBlockListDestroy(psCookie->psSyncBlockList); |
| OSFreeMem(psCookie); |
| |
| err_out: |
| return eError; |
| } |
| |
| #if !defined(__KERNEL__) |
| IMG_INTERNAL |
| PVRSRV_ERROR SyncPrimServerAlloc(SYNC_BRIDGE_HANDLE hBridge, |
| PVRSRV_CLIENT_SYNC_PRIM **ppsSync, |
| const IMG_CHAR *pszClassName |
| PVR_DBG_FILELINE_PARAM) |
| { |
| IMG_CHAR szClassName[SYNC_MAX_CLASS_NAME_LEN]; |
| SYNC_PRIM *psNewSync; |
| PVRSRV_ERROR eError; |
| size_t uiSize; |
| |
| #if !defined(PVR_SYNC_PRIM_ALLOC_TRACE) |
| PVR_DBG_FILELINE_UNREF(); |
| #endif |
| psNewSync = OSAllocZMem(sizeof(SYNC_PRIM)); |
| if (psNewSync == NULL) |
| { |
| eError = PVRSRV_ERROR_OUT_OF_MEMORY; |
| goto e0; |
| } |
| |
| if (pszClassName) |
| { |
| uiSize = OSStringNLength(pszClassName, SYNC_MAX_CLASS_NAME_LEN); |
| /* Copy the class name annotation into a fixed-size array */ |
| OSCachedMemCopy(szClassName, pszClassName, uiSize); |
| /* NUL-terminate the ClassName if it wasn't already */ |
| if (uiSize == SYNC_MAX_CLASS_NAME_LEN) |
| szClassName[SYNC_MAX_CLASS_NAME_LEN-1] = '\0'; |
| else |
| szClassName[uiSize++] = '\0'; |
| } |
| else |
| { |
| /* No class name annotation */ |
| uiSize = 0; |
| szClassName[0] = '\0'; |
| } |
| |
| eError = BridgeServerSyncAlloc(hBridge, |
| &psNewSync->u.sServer.hServerSync, |
| &psNewSync->u.sServer.ui32FirmwareAddr, |
| uiSize, |
| szClassName); |
| |
| if (eError != PVRSRV_OK) |
| { |
| goto e1; |
| } |
| |
| #if defined(PVR_SYNC_PRIM_ALLOC_TRACE) |
| PVR_DPF((PVR_DBG_WARNING, "Allocated sync=server fw=0x%x [%p]" PVR_DBG_FILELINE_FMT, |
| psNewSync->u.sServer.ui32FirmwareAddr, &psNewSync->sCommon PVR_DBG_FILELINE_ARG)); |
| #endif |
| |
| psNewSync->eType = SYNC_PRIM_TYPE_SERVER; |
| psNewSync->u.sServer.hBridge = hBridge; |
| *ppsSync = &psNewSync->sCommon; |
| |
| return PVRSRV_OK; |
| e1: |
| OSFreeMem(psNewSync); |
| e0: |
| return eError; |
| } |
| |
| IMG_INTERNAL |
| PVRSRV_ERROR SyncPrimServerGetStatus(IMG_UINT32 ui32SyncCount, |
| PVRSRV_CLIENT_SYNC_PRIM **papsSync, |
| IMG_UINT32 *pui32UID, |
| IMG_UINT32 *pui32FWAddr, |
| IMG_UINT32 *pui32CurrentOp, |
| IMG_UINT32 *pui32NextOp) |
| { |
| PVRSRV_ERROR eError; |
| IMG_UINT32 i; |
| SYNC_BRIDGE_HANDLE hBridge = NULL; |
| IMG_HANDLE *pahServerHandle; |
| IMG_BOOL bServerSync; |
| |
| if (papsSync[0]) |
| { |
| hBridge = _SyncPrimGetBridgeHandle(papsSync[0]); |
| } |
| if (!hBridge) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "%s: invalid Sync connection", __func__)); |
| eError = PVRSRV_ERROR_INVALID_SYNC_PRIM; |
| goto e0; |
| } |
| |
| pahServerHandle = OSAllocMem(sizeof(IMG_HANDLE) * ui32SyncCount); |
| if (pahServerHandle == NULL) |
| { |
| eError = PVRSRV_ERROR_OUT_OF_MEMORY; |
| goto e0; |
| } |
| |
| /* |
| Check that all the sync we've been passed are server syncs |
| and that they all are on the same connection. |
| */ |
| for (i=0;i<ui32SyncCount;i++) |
| { |
| SYNC_PRIM *psIntSync = IMG_CONTAINER_OF(papsSync[i], SYNC_PRIM, sCommon); |
| |
| eError = SyncPrimIsServerSync(papsSync[i], &bServerSync); |
| if (PVRSRV_OK != eError) goto e1; |
| if (!bServerSync) |
| { |
| eError = PVRSRV_ERROR_INVALID_SYNC_PRIM; |
| goto e1; |
| } |
| |
| if (!papsSync[i] || hBridge != _SyncPrimGetBridgeHandle(papsSync[i])) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "%s: Sync connection is different", __func__)); |
| eError = PVRSRV_ERROR_INVALID_SYNC_PRIM; |
| goto e1; |
| } |
| |
| pahServerHandle[i] = psIntSync->u.sServer.hServerSync; |
| } |
| |
| eError = BridgeServerSyncGetStatus(hBridge, |
| ui32SyncCount, |
| pahServerHandle, |
| pui32UID, |
| pui32FWAddr, |
| pui32CurrentOp, |
| pui32NextOp); |
| OSFreeMem(pahServerHandle); |
| |
| if (eError != PVRSRV_OK) |
| { |
| goto e0; |
| } |
| return PVRSRV_OK; |
| |
| e1: |
| OSFreeMem(pahServerHandle); |
| e0: |
| return eError; |
| } |
| |
| #endif /* defined(__KERNEL__) */ |
| #endif /* defined(SUPPORT_SERVER_SYNC_IMPL) */ |
| |
| IMG_INTERNAL PVRSRV_ERROR |
| SyncPrimIsServerSync(PVRSRV_CLIENT_SYNC_PRIM *psSync, IMG_BOOL *pbServerSync) |
| { |
| PVRSRV_ERROR eError = PVRSRV_OK; |
| SYNC_PRIM *psSyncInt; |
| |
| if (unlikely(!psSync)) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "%s: invalid input pointer", __func__)); |
| eError = PVRSRV_ERROR_INVALID_PARAMS; |
| goto e0; |
| } |
| psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon); |
| if (psSyncInt->eType == SYNC_PRIM_TYPE_LOCAL) |
| { |
| *pbServerSync = IMG_FALSE; |
| } |
| else if (psSyncInt->eType == SYNC_PRIM_TYPE_SERVER) |
| { |
| #if defined(SUPPORT_SERVER_SYNC_IMPL) |
| *pbServerSync = IMG_TRUE; |
| #else |
| PVR_DPF((PVR_DBG_ERROR, "%s: Server sync not supported, attempted use of server sync", __func__)); |
| return PVRSRV_ERROR_NOT_SUPPORTED; |
| #endif |
| } |
| else |
| { |
| /* Either the client has given us a bad pointer or there is an |
| * error in this module |
| */ |
| PVR_DPF((PVR_DBG_ERROR, "%s: Invalid sync type", __func__)); |
| eError = PVRSRV_ERROR_INVALID_SYNC_PRIM; |
| goto e0; |
| } |
| |
| e0: |
| return eError; |
| } |
| |
| #if defined(SUPPORT_SERVER_SYNC_IMPL) |
| IMG_INTERNAL |
| IMG_HANDLE SyncPrimGetServerHandle(PVRSRV_CLIENT_SYNC_PRIM *psSync) |
| { |
| SYNC_PRIM *psSyncInt; |
| |
| if (unlikely(!psSync)) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "%s: invalid input pointer", __func__)); |
| goto e0; |
| } |
| psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon); |
| if (likely(psSyncInt->eType == SYNC_PRIM_TYPE_SERVER)) |
| { |
| return psSyncInt->u.sServer.hServerSync; |
| } |
| else |
| { |
| PVR_DPF((PVR_DBG_ERROR, "%s: invalid sync type (%d)", |
| __func__, psSyncInt->eType)); |
| goto e0; |
| } |
| e0: |
| return (IMG_HANDLE) NULL; |
| } |
| |
| IMG_INTERNAL |
| PVRSRV_ERROR SyncPrimServerQueueOp(PVRSRV_CLIENT_SYNC_PRIM_OP *psSyncOp) |
| { |
| SYNC_PRIM *psSyncInt; |
| IMG_BOOL bUpdate; |
| PVRSRV_ERROR eError; |
| |
| if (!psSyncOp) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "%s: invalid input pointer", __func__)); |
| eError = PVRSRV_ERROR_INVALID_PARAMS; |
| goto e0; |
| } |
| |
| psSyncInt = IMG_CONTAINER_OF(psSyncOp->psSync, SYNC_PRIM, sCommon); |
| if (psSyncInt->eType != SYNC_PRIM_TYPE_SERVER) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "%s: invalid sync type (%d)", |
| __func__, psSyncInt->eType)); |
| eError = PVRSRV_ERROR_INVALID_SYNC_PRIM; |
| goto e0; |
| } |
| if (0 == psSyncOp->ui32Flags) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "%s: no sync flags", __func__)); |
| eError = PVRSRV_ERROR_INVALID_SYNC_PRIM; |
| goto e0; |
| } |
| |
| if (psSyncOp->ui32Flags & PVRSRV_CLIENT_SYNC_PRIM_OP_UPDATE) |
| { |
| bUpdate = IMG_TRUE; |
| }else |
| { |
| bUpdate = IMG_FALSE; |
| } |
| |
| eError = BridgeServerSyncQueueHWOp(psSyncInt->u.sServer.hBridge, |
| psSyncInt->u.sServer.hServerSync, |
| bUpdate, |
| &psSyncOp->ui32FenceValue, |
| &psSyncOp->ui32UpdateValue); |
| e0: |
| return eError; |
| } |
| #endif |
| |
| #if defined(PDUMP) |
| IMG_INTERNAL void SyncPrimPDump(PVRSRV_CLIENT_SYNC_PRIM *psSync) |
| { |
| SYNC_PRIM *psSyncInt; |
| SYNC_PRIM_BLOCK *psSyncBlock; |
| SYNC_PRIM_CONTEXT *psContext; |
| PVRSRV_ERROR eError; |
| |
| PVR_ASSERT(psSync != NULL); |
| psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon); |
| |
| if (psSyncInt->eType != SYNC_PRIM_TYPE_LOCAL) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "%s: Invalid sync type", __func__)); |
| PVR_ASSERT(IMG_FALSE); |
| return; |
| } |
| |
| psSyncBlock = psSyncInt->u.sLocal.psSyncBlock; |
| psContext = psSyncBlock->psContext; |
| |
| eError = BridgeSyncPrimPDump(GetBridgeHandle(psContext->hDevConnection), |
| psSyncBlock->hServerSyncPrimBlock, |
| SyncPrimGetOffset(psSyncInt)); |
| |
| if (eError != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_ERROR, |
| "%s: failed with error %d", |
| __func__, eError)); |
| } |
| PVR_ASSERT(eError == PVRSRV_OK); |
| } |
| |
| IMG_INTERNAL void SyncPrimPDumpValue(PVRSRV_CLIENT_SYNC_PRIM *psSync, IMG_UINT32 ui32Value) |
| { |
| SYNC_PRIM *psSyncInt; |
| SYNC_PRIM_BLOCK *psSyncBlock; |
| SYNC_PRIM_CONTEXT *psContext; |
| PVRSRV_ERROR eError; |
| |
| PVR_ASSERT(psSync != NULL); |
| psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon); |
| |
| if (psSyncInt->eType != SYNC_PRIM_TYPE_LOCAL) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "%s: Invalid sync type", __func__)); |
| PVR_ASSERT(IMG_FALSE); |
| return; |
| } |
| |
| psSyncBlock = psSyncInt->u.sLocal.psSyncBlock; |
| psContext = psSyncBlock->psContext; |
| |
| eError = BridgeSyncPrimPDumpValue(GetBridgeHandle(psContext->hDevConnection), |
| psSyncBlock->hServerSyncPrimBlock, |
| SyncPrimGetOffset(psSyncInt), |
| ui32Value); |
| |
| if (eError != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_ERROR, |
| "%s: failed with error %d", |
| __func__, eError)); |
| } |
| PVR_ASSERT(eError == PVRSRV_OK); |
| } |
| |
| IMG_INTERNAL void SyncPrimPDumpPol(PVRSRV_CLIENT_SYNC_PRIM *psSync, |
| IMG_UINT32 ui32Value, |
| IMG_UINT32 ui32Mask, |
| PDUMP_POLL_OPERATOR eOperator, |
| IMG_UINT32 ui32PDumpFlags) |
| { |
| SYNC_PRIM *psSyncInt; |
| SYNC_PRIM_BLOCK *psSyncBlock; |
| SYNC_PRIM_CONTEXT *psContext; |
| PVRSRV_ERROR eError; |
| |
| PVR_ASSERT(psSync != NULL); |
| psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon); |
| |
| if (psSyncInt->eType != SYNC_PRIM_TYPE_LOCAL) |
| { |
| PVR_DPF((PVR_DBG_ERROR, |
| "%s: Invalid sync type (expected SYNC_PRIM_TYPE_LOCAL)", |
| __func__)); |
| PVR_ASSERT(IMG_FALSE); |
| return; |
| } |
| |
| psSyncBlock = psSyncInt->u.sLocal.psSyncBlock; |
| psContext = psSyncBlock->psContext; |
| |
| eError = BridgeSyncPrimPDumpPol(GetBridgeHandle(psContext->hDevConnection), |
| psSyncBlock->hServerSyncPrimBlock, |
| SyncPrimGetOffset(psSyncInt), |
| ui32Value, |
| ui32Mask, |
| eOperator, |
| ui32PDumpFlags); |
| |
| if (eError != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_ERROR, |
| "%s: failed with error %d", |
| __func__, eError)); |
| } |
| PVR_ASSERT(eError == PVRSRV_OK); |
| } |
| |
| #if defined(SUPPORT_SERVER_SYNC_IMPL) |
| IMG_INTERNAL void SyncPrimOpPDumpPol(PSYNC_OP_COOKIE psCookie, |
| PDUMP_POLL_OPERATOR eOperator, |
| IMG_UINT32 ui32PDumpFlags) |
| { |
| PVRSRV_ERROR eError; |
| |
| PVR_ASSERT(psCookie != NULL); |
| |
| eError = BridgeSyncPrimOpPDumpPol(psCookie->hBridge, |
| psCookie->hServerCookie, |
| eOperator, |
| ui32PDumpFlags); |
| |
| if (eError != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_ERROR, |
| "%s: failed with error %d", |
| __func__, eError)); |
| } |
| |
| PVR_ASSERT(eError == PVRSRV_OK); |
| } |
| #endif |
| |
| IMG_INTERNAL void SyncPrimPDumpCBP(PVRSRV_CLIENT_SYNC_PRIM *psSync, |
| IMG_UINT64 uiWriteOffset, |
| IMG_UINT64 uiPacketSize, |
| IMG_UINT64 uiBufferSize) |
| { |
| SYNC_PRIM *psSyncInt; |
| SYNC_PRIM_BLOCK *psSyncBlock; |
| SYNC_PRIM_CONTEXT *psContext; |
| PVRSRV_ERROR eError; |
| |
| PVR_ASSERT(psSync != NULL); |
| psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon); |
| |
| if (psSyncInt->eType != SYNC_PRIM_TYPE_LOCAL) |
| { |
| PVR_DPF((PVR_DBG_ERROR, "%s: Invalid sync type", __func__)); |
| PVR_ASSERT(IMG_FALSE); |
| return; |
| } |
| |
| psSyncBlock = psSyncInt->u.sLocal.psSyncBlock; |
| psContext = psSyncBlock->psContext; |
| |
| /* FIXME: uiWriteOffset, uiPacketSize, uiBufferSize were changed to |
| * 64-bit quantities to resolve Windows compiler warnings. |
| * However the bridge is only 32-bit hence compiler warnings |
| * of implicit cast and loss of data. |
| * Added explicit cast and assert to remove warning. |
| */ |
| #if defined(LINUX) && defined(__i386__) |
| PVR_ASSERT(uiWriteOffset<IMG_UINT32_MAX); |
| PVR_ASSERT(uiPacketSize<IMG_UINT32_MAX); |
| PVR_ASSERT(uiBufferSize<IMG_UINT32_MAX); |
| #endif |
| eError = BridgeSyncPrimPDumpCBP(GetBridgeHandle(psContext->hDevConnection), |
| psSyncBlock->hServerSyncPrimBlock, |
| SyncPrimGetOffset(psSyncInt), |
| (IMG_UINT32)uiWriteOffset, |
| (IMG_UINT32)uiPacketSize, |
| (IMG_UINT32)uiBufferSize); |
| |
| if (eError != PVRSRV_OK) |
| { |
| PVR_DPF((PVR_DBG_ERROR, |
| "%s: failed with error %d", |
| __func__, eError)); |
| } |
| PVR_ASSERT(eError == PVRSRV_OK); |
| } |
| |
| #endif |
| |