static PVRSRV_ERROR _Destroy3DTransferContext(RGX_SERVER_TQ_3D_DATA *ps3DData, PVRSRV_DEVICE_NODE *psDeviceNode, PVRSRV_CLIENT_SYNC_PRIM *psCleanupSync) { PVRSRV_ERROR eError; /* Check if the FW has finished with this resource ... */ eError = RGXFWRequestCommonContextCleanUp(psDeviceNode, FWCommonContextGetFWAddress(ps3DData->psServerCommonContext), psCleanupSync, RGXFWIF_DM_3D); if (eError == PVRSRV_ERROR_RETRY) { return eError; } else if (eError != PVRSRV_OK) { PVR_LOG(("%s: Unexpected error from RGXFWRequestCommonContextCleanUp (%s)", __FUNCTION__, PVRSRVGetErrorStringKM(eError))); } /* ... it has so we can free it's resources */ DevmemFwFree(ps3DData->psFWContextStateMemDesc); FWCommonContextFree(ps3DData->psServerCommonContext); return PVRSRV_OK; }
/*! ****************************************************************************** @Function PVRSRVLookupHandleAnyType @Description Lookup the data pointer and type corresponding to a handle @Input ppvData - location to return data pointer peType - location to return handle type hHandle - handle from client @Output ppvData - points to the data pointer peType - points to handle type @Return Error code or PVRSRV_OK ******************************************************************************/ PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_HANDLE hHandle) { HANDLE_DATA *psHandleData = IMG_NULL; PVRSRV_ERROR eError; PVR_ASSERT(gpsHandleFuncs); if (psBase == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupHandleAnyType: Missing handle base")); eError = PVRSRV_ERROR_INVALID_PARAMS; goto err; } eError = GetHandleData(psBase, &psHandleData, hHandle, PVRSRV_HANDLE_TYPE_NONE); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupHandleAnyType: Error looking up handle (%s)", PVRSRVGetErrorStringKM(eError))); OSDumpStack(); goto err; } *ppvData = psHandleData->pvData; *peType = psHandleData->eType; eError = PVRSRV_OK; err: return eError; }
/*! ****************************************************************************** @Function PVRSRVHandleDeInit @Description De-initialise handle management @Return Error code or PVRSRV_OK ******************************************************************************/ PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID) { PVRSRV_ERROR eError = PVRSRV_OK; if (gpsHandleFuncs != IMG_NULL) { if (gpsKernelHandleBase != IMG_NULL) { eError = PVRSRVFreeHandleBase(gpsKernelHandleBase); if (eError == PVRSRV_OK) { gpsKernelHandleBase = IMG_NULL; } else { PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleDeInit: FreeHandleBase failed (%s)", PVRSRVGetErrorStringKM(eError))); } } if (eError == PVRSRV_OK) { gpsHandleFuncs = IMG_NULL; } } else { /* If we don't have a handle function table we shouldn't have a handle base either */ PVR_ASSERT(gpsKernelHandleBase == IMG_NULL); } return eError; }
/*! ****************************************************************************** @Function DestroyHandleBase @Description Destroy a handle base structure @Input psBase - pointer to handle base structure @Return Error code or PVRSRV_OK ******************************************************************************/ static PVRSRV_ERROR DestroyHandleBase(HANDLE_IMPL_BASE *psBase) { PVRSRV_ERROR eError; PVR_ASSERT(psBase); if (psBase->ui32TotalHandCount != psBase->ui32TotalFreeHandCount) { PVR_DPF((PVR_DBG_WARNING, "%s: Handles still exist (%u found)", __FUNCTION__, psBase->ui32TotalHandCount - psBase->ui32TotalFreeHandCount)); } eError = ReallocHandleBlockArray(psBase, 0); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "%s: Couldn't free handle array (%s)", __FUNCTION__, PVRSRVGetErrorStringKM(eError))); return eError; } OSFreeMem(psBase); return PVRSRV_OK; }
IMG_EXPORT PVRSRV_ERROR PVRSRVRGXDestroyComputeContextKM(RGX_SERVER_COMPUTE_CONTEXT *psComputeContext) { PVRSRV_ERROR eError = PVRSRV_OK; /* Check if the FW has finished with this resource ... */ eError = RGXFWRequestCommonContextCleanUp(psComputeContext->psDeviceNode, FWCommonContextGetFWAddress(psComputeContext->psServerCommonContext), psComputeContext->psSync, RGXFWIF_DM_CDM); if (eError == PVRSRV_ERROR_RETRY) { return eError; } else if (eError != PVRSRV_OK) { PVR_LOG(("%s: Unexpected error from RGXFWRequestCommonContextCleanUp (%s)", __FUNCTION__, PVRSRVGetErrorStringKM(eError))); } /* ... it has so we can free its resources */ dllist_remove_node(&(psComputeContext->sListNode)); FWCommonContextFree(psComputeContext->psServerCommonContext); DevmemFwFree(psComputeContext->psFWFrameworkMemDesc); DevmemFwFree(psComputeContext->psFWComputeContextStateMemDesc); SyncPrimFree(psComputeContext->psSync); OSFreeMem(psComputeContext); return PVRSRV_OK; }
/*! ****************************************************************************** @Function PVRSRVHandleInit @Description Initialise handle management @Return Error code or PVRSRV_OK ******************************************************************************/ PVRSRV_ERROR PVRSRVHandleInit(IMG_VOID) { PVRSRV_ERROR eError; PVR_ASSERT(gpsKernelHandleBase == IMG_NULL); PVR_ASSERT(gpsHandleFuncs == IMG_NULL); eError = PVRSRVHandleGetFuncTable(&gpsHandleFuncs); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleInit: PVRSRVHandleGetFuncTable failed (%s)", PVRSRVGetErrorStringKM(eError))); goto error; } eError = PVRSRVAllocHandleBase(&gpsKernelHandleBase); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleInit: PVRSRVAllocHandleBase failed (%s)", PVRSRVGetErrorStringKM(eError))); goto error; } eError = gpsHandleFuncs->pfnEnableHandlePurging(gpsKernelHandleBase->psImplBase); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleInit: PVRSRVEnableHandlePurging failed (%s)", PVRSRVGetErrorStringKM(eError))); goto error; } return PVRSRV_OK; error: (IMG_VOID) PVRSRVHandleDeInit(); return eError; }
/*! ****************************************************************************** @Function PVRSRVLookupSubHandle @Description Lookup the data pointer corresponding to a subhandle @Input ppvData - location to return data pointer hHandle - handle from client eType - handle type hAncestor - ancestor handle @Output ppvData - points to the data pointer @Return Error code or PVRSRV_OK ******************************************************************************/ PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hAncestor) { HANDLE_DATA *psPHandleData = IMG_NULL; HANDLE_DATA *psCHandleData = IMG_NULL; PVRSRV_ERROR eError; /* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE); PVR_ASSERT(gpsHandleFuncs); if (psBase == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupSubHandle: Missing handle base")); eError = PVRSRV_ERROR_INVALID_PARAMS; goto err; } eError = GetHandleData(psBase, &psCHandleData, hHandle, eType); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupSubHandle: Error looking up subhandle (%s)", PVRSRVGetErrorStringKM(eError))); OSDumpStack(); goto err; } /* Look for hAncestor among the handle's ancestors */ for (psPHandleData = psCHandleData; ParentHandle(psPHandleData) != hAncestor; ) { eError = GetHandleData(psBase, &psPHandleData, ParentHandle(psPHandleData), PVRSRV_HANDLE_TYPE_NONE); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVLookupSubHandle: Subhandle doesn't belong to given ancestor")); eError = PVRSRV_ERROR_INVALID_SUBHANDLE; goto err; } } *ppvData = psCHandleData->pvData; eError = PVRSRV_OK; err: return eError; }
IMG_EXPORT PVRSRV_ERROR PVRSRVRGXDestroyComputeContextKM(RGX_SERVER_COMPUTE_CONTEXT *psComputeContext) { PVRSRV_ERROR eError = PVRSRV_OK; PVRSRV_RGXDEV_INFO *psDevInfo = psComputeContext->psDeviceNode->pvDevice; /* Check if the FW has finished with this resource ... */ eError = RGXFWRequestCommonContextCleanUp(psComputeContext->psDeviceNode, psComputeContext->psServerCommonContext, psComputeContext->psSync, RGXFWIF_DM_CDM); if (eError == PVRSRV_ERROR_RETRY) { return eError; } else if (eError != PVRSRV_OK) { PVR_LOG(("%s: Unexpected error from RGXFWRequestCommonContextCleanUp (%s)", __FUNCTION__, PVRSRVGetErrorStringKM(eError))); return eError; } /* ... it has so we can free its resources */ OSWRLockAcquireWrite(psDevInfo->hComputeCtxListLock); dllist_remove_node(&(psComputeContext->sListNode)); OSWRLockReleaseWrite(psDevInfo->hComputeCtxListLock); FWCommonContextFree(psComputeContext->psServerCommonContext); DevmemFwFree(psComputeContext->psFWFrameworkMemDesc); DevmemFwFree(psComputeContext->psFWComputeContextStateMemDesc); SyncPrimFree(psComputeContext->psSync); SyncAddrListDeinit(&psComputeContext->sSyncAddrListFence); SyncAddrListDeinit(&psComputeContext->sSyncAddrListUpdate); OSFreeMem(psComputeContext); return PVRSRV_OK; }
/*! ****************************************************************************** @Function EnsureFreeHandles @Description Ensure there are enough free handles @Input psBase - Pointer to handle base structure ui32Free - Number of free handles required @Return Error code or PVRSRV_OK ******************************************************************************/ static PVRSRV_ERROR EnsureFreeHandles(HANDLE_IMPL_BASE *psBase, IMG_UINT32 ui32Free) { PVRSRV_ERROR eError = PVRSRV_OK; if (ui32Free > psBase->ui32TotalFreeHandCount) { IMG_UINT32 ui32FreeHandDelta = ui32Free - psBase->ui32TotalFreeHandCount; eError = IncreaseHandleArraySize(psBase, ui32FreeHandDelta); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "%s: Couldn't allocate %u handles to ensure %u free " "handles (IncreaseHandleArraySize failed with error %s)", __FUNCTION__, ui32FreeHandDelta, ui32Free, PVRSRVGetErrorStringKM(eError))); } } return eError; }
/*! ****************************************************************************** @Function PVRSRVGetParentHandle @Description Lookup the parent of a handle @Input phParent - location for returning parent handle hHandle - handle for which the parent handle is required eType - handle type hParent - parent handle @Output *phParent - parent handle, or IMG_NULL if there is no parent @Return Error code or PVRSRV_OK. Note that not having a parent is not regarded as an error. ******************************************************************************/ PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phParent, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType) { HANDLE_DATA *psHandleData = IMG_NULL; PVRSRV_ERROR eError; /* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE); PVR_ASSERT(gpsHandleFuncs); if (psBase == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetParentHandle: Missing handle base")); eError = PVRSRV_ERROR_INVALID_PARAMS; goto err; } eError = GetHandleData(psBase, &psHandleData, hHandle, eType); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetParentHandle: Error looking up subhandle (%s)", PVRSRVGetErrorStringKM(eError))); OSDumpStack(); goto err; } *phParent = ParentHandle(psHandleData); eError = PVRSRV_OK; err: return eError; }
/* * PVRSRVSubmitTQ3DKickKM */ IMG_EXPORT PVRSRV_ERROR PVRSRVRGXSubmitTransferKM(RGX_SERVER_TQ_CONTEXT *psTransferContext, IMG_UINT32 ui32PrepareCount, IMG_UINT32 *paui32ClientFenceCount, PRGXFWIF_UFO_ADDR **papauiClientFenceUFOAddress, IMG_UINT32 **papaui32ClientFenceValue, IMG_UINT32 *paui32ClientUpdateCount, PRGXFWIF_UFO_ADDR **papauiClientUpdateUFOAddress, IMG_UINT32 **papaui32ClientUpdateValue, IMG_UINT32 *paui32ServerSyncCount, IMG_UINT32 **papaui32ServerSyncFlags, SERVER_SYNC_PRIMITIVE ***papapsServerSyncs, IMG_UINT32 ui32NumFenceFDs, IMG_INT32 *paui32FenceFDs, IMG_UINT32 *paui32FWCommandSize, IMG_UINT8 **papaui8FWCommand, IMG_UINT32 *pui32TQPrepareFlags) { PVRSRV_DEVICE_NODE *psDeviceNode = psTransferContext->psDeviceNode; #if defined(WDDM) RGX_CCB_CMD_HELPER_DATA as3DCmdHelper[TQ_MAX_PREPARES_PER_SUBMIT]; RGX_CCB_CMD_HELPER_DATA as2DCmdHelper[TQ_MAX_PREPARES_PER_SUBMIT]; #endif RGX_CCB_CMD_HELPER_DATA *pas3DCmdHelper; RGX_CCB_CMD_HELPER_DATA *pas2DCmdHelper; IMG_UINT32 ui323DCmdCount = 0; IMG_UINT32 ui322DCmdCount = 0; IMG_BOOL bKick2D = IMG_FALSE; IMG_BOOL bKick3D = IMG_FALSE; IMG_BOOL bPDumpContinuous = IMG_FALSE; IMG_UINT32 i; IMG_UINT32 ui32IntClientFenceCount = 0; PRGXFWIF_UFO_ADDR *pauiIntFenceUFOAddress = IMG_NULL; IMG_UINT32 *paui32IntFenceValue = IMG_NULL; IMG_UINT32 ui32IntClientUpdateCount = 0; PRGXFWIF_UFO_ADDR *pauiIntUpdateUFOAddress = IMG_NULL; IMG_UINT32 *paui32IntUpdateValue = IMG_NULL; PVRSRV_ERROR eError; PVRSRV_ERROR eError2; #if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) IMG_BOOL bSyncsMerged = IMG_FALSE; #endif if (ui32PrepareCount == 0) { return PVRSRV_ERROR_INVALID_PARAMS; } if (ui32NumFenceFDs != 0) { #if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) /* Fence FD's are only valid in the 3D case with no batching */ if ((ui32PrepareCount !=1) && (!TQ_PREP_FLAGS_COMMAND_IS(pui32TQPrepareFlags[0], 3D))) { return PVRSRV_ERROR_INVALID_PARAMS; } #else /* We only support Fence FD's if built with PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC */ return PVRSRV_ERROR_INVALID_PARAMS; #endif } #if defined(WDDM) pas3DCmdHelper = &as3DCmdHelper; pas2DCmdHelper = &as2DCmdHelper; #else /* We can't allocate the required amount of stack space on all consumer architectures */ pas3DCmdHelper = OSAllocMem(sizeof(*pas3DCmdHelper) * ui32PrepareCount); if (pas3DCmdHelper == IMG_NULL) { eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto fail_alloc3dhelper; } pas2DCmdHelper = OSAllocMem(sizeof(*pas2DCmdHelper) * ui32PrepareCount); if (pas2DCmdHelper == IMG_NULL) { eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto fail_alloc2dhelper; } #endif /* Ensure we do the right thing for server syncs which cross call bounderies */ for (i=0;i<ui32PrepareCount;i++) { IMG_BOOL bHaveStartPrepare = pui32TQPrepareFlags[i] & TQ_PREP_FLAGS_START; IMG_BOOL bHaveEndPrepare = IMG_FALSE; if (bHaveStartPrepare) { IMG_UINT32 k; /* We've at the start of a transfer operation (which might be made up of multiple HW operations) so check if we also have then end of the transfer operation in the batch */ for (k=i;k<ui32PrepareCount;k++) { if (pui32TQPrepareFlags[k] & TQ_PREP_FLAGS_END) { bHaveEndPrepare = IMG_TRUE; break; } } if (!bHaveEndPrepare) { /* We don't have the complete command passed in this call so drop the update request. When we get called again with the last HW command in this transfer operation we'll do the update at that point. */ for (k=0;k<paui32ServerSyncCount[i];k++) { papaui32ServerSyncFlags[i][k] &= ~PVRSRV_CLIENT_SYNC_PRIM_OP_UPDATE; } } } } /* Init the command helper commands for all the prepares */ for (i=0;i<ui32PrepareCount;i++) { RGX_CLIENT_CCB *psClientCCB; RGX_SERVER_COMMON_CONTEXT *psServerCommonCtx; IMG_CHAR *pszCommandName; RGX_CCB_CMD_HELPER_DATA *psCmdHelper; RGXFWIF_CCB_CMD_TYPE eType; if (TQ_PREP_FLAGS_COMMAND_IS(pui32TQPrepareFlags[i], 3D)) { psServerCommonCtx = psTransferContext->s3DData.psServerCommonContext; psClientCCB = FWCommonContextGetClientCCB(psServerCommonCtx); pszCommandName = "TQ-3D"; psCmdHelper = &pas3DCmdHelper[ui323DCmdCount++]; eType = RGXFWIF_CCB_CMD_TYPE_TQ_3D; } else if (TQ_PREP_FLAGS_COMMAND_IS(pui32TQPrepareFlags[i], 2D)) { psServerCommonCtx = psTransferContext->s2DData.psServerCommonContext; psClientCCB = FWCommonContextGetClientCCB(psServerCommonCtx); pszCommandName = "TQ-2D"; psCmdHelper = &pas2DCmdHelper[ui322DCmdCount++]; eType = RGXFWIF_CCB_CMD_TYPE_TQ_2D; } else { eError = PVRSRV_ERROR_INVALID_PARAMS; goto fail_cmdtype; } if (i == 0) { bPDumpContinuous = ((pui32TQPrepareFlags[i] & TQ_PREP_FLAGS_PDUMPCONTINUOUS) == TQ_PREP_FLAGS_PDUMPCONTINUOUS); PDUMPCOMMENTWITHFLAGS((bPDumpContinuous) ? PDUMP_FLAGS_CONTINUOUS : 0, "%s Command Server Submit on FWCtx %08x", pszCommandName, FWCommonContextGetFWAddress(psServerCommonCtx).ui32Addr); } else { IMG_BOOL bNewPDumpContinuous = ((pui32TQPrepareFlags[i] & TQ_PREP_FLAGS_PDUMPCONTINUOUS) == TQ_PREP_FLAGS_PDUMPCONTINUOUS); if (bNewPDumpContinuous != bPDumpContinuous) { eError = PVRSRV_ERROR_INVALID_PARAMS; PVR_DPF((PVR_DBG_ERROR, "%s: Mixing of continuous and non-continuous command in a batch is not permitted", __FUNCTION__)); goto fail_pdumpcheck; } } #if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) if (ui32NumFenceFDs) { IMG_UINT32 ui32NumFenceSyncs; PRGXFWIF_UFO_ADDR *puiFenceFWAddrs; IMG_UINT32 *pui32FenceValues; IMG_UINT32 ui32NumUpdateSyncs; PRGXFWIF_UFO_ADDR *puiUpdateFWAddrs; IMG_UINT32 *pui32UpdateValues; /* FIXME: We can't be taking the server sync operations here as we have no way to undo them should the acquire fail. If client/local syncs where used here would that remove the issue? */ eError = PVRFDSyncQueryFencesKM(ui32NumFenceFDs, paui32FenceFDs, IMG_TRUE, &ui32NumFenceSyncs, &puiFenceFWAddrs, &pui32FenceValues, &ui32NumUpdateSyncs, &puiUpdateFWAddrs, &pui32UpdateValues); if (eError != PVRSRV_OK) { goto fail_fdsync; } /* Merge the Android syncs and the client syncs together */ ui32IntClientFenceCount = paui32ClientFenceCount[i] + ui32NumFenceSyncs; pauiIntFenceUFOAddress = OSAllocMem(sizeof(*pauiIntFenceUFOAddress)* ui32IntClientFenceCount); if (pauiIntFenceUFOAddress == IMG_NULL) { /* Free memory created by PVRFDSyncQueryFencesKM */ OSFreeMem(puiFenceFWAddrs); OSFreeMem(pui32FenceValues); OSFreeMem(puiUpdateFWAddrs); OSFreeMem(pui32UpdateValues); goto fail_fenceUFOarray; } paui32IntFenceValue = OSAllocMem(sizeof(*paui32IntFenceValue)* ui32IntClientFenceCount); if (paui32IntFenceValue == IMG_NULL) { /* Free memory created by PVRFDSyncQueryFencesKM */ OSFreeMem(puiFenceFWAddrs); OSFreeMem(pui32FenceValues); OSFreeMem(puiUpdateFWAddrs); OSFreeMem(pui32UpdateValues); OSFreeMem(pauiIntFenceUFOAddress); goto fail_fencevaluearray; } ui32IntClientUpdateCount = paui32ClientUpdateCount[i] + ui32NumUpdateSyncs; pauiIntUpdateUFOAddress = OSAllocMem(sizeof(*pauiIntUpdateUFOAddress)* ui32IntClientUpdateCount); if (pauiIntUpdateUFOAddress == IMG_NULL) { /* Free memory created by PVRFDSyncQueryFencesKM */ OSFreeMem(puiFenceFWAddrs); OSFreeMem(pui32FenceValues); OSFreeMem(puiUpdateFWAddrs); OSFreeMem(pui32UpdateValues); OSFreeMem(pauiIntFenceUFOAddress); OSFreeMem(paui32IntFenceValue); goto fail_updateUFOarray; } paui32IntUpdateValue = OSAllocMem(sizeof(*paui32IntUpdateValue)* ui32IntClientUpdateCount); if (paui32IntUpdateValue == IMG_NULL) { /* Free memory created by PVRFDSyncQueryFencesKM */ OSFreeMem(puiFenceFWAddrs); OSFreeMem(pui32FenceValues); OSFreeMem(puiUpdateFWAddrs); OSFreeMem(pui32UpdateValues); OSFreeMem(pauiIntFenceUFOAddress); OSFreeMem(paui32IntFenceValue); OSFreeMem(pauiIntUpdateUFOAddress); goto fail_updatevaluearray; } SYNC_MERGE_CLIENT_FENCES(ui32IntClientFenceCount, pauiIntFenceUFOAddress, paui32IntFenceValue, ui32NumFenceSyncs, puiFenceFWAddrs, pui32FenceValues, paui32ClientFenceCount[i], papauiClientFenceUFOAddress[i], papaui32ClientFenceValue[i]); SYNC_MERGE_CLIENT_UPDATES(ui32IntClientUpdateCount, pauiIntUpdateUFOAddress, paui32IntUpdateValue, ui32NumUpdateSyncs, puiUpdateFWAddrs, pui32UpdateValues, paui32ClientUpdateCount[i], papauiClientUpdateUFOAddress[i], papaui32ClientUpdateValue[i]); if (ui32NumFenceSyncs || ui32NumUpdateSyncs) { PDUMPCOMMENT("(TQ) Android native fences in use: %u fence syncs, %u update syncs", ui32NumFenceSyncs, ui32NumUpdateSyncs); } /* Free the data created by PVRFDSyncQueryFencesKM as it has now been merged into *IntClient* */ OSFreeMem(puiFenceFWAddrs); OSFreeMem(pui32FenceValues); OSFreeMem(puiUpdateFWAddrs); OSFreeMem(pui32UpdateValues); bSyncsMerged = IMG_TRUE; } else #endif /* PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC */ { /* No client sync merging so just copy across the pointers */ ui32IntClientFenceCount = paui32ClientFenceCount[i]; pauiIntFenceUFOAddress = papauiClientFenceUFOAddress[i]; paui32IntFenceValue = papaui32ClientFenceValue[i]; ui32IntClientUpdateCount = paui32ClientUpdateCount[i]; pauiIntUpdateUFOAddress = papauiClientUpdateUFOAddress[i]; paui32IntUpdateValue = papaui32ClientUpdateValue[i]; } /* Create the command helper data for this command */ eError = RGXCmdHelperInitCmdCCB(psClientCCB, ui32IntClientFenceCount, pauiIntFenceUFOAddress, paui32IntFenceValue, ui32IntClientUpdateCount, pauiIntUpdateUFOAddress, paui32IntUpdateValue, paui32ServerSyncCount[i], papaui32ServerSyncFlags[i], papapsServerSyncs[i], paui32FWCommandSize[i], papaui8FWCommand[i], eType, bPDumpContinuous, pszCommandName, psCmdHelper); if (eError != PVRSRV_OK) { goto fail_initcmd; } } /* Acquire space for all the commands in one go */ if (ui323DCmdCount) { eError = RGXCmdHelperAcquireCmdCCB(ui323DCmdCount, &pas3DCmdHelper[0], &bKick3D); if (eError != PVRSRV_OK) { if (bKick3D) { ui323DCmdCount = 0; ui322DCmdCount = 0; } else { goto fail_3dcmdacquire; } } } if (ui322DCmdCount) { eError = RGXCmdHelperAcquireCmdCCB(ui322DCmdCount, &pas2DCmdHelper[0], &bKick2D); if (eError != PVRSRV_OK) { if (bKick2D || bKick3D) { ui323DCmdCount = 0; ui322DCmdCount = 0; } else { goto fail_2dcmdacquire; } } } /* We should acquire the kernel CCB(s) space here as the schedule could fail and we would have to roll back all the syncs */ /* Only do the command helper release (which takes the server sync operations if the acquire succeeded */ if (ui323DCmdCount) { RGXCmdHelperReleaseCmdCCB(ui323DCmdCount, &pas3DCmdHelper[0], "TQ_3D", FWCommonContextGetFWAddress(psTransferContext->s3DData.psServerCommonContext).ui32Addr); } if (ui322DCmdCount) { RGXCmdHelperReleaseCmdCCB(ui322DCmdCount, &pas2DCmdHelper[0], "TQ_2D", FWCommonContextGetFWAddress(psTransferContext->s2DData.psServerCommonContext).ui32Addr); } /* Even if we failed to acquire the client CCB space we might still need to kick the HW to process a padding packet to release space for us next time round */ if (bKick3D) { RGXFWIF_KCCB_CMD s3DKCCBCmd; /* Construct the kernel 3D CCB command. */ s3DKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_KICK; s3DKCCBCmd.uCmdData.sCmdKickData.psContext = FWCommonContextGetFWAddress(psTransferContext->s3DData.psServerCommonContext); s3DKCCBCmd.uCmdData.sCmdKickData.ui32CWoffUpdate = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psTransferContext->s3DData.psServerCommonContext)); s3DKCCBCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl = 0; LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) { eError2 = RGXScheduleCommand(psDeviceNode->pvDevice, RGXFWIF_DM_3D, &s3DKCCBCmd, sizeof(s3DKCCBCmd), bPDumpContinuous); if (eError2 != PVRSRV_ERROR_RETRY) { break; } OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT); } END_LOOP_UNTIL_TIMEOUT(); } if (bKick2D) { RGXFWIF_KCCB_CMD s2DKCCBCmd; /* Construct the kernel 3D CCB command. */ s2DKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_KICK; s2DKCCBCmd.uCmdData.sCmdKickData.psContext = FWCommonContextGetFWAddress(psTransferContext->s2DData.psServerCommonContext); s2DKCCBCmd.uCmdData.sCmdKickData.ui32CWoffUpdate = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psTransferContext->s2DData.psServerCommonContext)); s2DKCCBCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl = 0; LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) { eError2 = RGXScheduleCommand(psDeviceNode->pvDevice, RGXFWIF_DM_2D, &s2DKCCBCmd, sizeof(s2DKCCBCmd), bPDumpContinuous); if (eError2 != PVRSRV_ERROR_RETRY) { break; } OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT); } END_LOOP_UNTIL_TIMEOUT(); } /* * Now check eError (which may have returned an error from our earlier calls * to RGXCmdHelperAcquireCmdCCB) - we needed to process any flush command first * so we check it now... */ if (eError != PVRSRV_OK ) { goto fail_2dcmdacquire; } #if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) /* Free the merged sync memory if required */ if (bSyncsMerged) { OSFreeMem(pauiIntFenceUFOAddress); OSFreeMem(paui32IntFenceValue); OSFreeMem(pauiIntUpdateUFOAddress); OSFreeMem(paui32IntUpdateValue); } #if defined(NO_HARDWARE) for (i = 0; i < ui32NumFenceFDs; i++) { eError = PVRFDSyncNoHwUpdateFenceKM(paui32FenceFDs[i]); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "%s: Failed nohw update on fence fd=%d (%s)", __func__, paui32FenceFDs[i], PVRSRVGetErrorStringKM(eError))); } } #endif #endif #if !defined(WDDM) OSFreeMem(pas2DCmdHelper); OSFreeMem(pas3DCmdHelper); #endif return PVRSRV_OK; /* No resources are created in this function so there is nothing to free unless we had to merge syncs. If we fail after the client CCB acquire there is still nothing to do as only the client CCB release will modify the client CCB */ fail_2dcmdacquire: fail_3dcmdacquire: fail_initcmd: #if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) if (bSyncsMerged) { OSFreeMem(pauiIntFenceUFOAddress); OSFreeMem(paui32IntFenceValue); OSFreeMem(pauiIntUpdateUFOAddress); OSFreeMem(paui32IntUpdateValue); } fail_updatevaluearray: fail_updateUFOarray: fail_fencevaluearray: fail_fenceUFOarray: fail_fdsync: #endif fail_pdumpcheck: fail_cmdtype: PVR_ASSERT(eError != PVRSRV_OK); #if !defined(WDDM) OSFreeMem(pas2DCmdHelper); fail_alloc2dhelper: OSFreeMem(pas3DCmdHelper); fail_alloc3dhelper: #endif return eError; }
/*! ****************************************************************************** @Function PVRSRVAllocHandle @Description Allocate a handle @Input phHandle - location for new handle pvData - pointer to resource to be associated with the handle eType - the type of resource @Output phHandle - points to new handle @Return Error code or PVRSRV_OK ******************************************************************************/ PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag) { IMG_HANDLE hHandle; PVRSRV_ERROR eError; *phHandle = IMG_NULL; /* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE); PVR_ASSERT(gpsHandleFuncs); if (psBase == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandle: Missing handle base")); eError = PVRSRV_ERROR_INVALID_PARAMS; goto exit_AllocHandle; } if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI)) { /* See if there is already a handle for this data pointer */ hHandle = FindHandle(psBase, pvData, eType, IMG_NULL); if (hHandle != IMG_NULL) { HANDLE_DATA *psHandleData = IMG_NULL; eError = GetHandleData(psBase, &psHandleData, hHandle, eType); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandle: Lookup of existing handle failed (%s)", PVRSRVGetErrorStringKM(eError))); goto exit_AllocHandle; } /* * If the client is willing to share a handle, and the * existing handle is marked as shareable, return the * existing handle. */ if (TEST_FLAG(psHandleData->eFlag & eFlag, PVRSRV_HANDLE_ALLOC_FLAG_SHARED)) { psHandleData->ui32Refs++; *phHandle = hHandle; eError = PVRSRV_OK; goto exit_AllocHandle; } eError = PVRSRV_ERROR_HANDLE_NOT_SHAREABLE; goto exit_AllocHandle; } } eError = AllocHandle(psBase, phHandle, pvData, eType, eFlag, IMG_NULL); exit_AllocHandle: return eError; }
PVRSRV_ERROR RGXPreKickCacheCommand(PVRSRV_RGXDEV_INFO *psDevInfo) { PVRSRV_DEVICE_NODE *psDeviceNode = psDevInfo->psDeviceNode; RGXFWIF_KCCB_CMD sFlushCmd; PVRSRV_ERROR eError = PVRSRV_OK; RGXFWIF_DM eDMcount = RGXFWIF_DM_MAX; if (!ui32CacheOpps) { goto _PVRSRVPowerLock_Exit; } sFlushCmd.eCmdType = RGXFWIF_KCCB_CMD_MMUCACHE; /* Set which memory context this command is for (all ctxs for now) */ ui32CacheOpps |= RGXFWIF_MMUCACHEDATA_FLAGS_CTX_ALL; #if 0 sFlushCmd.uCmdData.sMMUCacheData.psMemoryContext = ??? #endif /* PVRSRVPowerLock guarantees atomicity between commands and global variables consistency. * This is helpful in a scenario with several applications allocating resources. */ eError = PVRSRVPowerLock(); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_WARNING, "RGXPreKickCacheCommand: failed to acquire powerlock (%s)", PVRSRVGetErrorStringKM(eError))); goto _PVRSRVPowerLock_Exit; } PDUMPPOWCMDSTART(); eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_ON, IMG_FALSE); PDUMPPOWCMDEND(); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_WARNING, "RGXPreKickCacheCommand: failed to transition RGX to ON (%s)", PVRSRVGetErrorStringKM(eError))); goto _PVRSRVSetDevicePowerStateKM_Exit; } sFlushCmd.uCmdData.sMMUCacheData.ui32Flags = ui32CacheOpps; sFlushCmd.uCmdData.sMMUCacheData.ui32CacheSequenceNum = ++ui32CacheOpSequence; #if defined(PDUMP) PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Submit MMU flush and invalidate (flags = 0x%08x, cache operation sequence = %u)", ui32CacheOpps, ui32CacheOpSequence); #endif ui32CacheOpps = 0; /* Schedule MMU cache command */ do { eDMcount--; eError = RGXSendCommandRaw(psDevInfo, eDMcount, &sFlushCmd, sizeof(RGXFWIF_KCCB_CMD), PDUMP_FLAGS_CONTINUOUS); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"RGXPreKickCacheCommand: Failed to schedule MMU cache command \ to DM=%d with error (%u)", eDMcount, eError)); break; } } while(eDMcount > 0); _PVRSRVSetDevicePowerStateKM_Exit: PVRSRVPowerUnlock(); _PVRSRVPowerLock_Exit: return eError; }
/*! ****************************************************************************** @Function AcquireHandle @Description Acquire a new handle @Input psBase - Pointer to handle base structure phHandle - Points to a handle pointer pvData - Pointer to resource to be associated with the handle @Output phHandle - Points to a handle pointer @Return Error code or PVRSRV_OK ******************************************************************************/ static PVRSRV_ERROR AcquireHandle(HANDLE_IMPL_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData) { IMG_UINT32 ui32NewIndex = BASE_TO_TOTAL_INDICES(psBase); HANDLE_IMPL_DATA *psNewHandleData = IMG_NULL; PVRSRV_ERROR eError; PVR_ASSERT(psBase != IMG_NULL); PVR_ASSERT(phHandle != IMG_NULL); PVR_ASSERT(pvData != IMG_NULL); /* Ensure there is a free handle */ eError = EnsureFreeHandles(psBase, 1); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "%s: EnsureFreeHandles failed (%s)", __FUNCTION__, PVRSRVGetErrorStringKM(eError))); return eError; } PVR_ASSERT(psBase->ui32TotalFreeHandCount != 0); if (!psBase->bPurgingEnabled) { /* Array index of first free handle */ ui32NewIndex = psBase->ui32FirstFreeIndex; /* Get handle array entry */ psNewHandleData = INDEX_TO_HANDLE_DATA(psBase, ui32NewIndex); } else { IMG_UINT32 ui32BlockedIndex; /* * If purging is enabled, we always try to allocate handles * at the front of the array, to increase the chances that * the size of the handle array can be reduced by a purge. * No linked list of free handles is kept; we search for * free handles as required. */ /* * ui32FirstFreeIndex should only be set when a new batch of * handle structures is allocated, and should always be a * multiple of the block size. */ PVR_ASSERT((psBase->ui32FirstFreeIndex % HANDLE_BLOCK_SIZE) == 0); for (ui32BlockedIndex = ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(psBase->ui32FirstFreeIndex); ui32BlockedIndex < psBase->ui32TotalHandCount; ui32BlockedIndex += HANDLE_BLOCK_SIZE) { HANDLE_BLOCK *psHandleBlock = BASE_AND_INDEX_TO_HANDLE_BLOCK(psBase, ui32BlockedIndex); if (psHandleBlock->ui32FreeHandCount == 0) { continue; } for (ui32NewIndex = ui32BlockedIndex; ui32NewIndex < ui32BlockedIndex + HANDLE_BLOCK_SIZE; ui32NewIndex++) { psNewHandleData = INDEX_TO_HANDLE_DATA(psBase, ui32NewIndex); if (psNewHandleData->pvData == IMG_NULL) { break; } } } psBase->ui32FirstFreeIndex = 0; PVR_ASSERT(INDEX_IS_VALID(psBase, ui32NewIndex)); } PVR_ASSERT(psNewHandleData != IMG_NULL); psBase->ui32TotalFreeHandCount--; PVR_ASSERT(INDEX_TO_BLOCK_FREE_HAND_COUNT(psBase, ui32NewIndex) <= HANDLE_BLOCK_SIZE); PVR_ASSERT(INDEX_TO_BLOCK_FREE_HAND_COUNT(psBase, ui32NewIndex) > 0); INDEX_TO_BLOCK_FREE_HAND_COUNT(psBase, ui32NewIndex)--; /* No free list management if purging is enabled */ if (!psBase->bPurgingEnabled) { /* Check whether the last free handle has been allocated */ if (psBase->ui32TotalFreeHandCount == 0) { PVR_ASSERT(psBase->ui32FirstFreeIndex == ui32NewIndex); PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == (ui32NewIndex + 1)); psBase->ui32LastFreeIndexPlusOne = 0; psBase->ui32FirstFreeIndex = 0; } else { /* * Update the first free handle index. * If the "next free index plus one" field in the new * handle structure is zero, the next free index is * the index of the new handle plus one. This * convention has been adopted to simplify the * initialisation of freshly allocated handle * space. */ if (psNewHandleData->ui32NextIndexPlusOne == 0) { psBase->ui32FirstFreeIndex = ui32NewIndex + 1; } else { psBase->ui32FirstFreeIndex = psNewHandleData->ui32NextIndexPlusOne - 1; } } } PVR_ASSERT(HANDLE_DATA_TO_HANDLE(psNewHandleData) == INDEX_TO_HANDLE(ui32NewIndex)); psNewHandleData->pvData = pvData; psNewHandleData->ui32NextIndexPlusOne = 0; /* Return the new handle to the client */ *phHandle = INDEX_TO_HANDLE(ui32NewIndex); #if defined(DEBUG_HANDLEALLOC_KM) PVR_DPF((PVR_DBG_MESSAGE, "Handle acquire base %p hdl %p", psBase, *phHandle)); #endif return PVRSRV_OK; }
PVRSRV_ERROR PVRSRVRGXSetComputeContextPriorityKM(CONNECTION_DATA *psConnection, RGX_SERVER_COMPUTE_CONTEXT *psComputeContext, IMG_UINT32 ui32Priority) { PVRSRV_ERROR eError; eError = ContextSetPriority(psComputeContext->psServerCommonContext, psConnection, psComputeContext->psDeviceNode->pvDevice, ui32Priority, RGXFWIF_DM_CDM); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "%s: Failed to set the priority of the compute context (%s)", __FUNCTION__, PVRSRVGetErrorStringKM(eError))); } return eError; }
/*! ****************************************************************************** @Function PVRSRVSetPowerStateKM @Description Set the system into a new state @Input eNewPowerState : @Input bForced : TRUE if the transition should not fail (e.g. OS request) @Return PVRSRV_ERROR ******************************************************************************/ IMG_EXPORT PVRSRV_ERROR PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState, IMG_BOOL bForced) { PVRSRV_ERROR eError; PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData(); IMG_UINT uiStage = 0; PVRSRV_DEV_POWER_STATE eNewDevicePowerState = _IsSystemStatePowered(eNewSysPowerState)? PVRSRV_DEV_POWER_STATE_DEFAULT : PVRSRV_DEV_POWER_STATE_OFF; /* require a proper power state */ if (eNewSysPowerState == PVRSRV_SYS_POWER_STATE_Unspecified) { return PVRSRV_ERROR_INVALID_PARAMS; } /* no power transition requested, so do nothing */ if (eNewSysPowerState == psPVRSRVData->eCurrentPowerState) { return PVRSRV_OK; } /* Prevent simultaneous SetPowerStateKM calls */ PVRSRVForcedPowerLock(); /* Perform pre transitions: first device and then sys layer */ eError = PVRSRVDevicePrePowerStateKM(IMG_TRUE, 0, eNewDevicePowerState, bForced); if (eError != PVRSRV_OK) { uiStage++; goto ErrorExit; } eError = PVRSRVSysPrePowerState(eNewSysPowerState, bForced); if (eError != PVRSRV_OK) { uiStage++; goto ErrorExit; } /* Perform system-specific post power transitions: first sys layer and then device */ eError = PVRSRVSysPostPowerState(eNewSysPowerState, bForced); if (eError != PVRSRV_OK) { uiStage++; goto ErrorExit; } eError = PVRSRVDevicePostPowerStateKM(IMG_TRUE, 0, eNewDevicePowerState, bForced); if (eError != PVRSRV_OK) { uiStage++; goto ErrorExit; } psPVRSRVData->eCurrentPowerState = eNewSysPowerState; psPVRSRVData->eFailedPowerState = PVRSRV_SYS_POWER_STATE_Unspecified; PVRSRVPowerUnlock(); /* Reprocess the devices' queues in case commands were blocked during the power transition. */ if (_IsSystemStatePowered(eNewSysPowerState) && PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL)) { PVRSRVCheckStatus(IMG_NULL); } return PVRSRV_OK; ErrorExit: /* save the power state for the re-attempt */ psPVRSRVData->eFailedPowerState = eNewSysPowerState; PVRSRVPowerUnlock(); PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetPowerStateKM: Transition from %d to %d FAILED (%s) at stage %d, forced: %d. Dumping debug info.", psPVRSRVData->eCurrentPowerState, eNewSysPowerState, PVRSRVGetErrorStringKM(eError), uiStage, bForced)); PVRSRVDebugRequest(DEBUG_REQUEST_VERBOSITY_MAX); return eError; }
/*! ****************************************************************************** @Function PVRSRVSetDevicePowerStateKM @Description Set the Device into a new state @Input ui32DeviceIndex : device index @Input eNewPowerState : New power state @Input bForced : TRUE if the transition should not fail (e.g. OS request) @Return PVRSRV_ERROR ******************************************************************************/ IMG_EXPORT PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(IMG_UINT32 ui32DeviceIndex, PVRSRV_DEV_POWER_STATE eNewPowerState, IMG_BOOL bForced) { PVRSRV_DATA* psPVRSRVData = PVRSRVGetPVRSRVData(); PVRSRV_ERROR eError; PVRSRV_DEV_POWER_STATE eOldPowerState; eError = PVRSRVGetDevicePowerState(ui32DeviceIndex, &eOldPowerState); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_WARNING, "PVRSRVSetDevicePowerStateKM: Couldn't read power state.")); eOldPowerState = PVRSRV_DEV_POWER_STATE_DEFAULT; } #if defined(PDUMP) if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT) { /* Pdump a power-up regardless of the default state. Then disable pdump and transition to the default power state. This ensures that a power-up is always present in the pdump when necessary. */ eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_ON, bForced); if(eError != PVRSRV_OK) { goto Exit; } eError = PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_ON, bForced); if (eError != PVRSRV_OK) { goto Exit; } PDUMPPOWCMDSTART(); } #endif /* PDUMP */ eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState, bForced); if(eError != PVRSRV_OK) { if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT) { PDUMPPOWCMDEND(); } goto Exit; } eError = PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState, bForced); if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT) { PDUMPPOWCMDEND(); } /* Signal Device Watchdog Thread about power mode change. */ if (eOldPowerState != eNewPowerState && eNewPowerState == PVRSRV_DEV_POWER_STATE_ON) { psPVRSRVData->ui32DevicesWatchdogPwrTrans++; if (psPVRSRVData->ui32DevicesWatchdogTimeout == DEVICES_WATCHDOG_POWER_OFF_SLEEP_TIMEOUT) { if (psPVRSRVData->hDevicesWatchdogEvObj) { eError = OSEventObjectSignal(psPVRSRVData->hDevicesWatchdogEvObj); PVR_LOG_IF_ERROR(eError, "OSEventObjectSignal"); } } } Exit: if (eError == PVRSRV_ERROR_DEVICE_POWER_CHANGE_DENIED) { PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVSetDevicePowerStateKM : Transition to %d was denied, Forced=%d", eNewPowerState, bForced)); } else if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_WARNING, "PVRSRVSetDevicePowerStateKM : Transition to %d FAILED (%s)", eNewPowerState, PVRSRVGetErrorStringKM(eError))); } return eError; }
/*! ****************************************************************************** @Function FreeHandle @Description Free a handle data structure. @Input psBase - Pointer to handle base structure hHandle - Handle to be freed eType - Type of the handle to be freed ppvData - Location for data associated with the freed handle @Output ppvData - Points to data that was associated with the freed handle @Return PVRSRV_OK or PVRSRV_ERROR ******************************************************************************/ static PVRSRV_ERROR FreeHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType, IMG_VOID **ppvData) { HANDLE_DATA *psHandleData = IMG_NULL; HANDLE_DATA *psReleasedHandleData; PVRSRV_ERROR eError; eError = GetHandleData(psBase, &psHandleData, hHandle, eType); if (eError != PVRSRV_OK) { return eError; } PVR_ASSERT(psHandleData->ui32Refs>0); psHandleData->ui32Refs--; if (psHandleData->ui32Refs > 0) { /* Reference count still positive, only possible for shared handles */ PVR_ASSERT(TEST_ALLOC_FLAG(psHandleData, PVRSRV_HANDLE_ALLOC_FLAG_SHARED)); return PVRSRV_OK; } /* else reference count zero, time to clean up */ if (!TEST_ALLOC_FLAG(psHandleData, PVRSRV_HANDLE_ALLOC_FLAG_MULTI)) { HAND_KEY aKey; IMG_HANDLE hRemovedHandle; InitKey(aKey, psBase, psHandleData->pvData, psHandleData->eType, ParentIfPrivate(psHandleData)); hRemovedHandle = (IMG_HANDLE)HASH_Remove_Extended(psBase->psHashTab, aKey); PVR_ASSERT(hRemovedHandle != IMG_NULL); PVR_ASSERT(hRemovedHandle == psHandleData->hHandle); PVR_UNREFERENCED_PARAMETER(hRemovedHandle); } eError = UnlinkFromParent(psBase, psHandleData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "FreeHandle: Error whilst unlinking from parent handle (%s)", PVRSRVGetErrorStringKM(eError))); return eError; } /* Free children */ eError = IterateOverChildren(psBase, psHandleData, FreeHandleWrapper); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "FreeHandle: Error whilst freeing subhandles (%s)", PVRSRVGetErrorStringKM(eError))); return eError; } eError = gpsHandleFuncs->pfnReleaseHandle(psBase->psImplBase, psHandleData->hHandle, (IMG_VOID **)&psReleasedHandleData); if (eError == PVRSRV_OK) { PVR_ASSERT(psReleasedHandleData == psHandleData); } if (ppvData) { *ppvData = psHandleData->pvData; } OSFreeMem(psHandleData); return eError; }
PVRSRV_ERROR RGXCreateCCB(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_UINT32 ui32CCBSizeLog2, CONNECTION_DATA *psConnectionData, const IMG_CHAR *pszName, RGX_SERVER_COMMON_CONTEXT *psServerCommonContext, RGX_CLIENT_CCB **ppsClientCCB, DEVMEM_MEMDESC **ppsClientCCBMemDesc, DEVMEM_MEMDESC **ppsClientCCBCtrlMemDesc) { PVRSRV_ERROR eError; DEVMEM_FLAGS_T uiClientCCBMemAllocFlags, uiClientCCBCtlMemAllocFlags; IMG_UINT32 ui32AllocSize = (1U << ui32CCBSizeLog2); RGX_CLIENT_CCB *psClientCCB; psClientCCB = OSAllocMem(sizeof(*psClientCCB)); if (psClientCCB == IMG_NULL) { eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto fail_alloc; } psClientCCB->psServerCommonContext = psServerCommonContext; uiClientCCBMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) | PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(META_CACHED) | PVRSRV_MEMALLOCFLAG_GPU_READABLE | PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE | PVRSRV_MEMALLOCFLAG_CPU_READABLE | PVRSRV_MEMALLOCFLAG_UNCACHED | PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC | PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE; uiClientCCBCtlMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) | PVRSRV_MEMALLOCFLAG_GPU_READABLE | PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE | PVRSRV_MEMALLOCFLAG_CPU_READABLE | PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE | PVRSRV_MEMALLOCFLAG_UNCACHED | PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC | PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE; PDUMPCOMMENT("Allocate RGXFW cCCB"); eError = DevmemFwAllocateExportable(psDeviceNode, ui32AllocSize, uiClientCCBMemAllocFlags, "FirmwareClientCCB", &psClientCCB->psClientCCBMemDesc); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateCCBKM: Failed to allocate RGX client CCB (%s)", PVRSRVGetErrorStringKM(eError))); goto fail_alloc_ccb; } eError = DevmemAcquireCpuVirtAddr(psClientCCB->psClientCCBMemDesc, (IMG_VOID **) &psClientCCB->pui8ClientCCB); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateCCBKM: Failed to map RGX client CCB (%s)", PVRSRVGetErrorStringKM(eError))); goto fail_map_ccb; } PDUMPCOMMENT("Allocate RGXFW cCCB control"); eError = DevmemFwAllocateExportable(psDeviceNode, sizeof(RGXFWIF_CCCB_CTL), uiClientCCBCtlMemAllocFlags, "FirmwareClientCCBControl", &psClientCCB->psClientCCBCtrlMemDesc); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateCCBKM: Failed to allocate RGX client CCB control (%s)", PVRSRVGetErrorStringKM(eError))); goto fail_alloc_ccbctrl; } eError = DevmemAcquireCpuVirtAddr(psClientCCB->psClientCCBCtrlMemDesc, (IMG_VOID **) &psClientCCB->psClientCCBCtrl); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateCCBKM: Failed to map RGX client CCB (%s)", PVRSRVGetErrorStringKM(eError))); goto fail_map_ccbctrl; } psClientCCB->psClientCCBCtrl->ui32WriteOffset = 0; psClientCCB->psClientCCBCtrl->ui32ReadOffset = 0; psClientCCB->psClientCCBCtrl->ui32DepOffset = 0; psClientCCB->psClientCCBCtrl->ui32WrapMask = ui32AllocSize - 1; OSStringCopy(psClientCCB->szName, pszName); PDUMPCOMMENT("cCCB control"); DevmemPDumpLoadMem(psClientCCB->psClientCCBCtrlMemDesc, 0, sizeof(RGXFWIF_CCCB_CTL), PDUMP_FLAGS_CONTINUOUS); PVR_ASSERT(eError == PVRSRV_OK); psClientCCB->ui32HostWriteOffset = 0; psClientCCB->ui32LastPDumpWriteOffset = 0; psClientCCB->ui32Size = ui32AllocSize; #if defined REDUNDANT_SYNCS_DEBUG psClientCCB->ui32UpdateWriteIndex = 0; OSMemSet(psClientCCB->asFenceUpdateList, 0, sizeof(psClientCCB->asFenceUpdateList)); #endif eError = PDumpRegisterTransitionCallback(psConnectionData->psPDumpConnectionData, _RGXCCBPDumpTransition, psClientCCB, &psClientCCB->hTransition); if (eError != PVRSRV_OK) { goto fail_pdumpreg; } /* Note: Due to resman the connection structure could be freed before the client CCB so rather then saving off the connection structure save the PDump specific memory which is refcounted to ensure it's not freed too early */ psClientCCB->psPDumpConnectionData = psConnectionData->psPDumpConnectionData; PDUMPCOMMENT("New RGXFW cCCB(%s@%p) created", psClientCCB->szName, psClientCCB); *ppsClientCCB = psClientCCB; *ppsClientCCBMemDesc = psClientCCB->psClientCCBMemDesc; *ppsClientCCBCtrlMemDesc = psClientCCB->psClientCCBCtrlMemDesc; return PVRSRV_OK; fail_pdumpreg: DevmemReleaseCpuVirtAddr(psClientCCB->psClientCCBCtrlMemDesc); fail_map_ccbctrl: DevmemFwFree(psClientCCB->psClientCCBCtrlMemDesc); fail_alloc_ccbctrl: DevmemReleaseCpuVirtAddr(psClientCCB->psClientCCBMemDesc); fail_map_ccb: DevmemFwFree(psClientCCB->psClientCCBMemDesc); fail_alloc_ccb: OSFreeMem(psClientCCB); fail_alloc: PVR_ASSERT(eError != PVRSRV_OK); return eError; }