PVRSRV_ERROR RGXKickSyncKM(PVRSRV_DEVICE_NODE *psDeviceNode, RGX_SERVER_COMMON_CONTEXT *psServerCommonContext, RGXFWIF_DM eDM, IMG_CHAR *pszCommandName, IMG_UINT32 ui32ClientFenceCount, PRGXFWIF_UFO_ADDR *pauiClientFenceUFOAddress, IMG_UINT32 *paui32ClientFenceValue, IMG_UINT32 ui32ClientUpdateCount, PRGXFWIF_UFO_ADDR *pauiClientUpdateUFOAddress, IMG_UINT32 *paui32ClientUpdateValue, IMG_UINT32 ui32ServerSyncPrims, IMG_UINT32 *paui32ServerSyncFlags, SERVER_SYNC_PRIMITIVE **pasServerSyncs, IMG_BOOL bPDumpContinuous) { RGXFWIF_KCCB_CMD sCmpKCCBCmd; RGX_CCB_CMD_HELPER_DATA asCmdHelperData[1]; IMG_BOOL bKickRequired; PVRSRV_ERROR eError; PVRSRV_ERROR eError2; IMG_UINT32 i; /* Sanity check the server fences */ for (i=0;i<ui32ServerSyncPrims;i++) { if (!(paui32ServerSyncFlags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK)) { PVR_DPF((PVR_DBG_ERROR, "%s: Server fence (on %s) must fence", __FUNCTION__, pszCommandName)); return PVRSRV_ERROR_INVALID_SYNC_PRIM_OP; } } eError = RGXCmdHelperInitCmdCCB(FWCommonContextGetClientCCB(psServerCommonContext), ui32ClientFenceCount, pauiClientFenceUFOAddress, paui32ClientFenceValue, ui32ClientUpdateCount, pauiClientUpdateUFOAddress, paui32ClientUpdateValue, ui32ServerSyncPrims, paui32ServerSyncFlags, pasServerSyncs, 0, /* ui32CmdSize */ IMG_NULL, /* pui8DMCmd */ IMG_NULL, /* ppPreAddr */ IMG_NULL, /* ppPostAddr */ IMG_NULL, /* ppRMWUFOAddr */ RGXFWIF_CCB_CMD_TYPE_NULL, bPDumpContinuous, pszCommandName, asCmdHelperData); if (eError != PVRSRV_OK) { goto fail_cmdinit; } eError = RGXCmdHelperAcquireCmdCCB(IMG_ARR_NUM_ELEMS(asCmdHelperData), asCmdHelperData, &bKickRequired); if ((eError != PVRSRV_OK) && (!bKickRequired)) { /* Only bail if no new data was submitted into the client CCB, we might have already submitted a padding packet which we should flush through the FW. */ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create client CCB command", __FUNCTION__)); goto fail_cmdaquire; } /* We should reserved space in the kernel CCB here and fill in the command directly. This is so if there isn't space in the kernel CCB we can return with retry back to services client before we take any operations */ /* We might only be kicking for flush out a padding packet so only submit the command if the create was successful */ if (eError == PVRSRV_OK) { /* All the required resources are ready at this point, we can't fail so take the required server sync operations and commit all the resources */ RGXCmdHelperReleaseCmdCCB(1, asCmdHelperData, pszCommandName, FWCommonContextGetFWAddress(psServerCommonContext).ui32Addr); } /* Construct the kernel compute CCB command. */ sCmpKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_KICK; sCmpKCCBCmd.uCmdData.sCmdKickData.psContext = FWCommonContextGetFWAddress(psServerCommonContext); sCmpKCCBCmd.uCmdData.sCmdKickData.ui32CWoffUpdate = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psServerCommonContext)); sCmpKCCBCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl = 0; /* * Submit the compute command to the firmware. */ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) { eError2 = RGXScheduleCommand(psDeviceNode->pvDevice, eDM, &sCmpKCCBCmd, sizeof(sCmpKCCBCmd), bPDumpContinuous); if (eError2 != PVRSRV_ERROR_RETRY) { break; } OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT); } END_LOOP_UNTIL_TIMEOUT(); if (eError2 != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "%s failed to schedule kernel CCB command. (0x%x)", __FUNCTION__, eError)); } /* * Now check eError (which may have returned an error from our earlier call * to RGXCmdHelperAcquireCmdCCB) - we needed to process any flush command first * so we check it now... */ if (eError != PVRSRV_OK ) { goto fail_cmdaquire; } return PVRSRV_OK; fail_cmdaquire: fail_cmdinit: return eError; }
IMG_EXPORT PVRSRV_ERROR PVRSRVRGXKickCDMKM(RGX_SERVER_COMPUTE_CONTEXT *psComputeContext, IMG_UINT32 ui32ClientFenceCount, SYNC_PRIMITIVE_BLOCK **pauiClientFenceUFOSyncPrimBlock, IMG_UINT32 *paui32ClientFenceSyncOffset, IMG_UINT32 *paui32ClientFenceValue, IMG_UINT32 ui32ClientUpdateCount, SYNC_PRIMITIVE_BLOCK **pauiClientUpdateUFOSyncPrimBlock, IMG_UINT32 *paui32ClientUpdateSyncOffset, IMG_UINT32 *paui32ClientUpdateValue, IMG_UINT32 ui32ServerSyncPrims, IMG_UINT32 *paui32ServerSyncFlags, SERVER_SYNC_PRIMITIVE **pasServerSyncs, IMG_UINT32 ui32CmdSize, IMG_PBYTE pui8DMCmd, IMG_BOOL bPDumpContinuous, IMG_UINT32 ui32ExtJobRef, IMG_UINT32 ui32IntJobRef) { RGXFWIF_KCCB_CMD sCmpKCCBCmd; RGX_CCB_CMD_HELPER_DATA asCmdHelperData[1]; IMG_BOOL bKickRequired; PVRSRV_ERROR eError; PVRSRV_ERROR eError2; IMG_UINT32 i; RGXFWIF_DEV_VIRTADDR pPreTimestamp; RGXFWIF_DEV_VIRTADDR pPostTimestamp; PRGXFWIF_UFO_ADDR pRMWUFOAddr; eError = SyncAddrListPopulate(&psComputeContext->sSyncAddrListFence, ui32ClientFenceCount, pauiClientFenceUFOSyncPrimBlock, paui32ClientFenceSyncOffset); if(eError != PVRSRV_OK) { goto err_populate_sync_addr_list; } eError = SyncAddrListPopulate(&psComputeContext->sSyncAddrListUpdate, ui32ClientUpdateCount, pauiClientUpdateUFOSyncPrimBlock, paui32ClientUpdateSyncOffset); if(eError != PVRSRV_OK) { goto err_populate_sync_addr_list; } /* Sanity check the server fences */ for (i=0;i<ui32ServerSyncPrims;i++) { if (!(paui32ServerSyncFlags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK)) { PVR_DPF((PVR_DBG_ERROR, "%s: Server fence (on CDM) must fence", __FUNCTION__)); return PVRSRV_ERROR_INVALID_SYNC_PRIM_OP; } } RGX_GetTimestampCmdHelper((PVRSRV_RGXDEV_INFO*) psComputeContext->psDeviceNode->pvDevice, & pPreTimestamp, & pPostTimestamp, & pRMWUFOAddr); eError = RGXCmdHelperInitCmdCCB(FWCommonContextGetClientCCB(psComputeContext->psServerCommonContext), ui32ClientFenceCount, psComputeContext->sSyncAddrListFence.pasFWAddrs, paui32ClientFenceValue, ui32ClientUpdateCount, psComputeContext->sSyncAddrListUpdate.pasFWAddrs, paui32ClientUpdateValue, ui32ServerSyncPrims, paui32ServerSyncFlags, pasServerSyncs, ui32CmdSize, pui8DMCmd, & pPreTimestamp, & pPostTimestamp, & pRMWUFOAddr, RGXFWIF_CCB_CMD_TYPE_CDM, bPDumpContinuous, "Compute", asCmdHelperData); if (eError != PVRSRV_OK) { goto fail_cmdinit; } eError = RGXCmdHelperAcquireCmdCCB(IMG_ARR_NUM_ELEMS(asCmdHelperData), asCmdHelperData, &bKickRequired); if ((eError != PVRSRV_OK) && (!bKickRequired)) { /* Only bail if no new data was submitted into the client CCB, we might have already submitted a padding packet which we should flush through the FW. */ PVR_DPF((PVR_DBG_ERROR, "RGXKickCDM: Failed to create client CCB command")); goto fail_cmdaquire; } /* We should reserved space in the kernel CCB here and fill in the command directly. This is so if there isn't space in the kernel CCB we can return with retry back to services client before we take any operations */ /* We might only be kicking for flush out a padding packet so only submit the command if the create was successful */ if (eError == PVRSRV_OK) { /* All the required resources are ready at this point, we can't fail so take the required server sync operations and commit all the resources */ RGXCmdHelperReleaseCmdCCB(1, asCmdHelperData, "CDM", FWCommonContextGetFWAddress(psComputeContext->psServerCommonContext).ui32Addr); } /* Construct the kernel compute CCB command. */ sCmpKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_KICK; sCmpKCCBCmd.uCmdData.sCmdKickData.psContext = FWCommonContextGetFWAddress(psComputeContext->psServerCommonContext); sCmpKCCBCmd.uCmdData.sCmdKickData.ui32CWoffUpdate = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psComputeContext->psServerCommonContext)); sCmpKCCBCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl = 0; /* * Submit the compute command to the firmware. */ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) { eError2 = RGXScheduleCommand(psComputeContext->psDeviceNode->pvDevice, RGXFWIF_DM_CDM, &sCmpKCCBCmd, sizeof(sCmpKCCBCmd), bPDumpContinuous); if (eError2 != PVRSRV_ERROR_RETRY) { break; } OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT); } END_LOOP_UNTIL_TIMEOUT(); if (eError2 != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXKickCDMKM failed to schedule kernel CCB command. (0x%x)", eError)); } #if defined(SUPPORT_GPUTRACE_EVENTS) else { RGXHWPerfFTraceGPUEnqueueEvent(psComputeContext->psDeviceNode->pvDevice, ui32ExtJobRef, ui32IntJobRef, "CDM"); } #endif /* * Now check eError (which may have returned an error from our earlier call * to RGXCmdHelperAcquireCmdCCB) - we needed to process any flush command first * so we check it now... */ if (eError != PVRSRV_OK ) { goto fail_cmdaquire; } return PVRSRV_OK; fail_cmdaquire: fail_cmdinit: err_populate_sync_addr_list: return eError; }
/* SysCreateConfigData */ PVRSRV_ERROR SysCreateConfigData(PVRSRV_SYSTEM_CONFIG **ppsSysConfig) { /* Sunxi Init */ RgxSunxiInit(); /* * Setup information about physical memory heap(s) we have */ gsPhysHeapFuncs.pfnCpuPAddrToDevPAddr = UMAPhysHeapCpuPAddrToDevPAddr; gsPhysHeapFuncs.pfnDevPAddrToCpuPAddr = UMAPhysHeapDevPAddrToCpuPAddr; gsPhysHeapConfig[0].ui32PhysHeapID = 0; gsPhysHeapConfig[0].pszPDumpMemspaceName = "SYSMEM"; gsPhysHeapConfig[0].eType = PHYS_HEAP_TYPE_UMA; gsPhysHeapConfig[0].psMemFuncs = &gsPhysHeapFuncs; gsPhysHeapConfig[0].hPrivData = IMG_NULL; #if defined(TDMETACODE) gsPhysHeapConfig[1].ui32PhysHeapID = 1; gsPhysHeapConfig[1].pszPDumpMemspaceName = "TDMETACODEMEM"; gsPhysHeapConfig[1].eType = PHYS_HEAP_TYPE_UMA; gsPhysHeapConfig[1].psMemFuncs = &gsPhysHeapFuncs; gsPhysHeapConfig[1].hPrivData = IMG_NULL; gsPhysHeapConfig[2].ui32PhysHeapID = 2; gsPhysHeapConfig[2].pszPDumpMemspaceName = "TDSECUREBUFMEM"; gsPhysHeapConfig[2].eType = PHYS_HEAP_TYPE_UMA; gsPhysHeapConfig[2].psMemFuncs = &gsPhysHeapFuncs; gsPhysHeapConfig[2].hPrivData = IMG_NULL; #endif gsSysConfig.pasPhysHeaps = &(gsPhysHeapConfig[0]); gsSysConfig.ui32PhysHeapCount = IMG_ARR_NUM_ELEMS(gsPhysHeapConfig); gsSysConfig.pui32BIFTilingHeapConfigs = gauiBIFTilingHeapXStrides; gsSysConfig.ui32BIFTilingHeapCount = IMG_ARR_NUM_ELEMS(gauiBIFTilingHeapXStrides); /* * Setup RGX specific timing data */ gsRGXTimingInfo.ui32CoreClockSpeed = RGX_SUNXI_CORE_CLOCK_SPEED; gsRGXTimingInfo.bEnableActivePM = IMG_TRUE; gsRGXTimingInfo.bEnableRDPowIsland = IMG_TRUE; gsRGXTimingInfo.ui32ActivePMLatencyms = SYS_RGX_ACTIVE_POWER_LATENCY_MS; /* *Setup RGX specific data */ gsRGXData.psRGXTimingInfo = &gsRGXTimingInfo; #if defined(TDMETACODE) gsRGXData.bHasTDMetaCodePhysHeap = IMG_TRUE; gsRGXData.uiTDMetaCodePhysHeapID = 1; gsRGXData.bHasTDSecureBufPhysHeap = IMG_TRUE; gsRGXData.uiTDSecureBufPhysHeapID = 2; #endif /* * Setup RGX device */ gsDevices[0].eDeviceType = PVRSRV_DEVICE_TYPE_RGX; gsDevices[0].pszName = "RGX"; /* Device setup information */ gsDevices[0].sRegsCpuPBase.uiAddr = SUNXI_GPU_PBASE; gsDevices[0].ui32RegsSize = SUNXI_GPU_SIZE; gsDevices[0].ui32IRQ = SUNXI_IRQ_GPU; gsDevices[0].bIRQIsShared = IMG_FALSE; /* Device's physical heap IDs */ gsDevices[0].aui32PhysHeapID[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL] = 0; gsDevices[0].aui32PhysHeapID[PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL] = 0; /* Power management on SUNXI system */ gsDevices[0].pfnPrePowerState = AwPrePowerState; gsDevices[0].pfnPostPowerState = AwPostPowerState; /* No clock frequency either */ gsDevices[0].pfnClockFreqGet = NULL; /* No interrupt handled either */ gsDevices[0].pfnInterruptHandled = IMG_NULL; gsDevices[0].pfnCheckMemAllocSize = SysCheckMemAllocSize; gsDevices[0].hDevData = &gsRGXData; /* * Setup system config */ gsSysConfig.pszSystemName = RGX_SUNXI_SYSTEM_NAME; gsSysConfig.uiDeviceCount = sizeof(gsDevices)/sizeof(gsDevices[0]); gsSysConfig.pasDevices = &gsDevices[0]; /* Power management on no SUNXI system */ gsSysConfig.pfnSysPrePowerState = AwSysPrePowerState; gsSysConfig.pfnSysPostPowerState = AwSysPostPowerState; /* no cache snooping */ gsSysConfig.eCacheSnoopingMode = PVRSRV_SYSTEM_SNOOP_NONE; /* Setup other system specific stuff */ #if defined(SUPPORT_ION) IonInit(NULL); #endif *ppsSysConfig = &gsSysConfig; return PVRSRV_OK; }