/****************************************************************************** FUNCTION : RGXReleaseCCB PURPOSE : Release a CCB that we have been writing to. PARAMETERS : psDevData - device data psCCB - the CCB RETURNS : None ******************************************************************************/ IMG_INTERNAL IMG_VOID RGXReleaseCCB(RGX_CLIENT_CCB *psClientCCB, IMG_UINT32 ui32CmdSize, IMG_BOOL bPDumpContinuous) { IMG_UINT32 ui32PDumpFlags = bPDumpContinuous ? PDUMP_FLAGS_CONTINUOUS : 0; IMG_BOOL bInCaptureRange; IMG_BOOL bPdumpEnabled; PDumpIsCaptureFrameKM(&bInCaptureRange); bPdumpEnabled = (bInCaptureRange || bPDumpContinuous); /* Dump the CCB data */ if (bPdumpEnabled) { DevmemPDumpLoadMem(psClientCCB->psClientCCBMemDesc, psClientCCB->ui32HostWriteOffset, ui32CmdSize, ui32PDumpFlags); } /* * Update the CCB write offset. */ UPDATE_CCB_OFFSET(psClientCCB->ui32HostWriteOffset, ui32CmdSize, psClientCCB->ui32Size); /* PDumpSetFrame will detect as we Transition out of capture range for frame based data but if we are PDumping continuous data then we need to inform the PDump layer ourselves */ if (bPDumpContinuous && !bInCaptureRange) { PVRSRV_ERROR eError; /* Only Transitioning into capture range can cause an error */ eError = PDumpTransition(psClientCCB->psPDumpConnectionData, IMG_FALSE, IMG_TRUE); PVR_ASSERT(eError == PVRSRV_OK); } if (bPdumpEnabled) { /* Update the PDump write offset to show we PDumped this command */ psClientCCB->ui32LastPDumpWriteOffset = psClientCCB->ui32HostWriteOffset; } #if defined(NO_HARDWARE) /* The firmware is not running, it cannot update these; we do here instead. */ psClientCCB->psClientCCBCtrl->ui32ReadOffset = psClientCCB->ui32HostWriteOffset; psClientCCB->psClientCCBCtrl->ui32DepOffset = psClientCCB->ui32HostWriteOffset; #endif }
/****************************************************************************** FUNCTION : RGXReleaseCCB PURPOSE : Release a CCB that we have been writing to. PARAMETERS : psDevData - device data psCCB - the CCB RETURNS : None ******************************************************************************/ IMG_INTERNAL IMG_VOID RGXReleaseCCB(RGX_CLIENT_CCB *psClientCCB, IMG_UINT32 ui32CmdSize, IMG_BOOL bPDumpContinuous) { IMG_UINT32 ui32PDumpFlags = bPDumpContinuous ? PDUMP_FLAGS_CONTINUOUS : 0; IMG_BOOL bInCaptureRange; IMG_BOOL bPdumpEnabled; PDumpIsCaptureFrameKM(&bInCaptureRange); bPdumpEnabled = (bInCaptureRange || bPDumpContinuous); /* Dump the CCB data */ if (bPdumpEnabled) { DevmemPDumpLoadMem(psClientCCB->psClientCCBMemDesc, psClientCCB->ui32HostWriteOffset, ui32CmdSize, ui32PDumpFlags); } /* * Check if there have been any fences written that will already be * satistified by a previously written update in this CCB. */ #if defined REDUNDANT_SYNCS_DEBUG { IMG_UINT8 *pui8BufferStart = (IMG_PVOID)((IMG_UINTPTR_T)psClientCCB->pui8ClientCCB + psClientCCB->ui32HostWriteOffset); IMG_UINT8 *pui8BufferEnd = (IMG_PVOID)((IMG_UINTPTR_T)psClientCCB->pui8ClientCCB + psClientCCB->ui32HostWriteOffset + ui32CmdSize); /* Walk through the commands in this section of CCB being released... */ while (pui8BufferStart < pui8BufferEnd) { RGXFWIF_CCB_CMD_HEADER *psCmdHeader = (RGXFWIF_CCB_CMD_HEADER *) pui8BufferStart; if (psCmdHeader->eCmdType == RGXFWIF_CCB_CMD_TYPE_UPDATE) { /* If an UPDATE then record the value incase a later fence depends on it. */ IMG_UINT32 ui32NumUpdates = psCmdHeader->ui32CmdSize / sizeof(RGXFWIF_UFO); IMG_UINT32 i; for (i = 0; i < ui32NumUpdates; i++) { RGXFWIF_UFO *psUFOPtr = ((RGXFWIF_UFO*)(pui8BufferStart + sizeof(RGXFWIF_CCB_CMD_HEADER))) + i; psClientCCB->asFenceUpdateList[psClientCCB->ui32UpdateWriteIndex++] = *psUFOPtr; psClientCCB->ui32UpdateWriteIndex &= (RGX_CCCB_FENCE_UPDATE_LIST_SIZE-1); } } else if (psCmdHeader->eCmdType == RGXFWIF_CCB_CMD_TYPE_FENCE) { IMG_UINT32 ui32NumFences = psCmdHeader->ui32CmdSize / sizeof(RGXFWIF_UFO); IMG_UINT32 i; for (i = 0; i < ui32NumFences; i++) { RGXFWIF_UFO *psUFOPtr = ((RGXFWIF_UFO*)(pui8BufferStart + sizeof(RGXFWIF_CCB_CMD_HEADER))) + i; IMG_UINT32 ui32UpdateIndex; /* Check recently queued updates to see if this fence will be satisfied by the time it is checked. */ for (ui32UpdateIndex = 0; ui32UpdateIndex < RGX_CCCB_FENCE_UPDATE_LIST_SIZE; ui32UpdateIndex++) { RGXFWIF_UFO *psUpdatePtr = &psClientCCB->asFenceUpdateList[ui32UpdateIndex]; if (psUFOPtr->puiAddrUFO.ui32Addr == psUpdatePtr->puiAddrUFO.ui32Addr && psUFOPtr->ui32Value == psUpdatePtr->ui32Value) { PVR_DPF((PVR_DBG_WARNING, "Redundant fence found in cCCB(%p) - 0x%x -> 0x%x", psClientCCB, psUFOPtr->puiAddrUFO.ui32Addr, psUFOPtr->ui32Value)); //psUFOPtr->puiAddrUFO.ui32Addr = 0; break; } } } } else if (psCmdHeader->eCmdType == RGXFWIF_CCB_CMD_TYPE_FENCE_PR) { IMG_UINT32 ui32NumFences = psCmdHeader->ui32CmdSize / sizeof(RGXFWIF_UFO); IMG_UINT32 i; for (i = 0; i < ui32NumFences; i++) { RGXFWIF_UFO *psUFOPtr = ((RGXFWIF_UFO*)(pui8BufferStart + sizeof(RGXFWIF_CCB_CMD_HEADER))) + i; IMG_UINT32 ui32UpdateIndex; /* Check recently queued updates to see if this fence will be satisfied by the time it is checked. */ for (ui32UpdateIndex = 0; ui32UpdateIndex < RGX_CCCB_FENCE_UPDATE_LIST_SIZE; ui32UpdateIndex++) { RGXFWIF_UFO *psUpdatePtr = &psClientCCB->asFenceUpdateList[ui32UpdateIndex]; /* * The PR-fence will be met if the update value is >= the required fence value. E.g. * the difference between the update value and fence value is positive. */ if (psUFOPtr->puiAddrUFO.ui32Addr == psUpdatePtr->puiAddrUFO.ui32Addr && ((psUpdatePtr->ui32Value - psUFOPtr->ui32Value) & (1U << 31)) == 0) { PVR_DPF((PVR_DBG_WARNING, "Redundant PR fence found in cCCB(%p) - 0x%x -> 0x%x", psClientCCB, psUFOPtr->puiAddrUFO.ui32Addr, psUFOPtr->ui32Value)); //psUFOPtr->puiAddrUFO.ui32Addr = 0; break; } } } } /* Move to the next command in this section of CCB being released... */ pui8BufferStart += sizeof(RGXFWIF_CCB_CMD_HEADER) + psCmdHeader->ui32CmdSize; } } #endif /* REDUNDANT_SYNCS_DEBUG */ /* * Update the CCB write offset. */ UPDATE_CCB_OFFSET(psClientCCB->ui32HostWriteOffset, ui32CmdSize, psClientCCB->ui32Size); /* PDumpSetFrame will detect as we Transition out of capture range for frame based data but if we are PDumping continuous data then we need to inform the PDump layer ourselves */ if (bPDumpContinuous && !bInCaptureRange) { PVRSRV_ERROR eError; /* Only Transitioning into capture range can cause an error */ eError = PDumpTransition(psClientCCB->psPDumpConnectionData, IMG_FALSE, IMG_TRUE); PVR_ASSERT(eError == PVRSRV_OK); } if (bPdumpEnabled) { /* Update the PDump write offset to show we PDumped this command */ psClientCCB->ui32LastPDumpWriteOffset = psClientCCB->ui32HostWriteOffset; } #if defined(NO_HARDWARE) /* The firmware is not running, it cannot update these; we do here instead. */ psClientCCB->psClientCCBCtrl->ui32ReadOffset = psClientCCB->ui32HostWriteOffset; psClientCCB->psClientCCBCtrl->ui32DepOffset = psClientCCB->ui32HostWriteOffset; #endif }
/****************************************************************************** FUNCTION : RGXAcquireCCB PURPOSE : Obtains access to write some commands to a CCB PARAMETERS : psClientCCB - The client CCB ui32CmdSize - How much space is required ppvBufferSpace - Pointer to space in the buffer bPDumpContinuous - Should this be PDump continuous? RETURNS : PVRSRV_ERROR ******************************************************************************/ IMG_INTERNAL PVRSRV_ERROR RGXAcquireCCB(RGX_CLIENT_CCB *psClientCCB, IMG_UINT32 ui32CmdSize, IMG_PVOID *ppvBufferSpace, IMG_BOOL bPDumpContinuous) { PVRSRV_ERROR eError; IMG_UINT32 ui32PDumpFlags = bPDumpContinuous ? PDUMP_FLAGS_CONTINUOUS : 0; IMG_BOOL bInCaptureRange; IMG_BOOL bPdumpEnabled; PDumpIsCaptureFrameKM(&bInCaptureRange); bPdumpEnabled = (bInCaptureRange || bPDumpContinuous); /* PDumpSetFrame will detect as we Transition into capture range for frame based data but if we are PDumping continuous data then we need to inform the PDump layer ourselves */ if (bPDumpContinuous && !bInCaptureRange) { eError = PDumpTransition(psClientCCB->psPDumpConnectionData, IMG_TRUE, IMG_TRUE); if (eError != PVRSRV_OK) { return eError; } } /* Check that the CCB can hold this command + padding */ if ((ui32CmdSize + PADDING_COMMAND_SIZE + 1) > psClientCCB->ui32Size) { PVR_DPF((PVR_DBG_ERROR, "Command size (%d bytes) too big for CCB (%d bytes)\n", ui32CmdSize, psClientCCB->ui32Size)); return PVRSRV_ERROR_CMD_TOO_BIG; } /* Check we don't overflow the end of the buffer and make sure we have enough for the padding command. */ if ((psClientCCB->ui32HostWriteOffset + ui32CmdSize + PADDING_COMMAND_SIZE) > psClientCCB->ui32Size) { RGXFWIF_CCB_CMD_HEADER *psHeader; IMG_VOID *pvHeader; PVRSRV_ERROR eError; IMG_UINT32 ui32Remain = psClientCCB->ui32Size - psClientCCB->ui32HostWriteOffset; /* We're at the end of the buffer without enough contiguous space */ eError = _RGXAcquireCCB(psClientCCB, ui32Remain, &pvHeader); if (eError != PVRSRV_OK) { /* It's possible no commands have been processed in which case as we can fail the padding allocation due to that fact we never allow the client CCB to be full */ return eError; } psHeader = pvHeader; psHeader->eCmdType = RGXFWIF_CCB_CMD_TYPE_PADDING; psHeader->ui32CmdSize = ui32Remain - sizeof(RGXFWIF_CCB_CMD_HEADER); PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "cCCB(%p): Padding cmd %d", psClientCCB, psHeader->ui32CmdSize); if (bPdumpEnabled) { DevmemPDumpLoadMem(psClientCCB->psClientCCBMemDesc, psClientCCB->ui32HostWriteOffset, ui32Remain, ui32PDumpFlags); } UPDATE_CCB_OFFSET(psClientCCB->ui32HostWriteOffset, ui32Remain, psClientCCB->ui32Size); } return _RGXAcquireCCB(psClientCCB, ui32CmdSize, ppvBufferSpace); }