struct IMG_CPU_PHYADDR LinuxMemAreaToCpuPAddr(struct LinuxMemArea *psLinuxMemArea, u32 ui32ByteOffset) { struct IMG_CPU_PHYADDR CpuPAddr; CpuPAddr.uiAddr = 0; switch (psLinuxMemArea->eAreaType) { case LINUX_MEM_AREA_IOREMAP: { CpuPAddr = psLinuxMemArea->uData.sIORemap.CPUPhysAddr; CpuPAddr.uiAddr += ui32ByteOffset; break; } case LINUX_MEM_AREA_EXTERNAL_KV: { if (psLinuxMemArea->uData.sExternalKV.bPhysContig) { CpuPAddr = SysSysPAddrToCpuPAddr(psLinuxMemArea->uData. sExternalKV.uPhysAddr. SysPhysAddr); CpuPAddr.uiAddr += ui32ByteOffset; } else { u32 ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset); struct IMG_SYS_PHYADDR SysPAddr = psLinuxMemArea->uData.sExternalKV.uPhysAddr. pSysPhysAddr[ui32PageIndex]; CpuPAddr = SysSysPAddrToCpuPAddr(SysPAddr); CpuPAddr.uiAddr += ADDR_TO_PAGE_OFFSET(ui32ByteOffset); } break; } case LINUX_MEM_AREA_IO: { CpuPAddr = psLinuxMemArea->uData.sIO.CPUPhysAddr; CpuPAddr.uiAddr += ui32ByteOffset; break; } case LINUX_MEM_AREA_VMALLOC: { char *pCpuVAddr; pCpuVAddr = (char *) psLinuxMemArea->uData.sVmalloc. pvVmallocAddress; pCpuVAddr += ui32ByteOffset; CpuPAddr.uiAddr = VMallocToPhys(pCpuVAddr); break; } case LINUX_MEM_AREA_ALLOC_PAGES: { struct page *page; u32 ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset); page = psLinuxMemArea->uData.sPageList. pvPageList[ui32PageIndex]; CpuPAddr.uiAddr = page_to_phys(page); CpuPAddr.uiAddr += ADDR_TO_PAGE_OFFSET(ui32ByteOffset); break; } case LINUX_MEM_AREA_SUB_ALLOC: { CpuPAddr = OSMemHandleToCpuPAddr(psLinuxMemArea->uData. sSubAlloc. psParentLinuxMemArea, psLinuxMemArea->uData. sSubAlloc.ui32ByteOffset + ui32ByteOffset); break; } default: PVR_DPF(PVR_DBG_ERROR, "%s: Unknown Linux memory area type (%d)\n", __func__, psLinuxMemArea->eAreaType); } PVR_ASSERT(CpuPAddr.uiAddr); return CpuPAddr; }
/*********************************************************************************** Function Name : AssembleUSEASMInstrcutions Inputs : gc, psUSEASMInfo Outputs : psUSEASMInfo Returns : - Description : Calls USEASM to generate USE instructions for a list of USEASM instructions ************************************************************************************/ IMG_INTERNAL GLES1_MEMERROR AssembleUSEASMInstructions(GLES1Context *gc, GLESUSEASMInfo *psUSEASMInfo) { USE_REGISTER sOutputRegister= {0, USEASM_REGTYPE_OUTPUT, 0, 0, 0}; IMG_UINT32 auKeepOutputReg[1]= { 0 }; IMG_UINT32 auKeepTempReg[1]= { 0 }; IMG_UINT32 auKeepPAReg[1]= { 0 }; USEASM_CONTEXT sUseasmContext; USEOPT_DATA sUseoptData; SGX_CORE_INFO sTarget; IMG_UINT32 i; if(!psUSEASMInfo->psFirstUSEASMInstruction) { PVR_DPF((PVR_DBG_ERROR,"AssembleUSEASMInstructions(): No USEASM input instructions")); psUSEASMInfo->ui32NumHWInstructions = 0; return GLES1_GENERAL_MEM_ERROR; } psUSEASMInfo->pui32HWInstructions = GLES1Malloc(gc, psUSEASMInfo->ui32NumMainUSEASMInstructions * EURASIA_USE_INSTRUCTION_SIZE); if(!psUSEASMInfo->pui32HWInstructions) { PVR_DPF((PVR_DBG_ERROR,"AssembleUSEASMInstructions(): Failed to allocate memory for HW instructions")); psUSEASMInfo->ui32NumHWInstructions = 0; return GLES1_HOST_MEM_ERROR; } sTarget.eID = SGX_CORE_ID; #if defined(SGX_CORE_REV) sTarget.uiRev = SGX_CORE_REV; #else sTarget.uiRev = 0; /* use head revision */ #endif sUseasmContext.pvContext = (IMG_VOID *)gc; sUseasmContext.pvLabelState = IMG_NULL; sUseasmContext.pfnRealloc = UseasmRealloc; sUseasmContext.pfnGetLabelAddress = UseAssemblerGetLabelAddress; sUseasmContext.pfnSetLabelAddress = UseAssemblerSetLabelAddress; sUseasmContext.pfnGetLabelName = UseAssemblerGetLabelName; sUseasmContext.pfnAssemblerError = UseAssemblerError; sUseoptData.pfnAlloc = UseasmAlloc; sUseoptData.pfnFree = UseasmFree; sUseoptData.uNumTempRegs = psUSEASMInfo->ui32MaxTempNumber + 1; sUseoptData.uNumPARegs = psUSEASMInfo->ui32MaxPrimaryNumber + 1; sUseoptData.uNumOutputRegs = 1; sUseoptData.auKeepTempReg = auKeepTempReg; sUseoptData.auKeepPAReg = auKeepPAReg; for(i=0; i<sUseoptData.uNumPARegs; i++) { UseoptSetBit(auKeepPAReg, i, IMG_TRUE); } sUseoptData.auKeepOutputReg = auKeepOutputReg; sUseoptData.psStart = psUSEASMInfo->psFirstUSEASMInstruction; sUseoptData.psProgram = psUSEASMInfo->psFirstUSEASMInstruction; sUseoptData.uNumOutRegs = 1; sUseoptData.asOutRegs = &sOutputRegister; #if 0 { IMG_UINT32 i, pi[50*8]; i = UseAssembler(UseAsmGetCoreDesc(&sTarget), psUSEASMInfo->psFirstUSEASMInstruction, pi, 0, &sUseasmContext); printf("Before:\n"); UseDisassembler(UseAsmGetCoreDesc(&sTarget), i, pi); } #endif /* Optimise program */ if((psUSEASMInfo->ui32NumMainUSEASMInstructions>1) && !gc->sAppHints.bDisableUSEASMOPT) { UseoptProgram(&sTarget, &sUseasmContext, &sUseoptData); if(sUseoptData.eStatus!=USEOPT_OK) { PVR_DPF((PVR_DBG_ERROR,"AssembleUSEASMInstructions(): UseoptProgram failed (%x)", sUseoptData.eStatus)); GLES1Free(gc, psUSEASMInfo->pui32HWInstructions); psUSEASMInfo->pui32HWInstructions = IMG_NULL; psUSEASMInfo->ui32NumHWInstructions = 0; return GLES1_GENERAL_MEM_ERROR; } } /* Reset the start pointer in case the first instruction was optimised out */ psUSEASMInfo->psFirstUSEASMInstruction = sUseoptData.psProgram; /* Assemble program */ psUSEASMInfo->ui32NumHWInstructions = UseAssembler(UseAsmGetCoreDesc(&sTarget), psUSEASMInfo->psFirstUSEASMInstruction, psUSEASMInfo->pui32HWInstructions, 0, &sUseasmContext); #if 0 { printf("After:\n"); UseDisassembler(UseAsmGetCoreDesc(&sTarget), psUSEASMInfo->ui32NumHWInstructions, psUSEASMInfo->pui32HWInstructions); } #endif return GLES1_NO_ERROR; }
/*! ****************************************************************************** @Function SysLocateDevices @Description Specifies devices in the systems memory map @Input psSysData - sys data @Return PVRSRV_ERROR ******************************************************************************/ static PVRSRV_ERROR SysLocateDevices(SYS_DATA *psSysData) { #if defined(NO_HARDWARE) PVRSRV_ERROR eError; IMG_CPU_PHYADDR sCpuPAddr; #else #if defined(PVR_LINUX_DYNAMIC_SGX_RESOURCE_INFO) struct resource *dev_res; int dev_irq; #endif #endif PVR_UNREFERENCED_PARAMETER(psSysData); /* SGX Device: */ gsSGXDeviceMap.ui32Flags = 0x0; #if defined(NO_HARDWARE) /* * For no hardware, allocate some contiguous memory for the * register block. */ /* Registers */ gsSGXDeviceMap.ui32RegsSize = SYS_OMAP3430_SGX_REGS_SIZE; eError = OSBaseAllocContigMemory(gsSGXDeviceMap.ui32RegsSize, &gsSGXRegsCPUVAddr, &sCpuPAddr); if(eError != PVRSRV_OK) { return eError; } gsSGXDeviceMap.sRegsCpuPBase = sCpuPAddr; gsSGXDeviceMap.sRegsSysPBase = SysCpuPAddrToSysPAddr(gsSGXDeviceMap.sRegsCpuPBase); #if defined(__linux__) /* Indicate the registers are already mapped */ gsSGXDeviceMap.pvRegsCpuVBase = gsSGXRegsCPUVAddr; #else /* * FIXME: Could we just use the virtual address returned by * OSBaseAllocContigMemory? */ gsSGXDeviceMap.pvRegsCpuVBase = IMG_NULL; #endif OSMemSet(gsSGXRegsCPUVAddr, 0, gsSGXDeviceMap.ui32RegsSize); /* device interrupt IRQ Note: no interrupts available on no hardware system */ gsSGXDeviceMap.ui32IRQ = 0; #else /* defined(NO_HARDWARE) */ #if defined(PVR_LINUX_DYNAMIC_SGX_RESOURCE_INFO) /* get the resource and IRQ through platform resource API */ dev_res = platform_get_resource(gpsPVRLDMDev, IORESOURCE_MEM, 0); if (dev_res == NULL) { PVR_DPF((PVR_DBG_ERROR, "%s: platform_get_resource failed", __FUNCTION__)); return PVRSRV_ERROR_INVALID_DEVICE; } dev_irq = platform_get_irq(gpsPVRLDMDev, 0); if (dev_irq < 0) { PVR_DPF((PVR_DBG_ERROR, "%s: platform_get_irq failed (%d)", __FUNCTION__, -dev_irq)); return PVRSRV_ERROR_INVALID_DEVICE; } gsSGXDeviceMap.sRegsSysPBase.uiAddr = dev_res->start; gsSGXDeviceMap.sRegsCpuPBase = SysSysPAddrToCpuPAddr(gsSGXDeviceMap.sRegsSysPBase); PVR_TRACE(("SGX register base: 0x%lx", (unsigned long)gsSGXDeviceMap.sRegsCpuPBase.uiAddr)); #if defined(SGX544) && defined(SGX_FEATURE_MP) /* FIXME: Workaround due to HWMOD change. Otherwise this region is too small. */ gsSGXDeviceMap.ui32RegsSize = SYS_OMAP3430_SGX_REGS_SIZE; #else gsSGXDeviceMap.ui32RegsSize = (unsigned int)(dev_res->end - dev_res->start); #endif PVR_TRACE(("SGX register size: %d",gsSGXDeviceMap.ui32RegsSize)); gsSGXDeviceMap.ui32IRQ = dev_irq; PVR_TRACE(("SGX IRQ: %d", gsSGXDeviceMap.ui32IRQ)); #else /* defined(PVR_LINUX_DYNAMIC_SGX_RESOURCE_INFO) */ gsSGXDeviceMap.sRegsSysPBase.uiAddr = SYS_OMAP3430_SGX_REGS_SYS_PHYS_BASE; gsSGXDeviceMap.sRegsCpuPBase = SysSysPAddrToCpuPAddr(gsSGXDeviceMap.sRegsSysPBase); gsSGXDeviceMap.ui32RegsSize = SYS_OMAP3430_SGX_REGS_SIZE; gsSGXDeviceMap.ui32IRQ = SYS_OMAP3430_SGX_IRQ; #endif /* defined(PVR_LINUX_DYNAMIC_SGX_RESOURCE_INFO) */ #if defined(SGX_OCP_REGS_ENABLED) gsSGXRegsCPUVAddr = OSMapPhysToLin(gsSGXDeviceMap.sRegsCpuPBase, gsSGXDeviceMap.ui32RegsSize, PVRSRV_HAP_UNCACHED|PVRSRV_HAP_KERNEL_ONLY, IMG_NULL); if (gsSGXRegsCPUVAddr == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR,"SysLocateDevices: Failed to map SGX registers")); return PVRSRV_ERROR_BAD_MAPPING; } /* Indicate the registers are already mapped */ gsSGXDeviceMap.pvRegsCpuVBase = gsSGXRegsCPUVAddr; gpvOCPRegsLinAddr = gsSGXRegsCPUVAddr; #endif #endif /* defined(NO_HARDWARE) */ #if defined(PDUMP) { /* initialise memory region name for pdumping */ static IMG_CHAR pszPDumpDevName[] = "SGXMEM"; gsSGXDeviceMap.pszPDumpDevName = pszPDumpDevName; } #endif /* add other devices here: */ return PVRSRV_OK; }
/* Reserve space in the CCB and fill in the command and client sync data */ PVRSRV_ERROR RGXCmdHelperAcquireCmdCCB(IMG_UINT32 ui32CmdCount, RGX_CCB_CMD_HELPER_DATA *asCmdHelperData, IMG_BOOL *pbKickRequired) { IMG_UINT32 ui32BeforeWOff = asCmdHelperData[0].psClientCCB->ui32HostWriteOffset; IMG_UINT32 ui32AllocSize = 0; IMG_UINT32 i; IMG_UINT8 *pui8StartPtr; PVRSRV_ERROR eError; *pbKickRequired = IMG_FALSE; /* Workout how much space we need for all the command(s) */ for (i=0;i<ui32CmdCount;i++) { if (asCmdHelperData[0].bPDumpContinuous != asCmdHelperData[i].bPDumpContinuous) { PVR_DPF((PVR_DBG_ERROR, "%s: PDump continuous is not consistent (%s != %s) for command %d", __FUNCTION__, asCmdHelperData[0].bPDumpContinuous?"IMG_TRUE":"IMG_FALSE", asCmdHelperData[i].bPDumpContinuous?"IMG_TRUE":"IMG_FALSE", ui32CmdCount)); return PVRSRV_ERROR_INVALID_PARAMS; } ui32AllocSize += asCmdHelperData[i].ui32FenceCmdSize + asCmdHelperData[i].ui32DMCmdSize + asCmdHelperData[i].ui32UpdateCmdSize; } /* Acquire space in the CCB for all the command(s). */ eError = RGXAcquireCCB(asCmdHelperData[0].psClientCCB, ui32AllocSize, (IMG_PVOID *)&pui8StartPtr, asCmdHelperData[0].bPDumpContinuous); if (eError != PVRSRV_OK) { /* Failed so bail out and allow the client side to retry */ if (asCmdHelperData[0].psClientCCB->ui32HostWriteOffset != ui32BeforeWOff) { *pbKickRequired = IMG_TRUE; } return eError; } /* For each command fill in the fence, DM, and update command Note: We only fill in the client fences here, the server fences (and updates) will be filled in together at the end. This is because we might fail the kernel CCB alloc and would then have to rollback the server syncs if we took the operation here */ for (i=0;i<ui32CmdCount;i++) { RGX_CCB_CMD_HELPER_DATA *psCmdHelperData = &asCmdHelperData[i]; IMG_UINT8 *pui8CmdPtr; IMG_UINT8 *pui8ServerFenceStart = 0; IMG_UINT8 *pui8ServerUpdateStart = 0; #if defined(PDUMP) IMG_UINT32 ui32CtxAddr = FWCommonContextGetFWAddress(asCmdHelperData->psClientCCB->psServerCommonContext).ui32Addr; IMG_UINT32 ui32CcbWoff = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(asCmdHelperData->psClientCCB->psServerCommonContext)); #endif if (psCmdHelperData->ui32ClientFenceCount+psCmdHelperData->ui32ClientUpdateCount != 0) { PDUMPCOMMENT("Start of %s client syncs for cmd[%d] on FWCtx %08x Woff 0x%x bytes", psCmdHelperData->psClientCCB->szName, i, ui32CtxAddr, ui32CcbWoff); } /* Create the fence command. */ if (psCmdHelperData->ui32FenceCmdSize) { RGXFWIF_CCB_CMD_HEADER *psHeader; IMG_UINT k; /* Fences are at the start of the command */ pui8CmdPtr = pui8StartPtr; psHeader = (RGXFWIF_CCB_CMD_HEADER *) pui8CmdPtr; psHeader->eCmdType = RGXFWIF_CCB_CMD_TYPE_FENCE; psHeader->ui32CmdSize = psCmdHelperData->ui32FenceCmdSize - sizeof(RGXFWIF_CCB_CMD_HEADER); pui8CmdPtr += sizeof(RGXFWIF_CCB_CMD_HEADER); /* Fill in the client fences */ for (k = 0; k < psCmdHelperData->ui32ClientFenceCount; k++) { RGXFWIF_UFO *psUFOPtr = (RGXFWIF_UFO *) pui8CmdPtr; psUFOPtr->puiAddrUFO = psCmdHelperData->pauiFenceUFOAddress[k]; psUFOPtr->ui32Value = psCmdHelperData->paui32FenceValue[k]; pui8CmdPtr += sizeof(RGXFWIF_UFO); #if defined SYNC_COMMAND_DEBUG PVR_DPF((PVR_DBG_ERROR, "%s client sync fence - 0x%x -> 0x%x", psCmdHelperData->psClientCCB->szName, psUFOPtr->puiAddrUFO.ui32Addr, psUFOPtr->ui32Value)); #endif PDUMPCOMMENT(".. %s client sync fence - 0x%x -> 0x%x", psCmdHelperData->psClientCCB->szName, psUFOPtr->puiAddrUFO.ui32Addr, psUFOPtr->ui32Value); } pui8ServerFenceStart = pui8CmdPtr; } /* Create the DM command */ if (psCmdHelperData->ui32DMCmdSize) { RGXFWIF_CCB_CMD_HEADER *psHeader; /* The command is after any fences */ pui8CmdPtr = pui8StartPtr + psCmdHelperData->ui32FenceCmdSize; psHeader = (RGXFWIF_CCB_CMD_HEADER *) pui8CmdPtr; psHeader->eCmdType = psCmdHelperData->eType; psHeader->ui32CmdSize = psCmdHelperData->ui32DMCmdSize - sizeof(RGXFWIF_CCB_CMD_HEADER); pui8CmdPtr += sizeof(RGXFWIF_CCB_CMD_HEADER); OSMemCopy(pui8CmdPtr, psCmdHelperData->pui8DMCmd, psCmdHelperData->ui32CmdSize); } /* Create the update command. Note: We only fill in the client updates here, the server updates (and fences) will be filled in together at the end */ if (psCmdHelperData->ui32UpdateCmdSize) { RGXFWIF_CCB_CMD_HEADER *psHeader; IMG_UINT k; /* And the update is after the DM command */ pui8CmdPtr = pui8StartPtr + psCmdHelperData->ui32FenceCmdSize + psCmdHelperData->ui32DMCmdSize; psHeader = (RGXFWIF_CCB_CMD_HEADER *) pui8CmdPtr; psHeader->eCmdType = RGXFWIF_CCB_CMD_TYPE_UPDATE; psHeader->ui32CmdSize = psCmdHelperData->ui32UpdateCmdSize - sizeof(RGXFWIF_CCB_CMD_HEADER); pui8CmdPtr += sizeof(RGXFWIF_CCB_CMD_HEADER); /* Fill in the client updates */ for (k = 0; k < psCmdHelperData->ui32ClientUpdateCount; k++) { RGXFWIF_UFO *psUFOPtr = (RGXFWIF_UFO *) pui8CmdPtr; psUFOPtr->puiAddrUFO = psCmdHelperData->pauiUpdateUFOAddress[k]; psUFOPtr->ui32Value = psCmdHelperData->paui32UpdateValue[k]; pui8CmdPtr += sizeof(RGXFWIF_UFO); #if defined SYNC_COMMAND_DEBUG PVR_DPF((PVR_DBG_ERROR, "%s client sync update - 0x%x -> 0x%x", psCmdHelperData->psClientCCB->szName, psUFOPtr->puiAddrUFO.ui32Addr, psUFOPtr->ui32Value)); #endif PDUMPCOMMENT(".. %s client sync update - 0x%x -> 0x%x", psCmdHelperData->psClientCCB->szName, psUFOPtr->puiAddrUFO.ui32Addr, psUFOPtr->ui32Value); } pui8ServerUpdateStart = pui8CmdPtr; } /* Save the server sync fence & update offsets for submit time */ psCmdHelperData->pui8ServerFenceStart = pui8ServerFenceStart; psCmdHelperData->pui8ServerUpdateStart = pui8ServerUpdateStart; /* Save start for sanity checking at submit time */ psCmdHelperData->pui8StartPtr = pui8StartPtr; /* Set the start pointer for the next iteration around the loop */ pui8StartPtr += psCmdHelperData->ui32FenceCmdSize + psCmdHelperData->ui32DMCmdSize + psCmdHelperData->ui32UpdateCmdSize; if (psCmdHelperData->ui32ClientFenceCount+psCmdHelperData->ui32ClientUpdateCount != 0) { PDUMPCOMMENT("End of %s client syncs for cmd[%d] on FWCtx %08x Woff 0x%x bytes", psCmdHelperData->psClientCCB->szName, i, ui32CtxAddr, ui32CcbWoff); } else { PDUMPCOMMENT("No %s client syncs for cmd[%d] on FWCtx %08x Woff 0x%x bytes", psCmdHelperData->psClientCCB->szName, i, ui32CtxAddr, ui32CcbWoff); } } *pbKickRequired = IMG_TRUE; return PVRSRV_OK; }
/*********************************************************************************** Function Name : DuplicateUSEASMInstructionList Inputs : Outputs : Returns : Description : ************************************************************************************/ IMG_INTERNAL IMG_VOID DuplicateUSEASMInstructionList(GLES1Context *gc, GLESUSEASMInfo *psSrcUSEASMInfo, GLESUSEASMInfo *psDstUSEASMInfo) { USE_INST *psInputInstruction, *psOutputInstruction, *psPrev; PVR_UNREFERENCED_PARAMETER(gc); psInputInstruction = psSrcUSEASMInfo->psFirstUSEASMInstruction; psDstUSEASMInfo->psFirstUSEASMInstruction = IMG_NULL; psPrev = IMG_NULL; /* Fix build warning */ psOutputInstruction = IMG_NULL; while(psInputInstruction) { psOutputInstruction = GLES1Malloc(gc, sizeof(USE_INST)); if(!psOutputInstruction) { USE_INST *psNext; PVR_DPF((PVR_DBG_ERROR,"DuplicateUSEASMInstrcutionList(): Failed to allocate memory for USEASM instructions")); psOutputInstruction = psDstUSEASMInfo->psFirstUSEASMInstruction; while(psOutputInstruction) { psNext = psOutputInstruction->psNext; GLES1Free(gc, psOutputInstruction); psOutputInstruction = psNext; } psDstUSEASMInfo->psFirstUSEASMInstruction = IMG_NULL; psDstUSEASMInfo->psLastUSEASMInstruction = IMG_NULL; psDstUSEASMInfo->ui32NumMainUSEASMInstructions = 0; return; } *psOutputInstruction = *psInputInstruction; if(!psDstUSEASMInfo->psFirstUSEASMInstruction) { psDstUSEASMInfo->psFirstUSEASMInstruction = psOutputInstruction; } psOutputInstruction->psNext = IMG_NULL; if(psPrev) { psPrev->psNext = psOutputInstruction; } psOutputInstruction->psPrev = psPrev; psPrev = psOutputInstruction; psInputInstruction = psInputInstruction->psNext; } psDstUSEASMInfo->psLastUSEASMInstruction = psOutputInstruction; psDstUSEASMInfo->ui32NumMainUSEASMInstructions = psSrcUSEASMInfo->ui32NumMainUSEASMInstructions; }
IMG_EXPORT PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK *psKick) #endif { PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psKick->hCCBMemInfo; SGXMKIF_COMMAND sCommand = {0}; SGXMKIF_2DCMD_SHARED *ps2DCmd; PVRSRV_KERNEL_SYNC_INFO *psSyncInfo; PVRSRV_ERROR eError; IMG_UINT32 i; IMG_HANDLE hDevMemContext = IMG_NULL; #if defined(PDUMP) IMG_BOOL bPersistentProcess = IMG_FALSE; { PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData(); if(psPerProc != IMG_NULL) { bPersistentProcess = psPerProc->bPDumpPersistent; } } #endif #if defined(FIX_HW_BRN_31620) hDevMemContext = psKick->hDevMemContext; #endif if (!CCB_OFFSET_IS_VALID(SGXMKIF_2DCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset)) { PVR_DPF((PVR_DBG_ERROR, "SGXSubmit2DKM: Invalid CCB offset")); return PVRSRV_ERROR_INVALID_PARAMS; } ps2DCmd = CCB_DATA_FROM_OFFSET(SGXMKIF_2DCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset); OSMemSet(ps2DCmd, 0, sizeof(*ps2DCmd)); if (psKick->hTASyncInfo != IMG_NULL) { psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo; ps2DCmd->sTASyncData.ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++; ps2DCmd->sTASyncData.ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending; ps2DCmd->sTASyncData.sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr; ps2DCmd->sTASyncData.sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr; } if (psKick->h3DSyncInfo != IMG_NULL) { psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo; ps2DCmd->s3DSyncData.ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++; ps2DCmd->s3DSyncData.ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending; ps2DCmd->s3DSyncData.sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr; ps2DCmd->s3DSyncData.sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr; } ps2DCmd->ui32NumSrcSync = psKick->ui32NumSrcSync; for (i = 0; i < psKick->ui32NumSrcSync; i++) { psSyncInfo = psKick->ahSrcSyncInfo[i]; ps2DCmd->sSrcSyncData[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending; ps2DCmd->sSrcSyncData[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending; ps2DCmd->sSrcSyncData[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr; ps2DCmd->sSrcSyncData[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr; } if (psKick->hDstSyncInfo != IMG_NULL) { psSyncInfo = psKick->hDstSyncInfo; ps2DCmd->sDstSyncData.ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending; ps2DCmd->sDstSyncData.ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending; ps2DCmd->sDstSyncData.ui32ReadOps2PendingVal = psSyncInfo->psSyncData->ui32ReadOps2Pending; ps2DCmd->sDstSyncData.sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr; ps2DCmd->sDstSyncData.sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr; ps2DCmd->sDstSyncData.sReadOps2CompleteDevVAddr = psSyncInfo->sReadOps2CompleteDevVAddr; } for (i = 0; i < psKick->ui32NumSrcSync; i++) { psSyncInfo = psKick->ahSrcSyncInfo[i]; psSyncInfo->psSyncData->ui32ReadOpsPending++; } if (psKick->hDstSyncInfo != IMG_NULL) { psSyncInfo = psKick->hDstSyncInfo; psSyncInfo->psSyncData->ui32WriteOpsPending++; } #if defined(PDUMP) if ((PDumpIsCaptureFrameKM() || ((psKick->ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0)) && (bPersistentProcess == IMG_FALSE) ) { PDUMPCOMMENT("Shared part of 2D command\r\n"); PDUMPMEM(ps2DCmd, psCCBMemInfo, psKick->ui32CCBDumpWOff, sizeof(SGXMKIF_2DCMD_SHARED), psKick->ui32PDumpFlags, MAKEUNIQUETAG(psCCBMemInfo)); for (i = 0; i < psKick->ui32NumSrcSync; i++) { psSyncInfo = psKick->ahSrcSyncInfo[i]; PDUMPCOMMENT("Hack src surface write op in 2D cmd\r\n"); PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal, psCCBMemInfo, psKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_2DCMD_SHARED, sSrcSyncData[i].ui32WriteOpsPendingVal), sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal), psKick->ui32PDumpFlags, MAKEUNIQUETAG(psCCBMemInfo)); PDUMPCOMMENT("Hack src surface read op in 2D cmd\r\n"); PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal, psCCBMemInfo, psKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_2DCMD_SHARED, sSrcSyncData[i].ui32ReadOpsPendingVal), sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal), psKick->ui32PDumpFlags, MAKEUNIQUETAG(psCCBMemInfo)); } if (psKick->hDstSyncInfo != IMG_NULL) { IMG_UINT32 ui32PDumpReadOp2 = 0; psSyncInfo = psKick->hDstSyncInfo; PDUMPCOMMENT("Hack dest surface write op in 2D cmd\r\n"); PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal, psCCBMemInfo, psKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_2DCMD_SHARED, sDstSyncData.ui32WriteOpsPendingVal), sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal), psKick->ui32PDumpFlags, MAKEUNIQUETAG(psCCBMemInfo)); PDUMPCOMMENT("Hack dest surface read op in 2D cmd\r\n"); PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal, psCCBMemInfo, psKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_2DCMD_SHARED, sDstSyncData.ui32ReadOpsPendingVal), sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal), psKick->ui32PDumpFlags, MAKEUNIQUETAG(psCCBMemInfo)); PDUMPCOMMENT("Hack dest surface read op2 in 2D cmd\r\n"); PDUMPMEM(&ui32PDumpReadOp2, psCCBMemInfo, psKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_2DCMD_SHARED, sDstSyncData.ui32ReadOps2PendingVal), sizeof(ui32PDumpReadOp2), psKick->ui32PDumpFlags, MAKEUNIQUETAG(psCCBMemInfo)); } for (i = 0; i < psKick->ui32NumSrcSync; i++) { psSyncInfo = psKick->ahSrcSyncInfo[i]; psSyncInfo->psSyncData->ui32LastReadOpDumpVal++; } if (psKick->hDstSyncInfo != IMG_NULL) { psSyncInfo = psKick->hDstSyncInfo; psSyncInfo->psSyncData->ui32LastOpDumpVal++; } } #endif sCommand.ui32Data[1] = psKick->sHW2DContextDevVAddr.uiAddr; eError = SGXScheduleCCBCommandKM(hDevHandle, SGXMKIF_CMD_2D, &sCommand, KERNEL_ID, psKick->ui32PDumpFlags, hDevMemContext, IMG_FALSE); if (eError == PVRSRV_ERROR_RETRY) { #if defined(PDUMP) if (PDumpIsCaptureFrameKM()) { for (i = 0; i < psKick->ui32NumSrcSync; i++) { psSyncInfo = psKick->ahSrcSyncInfo[i]; psSyncInfo->psSyncData->ui32LastReadOpDumpVal--; } if (psKick->hDstSyncInfo != IMG_NULL) { psSyncInfo = psKick->hDstSyncInfo; psSyncInfo->psSyncData->ui32LastOpDumpVal--; } } #endif for (i = 0; i < psKick->ui32NumSrcSync; i++) { psSyncInfo = psKick->ahSrcSyncInfo[i]; psSyncInfo->psSyncData->ui32ReadOpsPending--; } if (psKick->hDstSyncInfo != IMG_NULL) { psSyncInfo = psKick->hDstSyncInfo; psSyncInfo->psSyncData->ui32WriteOpsPending--; } if (psKick->hTASyncInfo != IMG_NULL) { psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo; psSyncInfo->psSyncData->ui32WriteOpsPending--; } if (psKick->h3DSyncInfo != IMG_NULL) { psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo; psSyncInfo->psSyncData->ui32WriteOpsPending--; } } #if defined(NO_HARDWARE) for(i = 0; i < psKick->ui32NumSrcSync; i++) { psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[i]; psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending; } if (psKick->hDstSyncInfo != IMG_NULL) { psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hDstSyncInfo; psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending; } if (psKick->hTASyncInfo != IMG_NULL) { psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo; psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending; } if (psKick->h3DSyncInfo != IMG_NULL) { psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo; psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending; } #endif return eError; }
/****************************************************************************** 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); }
IMG_EXPORT PVRSRV_ERROR SGXAddSharedPBDescKM(PVRSRV_PER_PROCESS_DATA *psPerProc, IMG_HANDLE hDevCookie, PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo, PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo, PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo, PVRSRV_KERNEL_MEM_INFO *psHWBlockKernelMemInfo, IMG_UINT32 ui32TotalPBSize, IMG_HANDLE *phSharedPBDesc, PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescSubKernelMemInfos, IMG_UINT32 ui32SharedPBDescSubKernelMemInfosCount) { PVRSRV_STUB_PBDESC *psStubPBDesc=IMG_NULL; PVRSRV_ERROR eRet = PVRSRV_ERROR_GENERIC; IMG_UINT32 i; PVRSRV_SGXDEV_INFO *psSGXDevInfo; PRESMAN_ITEM psResItem; if (psPerProcCreateSharedPB != psPerProc) { goto NoAdd; } else { PVR_ASSERT(psResItemCreateSharedPB != IMG_NULL); ResManFreeResByPtr(psResItemCreateSharedPB); PVR_ASSERT(psResItemCreateSharedPB == IMG_NULL); PVR_ASSERT(psPerProcCreateSharedPB == IMG_NULL); } psSGXDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice; psStubPBDesc = psSGXDevInfo->psStubPBDescListKM; if (psStubPBDesc != IMG_NULL) { if(psStubPBDesc->ui32TotalPBSize != ui32TotalPBSize) { PVR_DPF((PVR_DBG_WARNING, "SGXAddSharedPBDescKM: Shared PB requested with different size (0x%x) from existing shared PB (0x%x) - requested size ignored", ui32TotalPBSize, psStubPBDesc->ui32TotalPBSize)); } psResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_SHARED_PB_DESC, psStubPBDesc, 0, &SGXCleanupSharedPBDescCallback); if (psResItem == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: " "Failed to register existing shared " "PBDesc with the resource manager")); goto NoAddKeepPB; } psStubPBDesc->ui32RefCount++; *phSharedPBDesc = (IMG_HANDLE)psResItem; eRet = PVRSRV_OK; goto NoAddKeepPB; } if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_STUB_PBDESC), (IMG_VOID **)&psStubPBDesc, 0, "Stub Parameter Buffer Description") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: Failed to alloc " "StubPBDesc")); eRet = PVRSRV_ERROR_OUT_OF_MEMORY; goto NoAdd; } psStubPBDesc->ppsSubKernelMemInfos = IMG_NULL; if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_MEM_INFO *) * ui32SharedPBDescSubKernelMemInfosCount, (IMG_VOID **)&psStubPBDesc->ppsSubKernelMemInfos, 0, "Array of Kernel Memory Info") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: " "Failed to alloc " "StubPBDesc->ppsSubKernelMemInfos")); eRet = PVRSRV_ERROR_OUT_OF_MEMORY; goto NoAdd; } if(PVRSRVDissociateMemFromResmanKM(psSharedPBDescKernelMemInfo) != PVRSRV_OK) { goto NoAdd; } if(PVRSRVDissociateMemFromResmanKM(psHWPBDescKernelMemInfo) != PVRSRV_OK) { goto NoAdd; } if(PVRSRVDissociateMemFromResmanKM(psBlockKernelMemInfo) != PVRSRV_OK) { goto NoAdd; } if(PVRSRVDissociateMemFromResmanKM(psHWBlockKernelMemInfo) != PVRSRV_OK) { goto NoAdd; } psStubPBDesc->ui32RefCount = 1; psStubPBDesc->ui32TotalPBSize = ui32TotalPBSize; psStubPBDesc->psSharedPBDescKernelMemInfo = psSharedPBDescKernelMemInfo; psStubPBDesc->psHWPBDescKernelMemInfo = psHWPBDescKernelMemInfo; psStubPBDesc->psBlockKernelMemInfo = psBlockKernelMemInfo; psStubPBDesc->psHWBlockKernelMemInfo = psHWBlockKernelMemInfo; psStubPBDesc->ui32SubKernelMemInfosCount = ui32SharedPBDescSubKernelMemInfosCount; for(i=0; i<ui32SharedPBDescSubKernelMemInfosCount; i++) { psStubPBDesc->ppsSubKernelMemInfos[i] = ppsSharedPBDescSubKernelMemInfos[i]; if(PVRSRVDissociateMemFromResmanKM(ppsSharedPBDescSubKernelMemInfos[i]) != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: " "Failed to dissociate shared PBDesc " "from process")); goto NoAdd; } } psResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_SHARED_PB_DESC, psStubPBDesc, 0, &SGXCleanupSharedPBDescCallback); if (psResItem == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: " "Failed to register shared PBDesc " " with the resource manager")); goto NoAdd; } psStubPBDesc->hDevCookie = hDevCookie; List_PVRSRV_STUB_PBDESC_Insert(&(psSGXDevInfo->psStubPBDescListKM), psStubPBDesc); *phSharedPBDesc = (IMG_HANDLE)psResItem; return PVRSRV_OK; NoAdd: if(psStubPBDesc) { if(psStubPBDesc->ppsSubKernelMemInfos) { OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_MEM_INFO *) * ui32SharedPBDescSubKernelMemInfosCount, psStubPBDesc->ppsSubKernelMemInfos, 0); psStubPBDesc->ppsSubKernelMemInfos = IMG_NULL; } OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_STUB_PBDESC), psStubPBDesc, 0); } NoAddKeepPB: for (i = 0; i < ui32SharedPBDescSubKernelMemInfosCount; i++) { PVRSRVFreeDeviceMemKM(hDevCookie, ppsSharedPBDescSubKernelMemInfos[i]); } PVRSRVFreeSharedSysMemoryKM(psSharedPBDescKernelMemInfo); PVRSRVFreeDeviceMemKM(hDevCookie, psHWPBDescKernelMemInfo); PVRSRVFreeSharedSysMemoryKM(psBlockKernelMemInfo); PVRSRVFreeDeviceMemKM(hDevCookie, psHWBlockKernelMemInfo); return eRet; }
IMG_EXPORT PVRSRV_ERROR SGXFindSharedPBDescKM(PVRSRV_PER_PROCESS_DATA *psPerProc, IMG_HANDLE hDevCookie, IMG_BOOL bLockOnFailure, IMG_UINT32 ui32TotalPBSize, IMG_HANDLE *phSharedPBDesc, PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescKernelMemInfo, PVRSRV_KERNEL_MEM_INFO **ppsHWPBDescKernelMemInfo, PVRSRV_KERNEL_MEM_INFO **ppsBlockKernelMemInfo, PVRSRV_KERNEL_MEM_INFO **ppsHWBlockKernelMemInfo, PVRSRV_KERNEL_MEM_INFO ***pppsSharedPBDescSubKernelMemInfos, IMG_UINT32 *ui32SharedPBDescSubKernelMemInfosCount) { PVRSRV_STUB_PBDESC *psStubPBDesc; PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescSubKernelMemInfos=IMG_NULL; PVRSRV_SGXDEV_INFO *psSGXDevInfo; PVRSRV_ERROR eError; psSGXDevInfo = ((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice; psStubPBDesc = psSGXDevInfo->psStubPBDescListKM; if (psStubPBDesc != IMG_NULL) { IMG_UINT32 i; PRESMAN_ITEM psResItem; if(psStubPBDesc->ui32TotalPBSize != ui32TotalPBSize) { PVR_DPF((PVR_DBG_WARNING, "SGXFindSharedPBDescKM: Shared PB requested with different size (0x%x) from existing shared PB (0x%x) - requested size ignored", ui32TotalPBSize, psStubPBDesc->ui32TotalPBSize)); } if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_MEM_INFO *) * psStubPBDesc->ui32SubKernelMemInfosCount, (IMG_VOID **)&ppsSharedPBDescSubKernelMemInfos, IMG_NULL, "Array of Kernel Memory Info") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "SGXFindSharedPBDescKM: OSAllocMem failed")); eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto ExitNotFound; } psResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_SHARED_PB_DESC, psStubPBDesc, 0, &SGXCleanupSharedPBDescCallback); if (psResItem == IMG_NULL) { OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_MEM_INFO *) * psStubPBDesc->ui32SubKernelMemInfosCount, ppsSharedPBDescSubKernelMemInfos, 0); PVR_DPF((PVR_DBG_ERROR, "SGXFindSharedPBDescKM: ResManRegisterRes failed")); eError = PVRSRV_ERROR_GENERIC; goto ExitNotFound; } *ppsSharedPBDescKernelMemInfo = psStubPBDesc->psSharedPBDescKernelMemInfo; *ppsHWPBDescKernelMemInfo = psStubPBDesc->psHWPBDescKernelMemInfo; *ppsBlockKernelMemInfo = psStubPBDesc->psBlockKernelMemInfo; *ppsHWBlockKernelMemInfo = psStubPBDesc->psHWBlockKernelMemInfo; *ui32SharedPBDescSubKernelMemInfosCount = psStubPBDesc->ui32SubKernelMemInfosCount; *pppsSharedPBDescSubKernelMemInfos = ppsSharedPBDescSubKernelMemInfos; for(i=0; i<psStubPBDesc->ui32SubKernelMemInfosCount; i++) { ppsSharedPBDescSubKernelMemInfos[i] = psStubPBDesc->ppsSubKernelMemInfos[i]; } psStubPBDesc->ui32RefCount++; *phSharedPBDesc = (IMG_HANDLE)psResItem; return PVRSRV_OK; } eError = PVRSRV_OK; if (bLockOnFailure) { if (psResItemCreateSharedPB == IMG_NULL) { psResItemCreateSharedPB = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK, psPerProc, 0, &SGXCleanupSharedPBDescCreateLockCallback); if (psResItemCreateSharedPB == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "SGXFindSharedPBDescKM: ResManRegisterRes failed")); eError = PVRSRV_ERROR_GENERIC; goto ExitNotFound; } PVR_ASSERT(psPerProcCreateSharedPB == IMG_NULL); psPerProcCreateSharedPB = psPerProc; } else { eError = PVRSRV_ERROR_PROCESSING_BLOCKED; } } ExitNotFound: *phSharedPBDesc = IMG_NULL; return eError; }
/* * PVRSRVCreateTransferContextKM */ IMG_EXPORT PVRSRV_ERROR PVRSRVRGXCreateTransferContextKM(CONNECTION_DATA *psConnection, PVRSRV_DEVICE_NODE *psDeviceNode, IMG_UINT32 ui32Priority, IMG_DEV_VIRTADDR sMCUFenceAddr, IMG_UINT32 ui32FrameworkCommandSize, IMG_PBYTE pabyFrameworkCommand, IMG_HANDLE hMemCtxPrivData, RGX_SERVER_TQ_CONTEXT **ppsTransferContext) { RGX_SERVER_TQ_CONTEXT *psTransferContext; DEVMEM_MEMDESC *psFWMemContextMemDesc = RGXGetFWMemDescFromMemoryContextHandle(hMemCtxPrivData); RGX_COMMON_CONTEXT_INFO sInfo; PVRSRV_ERROR eError = PVRSRV_OK; /* Allocate the server side structure */ psTransferContext = OSAllocMem(sizeof(*psTransferContext)); if (psTransferContext == IMG_NULL) { return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet(psTransferContext, 0, sizeof(*psTransferContext)); psTransferContext->psDeviceNode = psDeviceNode; /* Allocate cleanup sync */ eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext, &psTransferContext->psCleanupSync); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateTransferContextKM: Failed to allocate cleanup sync (0x%x)", eError)); goto fail_syncalloc; } /* * Create the FW framework buffer */ eError = PVRSRVRGXFrameworkCreateKM(psDeviceNode, &psTransferContext->psFWFrameworkMemDesc, ui32FrameworkCommandSize); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateTransferContextKM: Failed to allocate firmware GPU framework state (%u)", eError)); goto fail_frameworkcreate; } /* Copy the Framework client data into the framework buffer */ eError = PVRSRVRGXFrameworkCopyCommand(psTransferContext->psFWFrameworkMemDesc, pabyFrameworkCommand, ui32FrameworkCommandSize); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateTransferContextKM: Failed to populate the framework buffer (%u)", eError)); goto fail_frameworkcopy; } sInfo.psFWFrameworkMemDesc = psTransferContext->psFWFrameworkMemDesc; sInfo.psMCUFenceAddr = &sMCUFenceAddr; eError = _Create3DTransferContext(psConnection, psDeviceNode, psFWMemContextMemDesc, ui32Priority, &sInfo, &psTransferContext->s3DData); if (eError != PVRSRV_OK) { goto fail_3dtransfercontext; } psTransferContext->ui32Flags |= RGX_SERVER_TQ_CONTEXT_FLAGS_3D; eError = _Create2DTransferContext(psConnection, psDeviceNode, psFWMemContextMemDesc, ui32Priority, &sInfo, &psTransferContext->s2DData); if (eError != PVRSRV_OK) { goto fail_2dtransfercontext; } psTransferContext->ui32Flags |= RGX_SERVER_TQ_CONTEXT_FLAGS_2D; { PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; dllist_add_to_tail(&(psDevInfo->sTransferCtxtListHead), &(psTransferContext->sListNode)); *ppsTransferContext = psTransferContext; } return PVRSRV_OK; fail_2dtransfercontext: _Destroy3DTransferContext(&psTransferContext->s3DData, psTransferContext->psDeviceNode, psTransferContext->psCleanupSync); fail_3dtransfercontext: fail_frameworkcopy: DevmemFwFree(psTransferContext->psFWFrameworkMemDesc); fail_frameworkcreate: SyncPrimFree(psTransferContext->psCleanupSync); fail_syncalloc: OSFreeMem(psTransferContext); PVR_ASSERT(eError != PVRSRV_OK); psTransferContext = IMG_NULL; 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; }
IMG_EXPORT PVRSRV_ERROR PVRSRVRGXCreateComputeContextKM(CONNECTION_DATA *psConnection, PVRSRV_DEVICE_NODE *psDeviceNode, IMG_UINT32 ui32Priority, IMG_DEV_VIRTADDR sMCUFenceAddr, IMG_UINT32 ui32FrameworkCommandSize, IMG_PBYTE pbyFrameworkCommand, IMG_HANDLE hMemCtxPrivData, RGX_SERVER_COMPUTE_CONTEXT **ppsComputeContext) { PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; DEVMEM_MEMDESC *psFWMemContextMemDesc = RGXGetFWMemDescFromMemoryContextHandle(hMemCtxPrivData); RGX_SERVER_COMPUTE_CONTEXT *psComputeContext; RGX_COMMON_CONTEXT_INFO sInfo; PVRSRV_ERROR eError = PVRSRV_OK; /* Prepare cleanup struct */ psComputeContext = OSAllocMem(sizeof(*psComputeContext)); if (psComputeContext == IMG_NULL) { return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet(psComputeContext, 0, sizeof(*psComputeContext)); *ppsComputeContext = psComputeContext; psComputeContext->psDeviceNode = psDeviceNode; /* Allocate cleanup sync */ eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext, &psComputeContext->psSync); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateComputeContextKM: Failed to allocate cleanup sync (0x%x)", eError)); goto fail_syncalloc; } /* Allocate device memory for the firmware GPU context suspend state. Note: the FW reads/writes the state to memory by accessing the GPU register interface. */ PDUMPCOMMENT("Allocate RGX firmware compute context suspend state"); eError = DevmemFwAllocate(psDevInfo, sizeof(RGXFWIF_COMPUTECTX_STATE), RGX_FWCOMCTX_ALLOCFLAGS, "ComputeContextState", &psComputeContext->psFWComputeContextStateMemDesc); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateComputeContextKM: Failed to allocate firmware GPU context suspend state (%u)", eError)); goto fail_contextsuspendalloc; } /* * Create the FW framework buffer */ eError = PVRSRVRGXFrameworkCreateKM(psDeviceNode, &psComputeContext->psFWFrameworkMemDesc, ui32FrameworkCommandSize); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateComputeContextKM: Failed to allocate firmware GPU framework state (%u)", eError)); goto fail_frameworkcreate; } /* Copy the Framework client data into the framework buffer */ eError = PVRSRVRGXFrameworkCopyCommand(psComputeContext->psFWFrameworkMemDesc, pbyFrameworkCommand, ui32FrameworkCommandSize); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateComputeContextKM: Failed to populate the framework buffer (%u)", eError)); goto fail_frameworkcopy; } sInfo.psFWFrameworkMemDesc = psComputeContext->psFWFrameworkMemDesc; sInfo.psMCUFenceAddr = &sMCUFenceAddr; eError = FWCommonContextAllocate(psConnection, psDeviceNode, "CDM", IMG_NULL, 0, psFWMemContextMemDesc, psComputeContext->psFWComputeContextStateMemDesc, RGX_CCB_SIZE_LOG2, ui32Priority, &sInfo, &psComputeContext->psServerCommonContext); if (eError != PVRSRV_OK) { goto fail_contextalloc; } { PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; OSWRLockAcquireWrite(psDevInfo->hComputeCtxListLock, DEVINFO_COMPUTELIST); dllist_add_to_tail(&(psDevInfo->sComputeCtxtListHead), &(psComputeContext->sListNode)); OSWRLockReleaseWrite(psDevInfo->hComputeCtxListLock); } return PVRSRV_OK; fail_contextalloc: fail_frameworkcopy: DevmemFwFree(psComputeContext->psFWFrameworkMemDesc); fail_frameworkcreate: DevmemFwFree(psComputeContext->psFWComputeContextStateMemDesc); fail_contextsuspendalloc: SyncPrimFree(psComputeContext->psSync); fail_syncalloc: OSFreeMem(psComputeContext); return eError; }
IMG_EXPORT PVRSRV_ERROR PVRSRVRGXKickCDMKM(RGX_SERVER_COMPUTE_CONTEXT *psComputeContext, 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_UINT32 ui32CmdSize, IMG_PBYTE pui8DMCmd, IMG_BOOL bPDumpContinuous, IMG_UINT32 ui32ExtJobRef, IMG_UINT32 ui32IntJobRef) { RGXFWIF_KCCB_CMD sCmpKCCBCmd; RGX_CCB_CMD_HELPER_DATA sCmdHelperData; IMG_BOOL bKickRequired; PVRSRV_ERROR eError; PVRSRV_ERROR eError2; IMG_UINT32 i; PRGXFWIF_TIMESTAMP_ADDR pPreAddr; PRGXFWIF_TIMESTAMP_ADDR pPostAddr; PRGXFWIF_UFO_ADDR pRMWUFOAddr; /* 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, & pPreAddr, & pPostAddr, & pRMWUFOAddr); eError = RGXCmdHelperInitCmdCCB(FWCommonContextGetClientCCB(psComputeContext->psServerCommonContext), ui32ClientFenceCount, pauiClientFenceUFOAddress, paui32ClientFenceValue, ui32ClientUpdateCount, pauiClientUpdateUFOAddress, paui32ClientUpdateValue, ui32ServerSyncPrims, paui32ServerSyncFlags, pasServerSyncs, ui32CmdSize, pui8DMCmd, & pPreAddr, & pPostAddr, & pRMWUFOAddr, RGXFWIF_CCB_CMD_TYPE_CDM, bPDumpContinuous, "Compute", &sCmdHelperData); if (eError != PVRSRV_OK) { goto fail_cmdinit; } eError = RGXCmdHelperAcquireCmdCCB(1, &sCmdHelperData, &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, &sCmdHelperData, "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: return eError; }
void LinuxMMCleanup(void) { #if defined(DEBUG_LINUX_MEM_AREAS) { struct DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord = g_LinuxMemAreaRecords, *psNextRecord; if (g_LinuxMemAreaCount) PVR_DPF(PVR_DBG_ERROR, "%s: BUG!: " "There are %d Linux memory area allocation " "unfreed (%ld bytes)", __func__, g_LinuxMemAreaCount, g_LinuxMemAreaWaterMark); while (psCurrentRecord) { struct LinuxMemArea *psLinuxMemArea; psNextRecord = psCurrentRecord->psNext; psLinuxMemArea = psCurrentRecord->psLinuxMemArea; PVR_DPF(PVR_DBG_ERROR, "%s: BUG!: " "Cleaning up Linux memory area (%p), " "type=%s, size=%ld bytes", __func__, psCurrentRecord->psLinuxMemArea, LinuxMemAreaTypeToString(psCurrentRecord-> psLinuxMemArea-> eAreaType), psCurrentRecord->psLinuxMemArea-> ui32ByteSize); LinuxMemAreaDeepFree(psLinuxMemArea); psCurrentRecord = psNextRecord; } RemoveProcEntry("mem_areas"); } #endif #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) { struct DEBUG_MEM_ALLOC_REC *psCurrentRecord = g_MemoryRecords, *psNextRecord; while (psCurrentRecord) { psNextRecord = psCurrentRecord->psNext; PVR_DPF(PVR_DBG_ERROR, "%s: BUG!: Cleaning up memory: " "type=%s " "CpuVAddr=%p " "CpuPAddr=0x%08lx, " "allocated @ file=%s,line=%d", __func__, DebugMemAllocRecordTypeToString (psCurrentRecord->eAllocType), psCurrentRecord->pvCpuVAddr, psCurrentRecord->ulCpuPAddr, psCurrentRecord->pszFileName, psCurrentRecord->ui32Line); switch (psCurrentRecord->eAllocType) { case DEBUG_MEM_ALLOC_TYPE_KMALLOC: KFreeWrapper(psCurrentRecord->pvCpuVAddr); break; case DEBUG_MEM_ALLOC_TYPE_IOREMAP: IOUnmapWrapper((void __iomem __force *) psCurrentRecord->pvCpuVAddr); break; case DEBUG_MEM_ALLOC_TYPE_IO: DebugMemAllocRecordRemove (DEBUG_MEM_ALLOC_TYPE_IO, psCurrentRecord->pvKey, __FILE__, __LINE__); break; case DEBUG_MEM_ALLOC_TYPE_VMALLOC: VFreeWrapper(psCurrentRecord->pvCpuVAddr); break; case DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES: DebugMemAllocRecordRemove (DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, psCurrentRecord->pvKey, __FILE__, __LINE__); break; case DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE: KMemCacheFreeWrapper(psCurrentRecord-> pvPrivateData, psCurrentRecord-> pvCpuVAddr); break; case DEBUG_MEM_ALLOC_TYPE_KMAP: KUnMapWrapper(psCurrentRecord->pvKey); break; default: PVR_ASSERT(0); } psCurrentRecord = psNextRecord; } RemoveProcEntry("meminfo"); } #endif if (psLinuxMemAreaCache) { KMemCacheDestroyWrapper(psLinuxMemAreaCache); psLinuxMemAreaCache = NULL; } }
IMG_EXPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo) { SYS_DATA *psSysData; if(!psMiscInfo) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid parameters")); return PVRSRV_ERROR_INVALID_PARAMS; } psMiscInfo->ui32StatePresent = 0; if(psMiscInfo->ui32StateRequest & ~(PVRSRV_MISC_INFO_TIMER_PRESENT |PVRSRV_MISC_INFO_CLOCKGATE_PRESENT |PVRSRV_MISC_INFO_MEMSTATS_PRESENT |PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT |PVRSRV_MISC_INFO_DDKVERSION_PRESENT |PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT |PVRSRV_MISC_INFO_RESET_PRESENT |PVRSRV_MISC_INFO_FREEMEM_PRESENT)) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid state request flags")); return PVRSRV_ERROR_INVALID_PARAMS; } SysAcquireData(&psSysData); if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_TIMER_PRESENT) != 0UL) && (psSysData->pvSOCTimerRegisterKM != IMG_NULL)) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_TIMER_PRESENT; psMiscInfo->pvSOCTimerRegisterKM = psSysData->pvSOCTimerRegisterKM; psMiscInfo->hSOCTimerRegisterOSMemHandle = psSysData->hSOCTimerRegisterOSMemHandle; } else { psMiscInfo->pvSOCTimerRegisterKM = IMG_NULL; psMiscInfo->hSOCTimerRegisterOSMemHandle = IMG_NULL; } if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CLOCKGATE_PRESENT) != 0UL) && (psSysData->pvSOCClockGateRegsBase != IMG_NULL)) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_CLOCKGATE_PRESENT; psMiscInfo->pvSOCClockGateRegs = psSysData->pvSOCClockGateRegsBase; psMiscInfo->ui32SOCClockGateRegsSize = psSysData->ui32SOCClockGateRegsSize; } if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0UL) && (psMiscInfo->pszMemoryStr != IMG_NULL)) { RA_ARENA **ppArena; IMG_CHAR *pszStr; IMG_UINT32 ui32StrLen; IMG_INT32 i32Count; pszStr = psMiscInfo->pszMemoryStr; ui32StrLen = psMiscInfo->ui32MemoryStrLen; psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_MEMSTATS_PRESENT; ppArena = &psSysData->apsLocalDevMemArena[0]; while(*ppArena) { CHECK_SPACE(ui32StrLen); i32Count = OSSNPrintf(pszStr, 100, "\nLocal Backing Store:\n"); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); RA_GetStats(*ppArena, &pszStr, &ui32StrLen); ppArena++; } List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList, &PVRSRVGetMiscInfoKM_Device_AnyVaCb, &ui32StrLen, &i32Count, &pszStr, PVRSRV_MISC_INFO_MEMSTATS_PRESENT); i32Count = OSSNPrintf(pszStr, 100, "\n"); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); } if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_FREEMEM_PRESENT) && psMiscInfo->pszMemoryStr) { IMG_CHAR *pszStr; IMG_UINT32 ui32StrLen; IMG_INT32 i32Count; pszStr = psMiscInfo->pszMemoryStr; ui32StrLen = psMiscInfo->ui32MemoryStrLen; psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_FREEMEM_PRESENT; List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList, &PVRSRVGetMiscInfoKM_Device_AnyVaCb, &ui32StrLen, &i32Count, &pszStr, PVRSRV_MISC_INFO_FREEMEM_PRESENT); i32Count = OSSNPrintf(pszStr, 100, "\n"); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); } if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT) != 0UL) && (psSysData->psGlobalEventObject != IMG_NULL)) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT; psMiscInfo->sGlobalEventObject = *psSysData->psGlobalEventObject; } if (((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0UL) && ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) == 0UL) && (psMiscInfo->pszMemoryStr != IMG_NULL)) { IMG_CHAR *pszStr; IMG_UINT32 ui32StrLen; IMG_UINT32 ui32LenStrPerNum = 12; IMG_INT32 i32Count; PVRSRV_SGXDEV_INFO *sgx_dev_info; PVRSRV_SGX_MISCINFO_INFO *sgx_misc_info; PVRSRV_SGX_MISCINFO_FEATURES *sgx_features; unsigned long fw_ver; IMG_INT i; psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_DDKVERSION_PRESENT; /* * Since the kernel driver has already made sure that the * firmware version is supported by the kernel driver in * SGXDevInitCompatCheck, it's redundant for the user space * part to perform the same check. In order to support older * user space libraries where this check hasn't yet been removed, * simply report the version of the downloaded firmware which * will result in an exact match in user space. */ sgx_dev_info = pvr_get_sgx_dev_info(); if (!sgx_dev_info || !sgx_dev_info->psKernelSGXMiscMemInfo || !sgx_dev_info->psKernelSGXMiscMemInfo->pvLinAddrKM) return PVRSRV_ERROR_INVALID_DEVICE; sgx_misc_info = sgx_dev_info->psKernelSGXMiscMemInfo->pvLinAddrKM; sgx_features = &sgx_misc_info->sSGXFeatures; fw_ver = sgx_features->ui32DDKVersion; psMiscInfo->aui32DDKVersion[0] = PVR_FW_VER_MAJOR(fw_ver); psMiscInfo->aui32DDKVersion[1] = PVR_FW_VER_MINOR(fw_ver); psMiscInfo->aui32DDKVersion[2] = PVR_FW_VER_BRANCH(fw_ver); psMiscInfo->aui32DDKVersion[3] = sgx_features->ui32DDKBuild; pszStr = psMiscInfo->pszMemoryStr; ui32StrLen = psMiscInfo->ui32MemoryStrLen; for (i=0; i<4; i++) { if (ui32StrLen < ui32LenStrPerNum) { return PVRSRV_ERROR_INVALID_PARAMS; } i32Count = OSSNPrintf(pszStr, ui32LenStrPerNum, "%u", psMiscInfo->aui32DDKVersion[i]); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); if (i != 3) { i32Count = OSSNPrintf(pszStr, 2, "."); UPDATE_SPACE(pszStr, i32Count, ui32StrLen); } } } if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT) != 0UL) { psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT; if(psMiscInfo->sCacheOpCtl.bDeferOp) { psSysData->ePendingCacheOpType = psMiscInfo->sCacheOpCtl.eCacheOpType; } else { PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo; PVRSRV_PER_PROCESS_DATA *psPerProc; if(!psMiscInfo->sCacheOpCtl.u.psKernelMemInfo) { PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetMiscInfoKM: " "Ignoring non-deferred cache op with no meminfo")); return PVRSRV_ERROR_INVALID_PARAMS; } if(psSysData->ePendingCacheOpType != PVRSRV_MISC_INFO_CPUCACHEOP_NONE) { PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetMiscInfoKM: " "Deferred cache op is pending. It is unlikely you want " "to combine deferred cache ops with immediate ones")); } psPerProc = PVRSRVFindPerProcessData(); if(PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_PVOID *)&psKernelMemInfo, psMiscInfo->sCacheOpCtl.u.psKernelMemInfo, PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetMiscInfoKM: " "Can't find kernel meminfo")); return PVRSRV_ERROR_INVALID_PARAMS; } if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH) { if(!OSFlushCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle, psMiscInfo->sCacheOpCtl.pvBaseVAddr, psMiscInfo->sCacheOpCtl.ui32Length)) { return PVRSRV_ERROR_CACHEOP_FAILED; } } else if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN) { if(!OSCleanCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle, psMiscInfo->sCacheOpCtl.pvBaseVAddr, psMiscInfo->sCacheOpCtl.ui32Length)) { return PVRSRV_ERROR_CACHEOP_FAILED; } } } } #if defined(PVRSRV_RESET_ON_HWTIMEOUT) if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_RESET_PRESENT) != 0UL) { PVR_LOG(("User requested OS reset")); OSPanic(); } #endif return PVRSRV_OK; }
IMG_INTERNAL IMG_VOID StartUpMemSpeedTest(GLES1Context *gc) { IMG_UINT32 ui32BlockSize, ui32MaxSize, ui32BlockNumber; IMG_UINT32 *pui32VBuffer, *pui32HostBuffer1, *pui32HostBuffer2; IMG_UINT32 *pui32RealHostBuffer1, *pui32RealHostBuffer2; IMG_CHAR szTempBuffer[1024]; IMG_UINT32 ui32BufLen; PVR_DPF((PVR_DBG_WARNING, "Running StartUpMemSpeedTest. High memory watermark will be ruined. Disable using apphint EnableMemorySpeedTest")); ui32MaxSize = 128*1024; if(ui32MaxSize > (gc->apsBuffers[CBUF_TYPE_VERTEX_DATA_BUFFER]->ui32BufferLimitInBytes << 2)) { PVR_DPF((PVR_DBG_ERROR,"StartUpMemSpeedTest: VB is too small - aborting test")); return; } pui32VBuffer = gc->apsBuffers[CBUF_TYPE_VERTEX_DATA_BUFFER]->pui32BufferBase; pui32RealHostBuffer1 = (IMG_UINT32 *)GLES1Malloc(gc, 1024*1024+32); if (!pui32RealHostBuffer1) { PVR_DPF((PVR_DBG_ERROR,"StartUpMemSpeedTest: Failed host alloc 1 - aborting test")); return; } pui32RealHostBuffer2 = (IMG_UINT32 *)GLES1Malloc(gc, 1024*1024+32); if (!pui32RealHostBuffer2) { GLES1Free(gc, pui32RealHostBuffer1); PVR_DPF((PVR_DBG_ERROR,"StartUpMemSpeedTest: Failed host alloc 2 - aborting test")); return; } /* Align the addresses */ pui32HostBuffer1 = (IMG_UINT32 *)(((unsigned int)pui32RealHostBuffer1 & 0xFFFFFFE0UL) + 32); pui32HostBuffer2 = (IMG_UINT32 *)(((unsigned int)pui32RealHostBuffer2 & 0xFFFFFFE0UL) + 32); /* Spacer */ ui32BufLen = sprintf(szTempBuffer, "Bytes :"); /* Draw column headers */ for (ui32BlockSize=512; ui32BlockSize<=ui32MaxSize; ui32BlockSize<<=1) { ui32BufLen += sprintf(szTempBuffer + ui32BufLen, "%7u ",ui32BlockSize); } PVR_TRACE((szTempBuffer)); /* Spacer */ ui32BufLen = sprintf(szTempBuffer, "--------"); /* Draw separator */ for (ui32BlockSize=512; ui32BlockSize<=ui32MaxSize; ui32BlockSize<<=1) { ui32BufLen += sprintf(szTempBuffer + ui32BufLen, "-------|"); } PVR_TRACE((szTempBuffer)); /* Row header */ ui32BufLen = sprintf(szTempBuffer, "H -> VB:"); /* Host to VB copy */ for (ui32BlockSize=512,ui32BlockNumber=0; ui32BlockSize<=ui32MaxSize; ui32BlockSize<<=1,ui32BlockNumber++) { IMG_UINT32 ui32Start, ui32Stop, ui32Total; IMG_UINT32 ui32Count; IMG_FLOAT fMB, fSeconds; ui32Start = PVRSRVMetricsTimeNow(); for (ui32Count=0; ui32Count<10; ui32Count++) { GLES1MemCopy(pui32VBuffer, pui32HostBuffer1, ui32BlockSize); } ui32Stop = PVRSRVMetricsTimeNow(); ui32Total = ui32Stop - ui32Start; fMB = 10.0f*ui32BlockSize; fMB /= (1024.0f*1024.0f); fSeconds = (IMG_FLOAT)ui32Total; fSeconds *= (gc->fCPUSpeed/1000.0f); ui32BufLen += sprintf(szTempBuffer + ui32BufLen, "%7.2f ", fSeconds?fMB/fSeconds:0.0f); } PVR_TRACE((szTempBuffer)); /* Row header */ ui32BufLen = sprintf(szTempBuffer, "H -> H:"); /* Host to Host copy */ for (ui32BlockSize=512,ui32BlockNumber=0; ui32BlockSize<=ui32MaxSize; ui32BlockSize<<=1,ui32BlockNumber++) { IMG_UINT32 ui32Start, ui32Stop, ui32Total; IMG_UINT32 ui32Count; IMG_FLOAT fMB, fSeconds; ui32Start = PVRSRVMetricsTimeNow(); for (ui32Count=0; ui32Count<10; ui32Count++) { GLES1MemCopy(pui32HostBuffer2, pui32HostBuffer1, ui32BlockSize); } ui32Stop = PVRSRVMetricsTimeNow(); ui32Total = ui32Stop - ui32Start; fMB = 10.0f*ui32BlockSize; fMB /= (1024.0f*1024.0f); fSeconds = (IMG_FLOAT)ui32Total; fSeconds *= (gc->fCPUSpeed/1000.0f); ui32BufLen += sprintf(szTempBuffer + ui32BufLen, "%7.2f ", fSeconds?fMB/fSeconds:0.0f); } PVR_TRACE((szTempBuffer)); GLES1Free(gc, pui32RealHostBuffer1); GLES1Free(gc, pui32RealHostBuffer2); }
IMG_EXPORT PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle, PVRSRV_TRANSFER_SGX_KICK *psKick) #endif { PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psKick->hCCBMemInfo; SGXMKIF_COMMAND sCommand = {0}; SGXMKIF_TRANSFERCMD_SHARED *psSharedTransferCmd; PVRSRV_KERNEL_SYNC_INFO *psSyncInfo; PVRSRV_ERROR eError; IMG_UINT32 loop; IMG_HANDLE hDevMemContext = IMG_NULL; IMG_BOOL abSrcSyncEnable[SGX_MAX_TRANSFER_SYNC_OPS]; IMG_UINT32 ui32RealSrcSyncNum = 0; IMG_BOOL abDstSyncEnable[SGX_MAX_TRANSFER_SYNC_OPS]; IMG_UINT32 ui32RealDstSyncNum = 0; #if defined(PDUMP) IMG_BOOL bPersistentProcess = IMG_FALSE; { PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData(); if(psPerProc != IMG_NULL) { bPersistentProcess = psPerProc->bPDumpPersistent; } } #endif #if defined(FIX_HW_BRN_31620) hDevMemContext = psKick->hDevMemContext; #endif PVR_TTRACE(PVRSRV_TRACE_GROUP_TRANSFER, PVRSRV_TRACE_CLASS_FUNCTION_ENTER, TRANSFER_TOKEN_SUBMIT); for (loop = 0; loop < SGX_MAX_TRANSFER_SYNC_OPS; loop++) { abSrcSyncEnable[loop] = IMG_TRUE; abDstSyncEnable[loop] = IMG_TRUE; } if (!CCB_OFFSET_IS_VALID(SGXMKIF_TRANSFERCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset)) { PVR_DPF((PVR_DBG_ERROR, "SGXSubmitTransferKM: Invalid CCB offset")); PVR_TTRACE(PVRSRV_TRACE_GROUP_TRANSFER, PVRSRV_TRACE_CLASS_FUNCTION_EXIT, TRANSFER_TOKEN_SUBMIT); return PVRSRV_ERROR_INVALID_PARAMS; } psSharedTransferCmd = CCB_DATA_FROM_OFFSET(SGXMKIF_TRANSFERCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset); PVR_TTRACE(PVRSRV_TRACE_GROUP_TRANSFER, PVRSRV_TRACE_CLASS_CMD_START, TRANSFER_TOKEN_SUBMIT); PVR_TTRACE_UI32(PVRSRV_TRACE_GROUP_TRANSFER, PVRSRV_TRACE_CLASS_CCB, TRANSFER_TOKEN_CCB_OFFSET, psKick->ui32SharedCmdCCBOffset); if (psKick->hTASyncInfo != IMG_NULL) { psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo; PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_TRANSFER, TRANSFER_TOKEN_TA_SYNC, psSyncInfo, PVRSRV_SYNCOP_SAMPLE); psSharedTransferCmd->ui32TASyncWriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++; psSharedTransferCmd->ui32TASyncReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending; psSharedTransferCmd->sTASyncWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr; psSharedTransferCmd->sTASyncReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr; } else { psSharedTransferCmd->sTASyncWriteOpsCompleteDevVAddr.uiAddr = 0; psSharedTransferCmd->sTASyncReadOpsCompleteDevVAddr.uiAddr = 0; } if (psKick->h3DSyncInfo != IMG_NULL) { psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo; PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_TRANSFER, TRANSFER_TOKEN_3D_SYNC, psSyncInfo, PVRSRV_SYNCOP_SAMPLE); psSharedTransferCmd->ui323DSyncWriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++; psSharedTransferCmd->ui323DSyncReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending; psSharedTransferCmd->s3DSyncWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr; psSharedTransferCmd->s3DSyncReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr; } else { psSharedTransferCmd->s3DSyncWriteOpsCompleteDevVAddr.uiAddr = 0; psSharedTransferCmd->s3DSyncReadOpsCompleteDevVAddr.uiAddr = 0; } for (loop = 0; loop < MIN(SGX_MAX_TRANSFER_SYNC_OPS, psKick->ui32NumSrcSync); loop++) { IMG_UINT32 i; PVRSRV_KERNEL_SYNC_INFO * psMySyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[loop]; for (i = 0; i < loop; i++) { if (abSrcSyncEnable[i]) { psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[i]; if (psSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr == psMySyncInfo->sWriteOpsCompleteDevVAddr.uiAddr) { PVR_DPF((PVR_DBG_WARNING, "SGXSubmitTransferKM : Same src synchronized multiple times!")); abSrcSyncEnable[loop] = IMG_FALSE; break; } } } if (abSrcSyncEnable[loop]) { ui32RealSrcSyncNum++; } } for (loop = 0; loop < MIN(SGX_MAX_TRANSFER_SYNC_OPS, psKick->ui32NumDstSync); loop++) { IMG_UINT32 i; PVRSRV_KERNEL_SYNC_INFO * psMySyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[loop]; for (i = 0; i < loop; i++) { if (abDstSyncEnable[i]) { psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[i]; if (psSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr == psMySyncInfo->sWriteOpsCompleteDevVAddr.uiAddr) { PVR_DPF((PVR_DBG_WARNING, "SGXSubmitTransferKM : Same dst synchronized multiple times!")); abDstSyncEnable[loop] = IMG_FALSE; break; } } } if (abDstSyncEnable[loop]) { ui32RealDstSyncNum++; } } psSharedTransferCmd->ui32NumSrcSyncs = ui32RealSrcSyncNum; psSharedTransferCmd->ui32NumDstSyncs = ui32RealDstSyncNum; if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL) { IMG_UINT32 i = 0; for (loop = 0; loop < psKick->ui32NumSrcSync; loop++) { if (abSrcSyncEnable[loop]) { psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[loop]; PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_TRANSFER, TRANSFER_TOKEN_SRC_SYNC, psSyncInfo, PVRSRV_SYNCOP_SAMPLE); psSharedTransferCmd->asSrcSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending; psSharedTransferCmd->asSrcSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending; psSharedTransferCmd->asSrcSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr; psSharedTransferCmd->asSrcSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr; i++; } } PVR_ASSERT(i == ui32RealSrcSyncNum); i = 0; for (loop = 0; loop < psKick->ui32NumDstSync; loop++) { if (abDstSyncEnable[loop]) { psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[loop]; psSyncInfo->psSyncData->ui64LastWrite = ui64KickCount; PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_TRANSFER, TRANSFER_TOKEN_DST_SYNC, psSyncInfo, PVRSRV_SYNCOP_SAMPLE); psSharedTransferCmd->asDstSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending; psSharedTransferCmd->asDstSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending; psSharedTransferCmd->asDstSyncs[i].ui32ReadOps2PendingVal = psSyncInfo->psSyncData->ui32ReadOps2Pending; psSharedTransferCmd->asDstSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr; psSharedTransferCmd->asDstSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr; psSharedTransferCmd->asDstSyncs[i].sReadOps2CompleteDevVAddr = psSyncInfo->sReadOps2CompleteDevVAddr; i++; } } PVR_ASSERT(i == ui32RealDstSyncNum); for (loop = 0; loop < psKick->ui32NumSrcSync; loop++) { if (abSrcSyncEnable[loop]) { psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[loop]; psSyncInfo->psSyncData->ui32ReadOpsPending++; } } for (loop = 0; loop < psKick->ui32NumDstSync; loop++) { if (abDstSyncEnable[loop]) { psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[loop]; psSyncInfo->psSyncData->ui32WriteOpsPending++; } } } #if defined(PDUMP) if ((PDumpIsCaptureFrameKM() || ((psKick->ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0)) && (bPersistentProcess == IMG_FALSE) ) { PDUMPCOMMENT("Shared part of transfer command\r\n"); PDUMPMEM(psSharedTransferCmd, psCCBMemInfo, psKick->ui32CCBDumpWOff, sizeof(SGXMKIF_TRANSFERCMD_SHARED), psKick->ui32PDumpFlags, MAKEUNIQUETAG(psCCBMemInfo)); if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL) { IMG_UINT32 i = 0; for (loop = 0; loop < psKick->ui32NumSrcSync; loop++) { if (abSrcSyncEnable[loop]) { psSyncInfo = psKick->ahSrcSyncInfo[loop]; PDUMPCOMMENT("Hack src surface write op in transfer cmd\r\n"); PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal, psCCBMemInfo, psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, asSrcSyncs) + i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal)), sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal), psKick->ui32PDumpFlags, MAKEUNIQUETAG(psCCBMemInfo)); PDUMPCOMMENT("Hack src surface read op in transfer cmd\r\n"); PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal, psCCBMemInfo, psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, asSrcSyncs) + i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal)), sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal), psKick->ui32PDumpFlags, MAKEUNIQUETAG(psCCBMemInfo)); i++; } } i = 0; for (loop = 0; loop < psKick->ui32NumDstSync; loop++) { if (abDstSyncEnable[i]) { IMG_UINT32 ui32PDumpReadOp2 = 0; psSyncInfo = psKick->ahDstSyncInfo[loop]; PDUMPCOMMENT("Hack dest surface write op in transfer cmd\r\n"); PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal, psCCBMemInfo, psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, asDstSyncs) + i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal)), sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal), psKick->ui32PDumpFlags, MAKEUNIQUETAG(psCCBMemInfo)); PDUMPCOMMENT("Hack dest surface read op in transfer cmd\r\n"); PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal, psCCBMemInfo, psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, asDstSyncs) + i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal)), sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal), psKick->ui32PDumpFlags, MAKEUNIQUETAG(psCCBMemInfo)); PDUMPCOMMENT("Hack dest surface read op2 in transfer cmd\r\n"); PDUMPMEM(&ui32PDumpReadOp2, psCCBMemInfo, psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, asDstSyncs) + i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOps2PendingVal)), sizeof(ui32PDumpReadOp2), psKick->ui32PDumpFlags, MAKEUNIQUETAG(psCCBMemInfo)); i++; } } for (loop = 0; loop < (psKick->ui32NumSrcSync); loop++) { if (abSrcSyncEnable[loop]) { psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[loop]; psSyncInfo->psSyncData->ui32LastReadOpDumpVal++; } } for (loop = 0; loop < (psKick->ui32NumDstSync); loop++) { if (abDstSyncEnable[loop]) { psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[0]; psSyncInfo->psSyncData->ui32LastOpDumpVal++; } } } if (psKick->hTASyncInfo != IMG_NULL) { psSyncInfo = psKick->hTASyncInfo; PDUMPCOMMENT("Tweak TA/TQ surface write op in transfer cmd\r\n"); PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal, psCCBMemInfo, psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, ui32TASyncWriteOpsPendingVal)), sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal), psKick->ui32PDumpFlags, MAKEUNIQUETAG(psCCBMemInfo)); psSyncInfo->psSyncData->ui32LastOpDumpVal++; } if (psKick->h3DSyncInfo != IMG_NULL) { psSyncInfo = psKick->h3DSyncInfo; PDUMPCOMMENT("Tweak 3D/TQ surface write op in transfer cmd\r\n"); PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal, psCCBMemInfo, psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, ui323DSyncWriteOpsPendingVal)), sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal), psKick->ui32PDumpFlags, MAKEUNIQUETAG(psCCBMemInfo)); psSyncInfo->psSyncData->ui32LastOpDumpVal++; } } #endif sCommand.ui32Data[1] = psKick->sHWTransferContextDevVAddr.uiAddr; PVR_TTRACE(PVRSRV_TRACE_GROUP_TRANSFER, PVRSRV_TRACE_CLASS_CMD_END, TRANSFER_TOKEN_SUBMIT); eError = SGXScheduleCCBCommandKM(hDevHandle, SGXMKIF_CMD_TRANSFER, &sCommand, KERNEL_ID, psKick->ui32PDumpFlags, hDevMemContext, IMG_FALSE); if (eError == PVRSRV_ERROR_RETRY) { if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL) { for (loop = 0; loop < psKick->ui32NumSrcSync; loop++) { if (abSrcSyncEnable[loop]) { psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[loop]; psSyncInfo->psSyncData->ui32ReadOpsPending--; #if defined(PDUMP) if (PDumpIsCaptureFrameKM() || ((psKick->ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0)) { psSyncInfo->psSyncData->ui32LastReadOpDumpVal--; } #endif } } for (loop = 0; loop < psKick->ui32NumDstSync; loop++) { if (abDstSyncEnable[loop]) { psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[loop]; psSyncInfo->psSyncData->ui32WriteOpsPending--; #if defined(PDUMP) if (PDumpIsCaptureFrameKM() || ((psKick->ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0)) { psSyncInfo->psSyncData->ui32LastOpDumpVal--; } #endif } } } if (psKick->hTASyncInfo != IMG_NULL) { psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo; psSyncInfo->psSyncData->ui32WriteOpsPending--; } if (psKick->h3DSyncInfo != IMG_NULL) { psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo; psSyncInfo->psSyncData->ui32WriteOpsPending--; } } else if (PVRSRV_OK != eError) { PVR_DPF((PVR_DBG_ERROR, "SGXSubmitTransferKM: SGXScheduleCCBCommandKM failed.")); PVR_TTRACE(PVRSRV_TRACE_GROUP_TRANSFER, PVRSRV_TRACE_CLASS_FUNCTION_EXIT, TRANSFER_TOKEN_SUBMIT); return eError; } #if defined(NO_HARDWARE) if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_NOSYNCUPDATE) == 0) { for (loop = 0; loop < psKick->ui32NumSrcSync; loop++) { if (abSrcSyncEnable[loop]) { psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[loop]; psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending; } } for (loop = 0; loop < psKick->ui32NumDstSync; loop++) { if (abDstSyncEnable[loop]) { psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[loop]; psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending; } } if (psKick->hTASyncInfo != IMG_NULL) { psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo; psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending; } if (psKick->h3DSyncInfo != IMG_NULL) { psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo; psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending; } } #endif PVR_TTRACE(PVRSRV_TRACE_GROUP_TRANSFER, PVRSRV_TRACE_CLASS_FUNCTION_EXIT, TRANSFER_TOKEN_SUBMIT); return eError; }
PVRSRV_ERROR EnableSGXClocks(SYS_DATA *psSysData) { #if !defined(NO_HARDWARE) SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData; if (atomic_read(&psSysSpecData->sSGXClocksEnabled) != 0) { return PVRSRV_OK; } PVR_DPF((PVR_DBG_MESSAGE, "EnableSGXClocks: Enabling SGX Clocks")); #if defined(LDM_PLATFORM) && !defined(PVR_DRI_DRM_NOT_PCI) && defined(CONFIG_PM_RUNTIME) { int res = pm_runtime_get_sync(&gpsPVRLDMDev->dev); if (res < 0) { PVR_DPF((PVR_DBG_ERROR, "EnableSGXClocks: pm_runtime_get_sync failed (%d)", -res)); return PVRSRV_ERROR_UNABLE_TO_ENABLE_CLOCK; } } #endif //disable_clock(MT65XX_PDN_MM_MFG_HALF, "MFG"); //disable_clock(MT65XX_PDN_MM_MFG, "MFG"); //disable_clock(MT65XX_PDN_MM_G3D, "MFG"); #if USE_SYS_CLOCK #if !defined(MTK_CLK_CTRL) DRV_WriteReg16(PLL_CON11, DRV_Reg16(PLL_CON11)|0x0C00); // F3D_CK_SEL #endif DRV_WriteReg32(MMSYS2_CONFG_BASE + 0x0504, 0x4); // MFG_CORE_CK_SEL DCM #else #if !defined(MTK_CLK_CTRL) DRV_WriteReg16(PLL_CON11, DRV_Reg16(PLL_CON11)|0x0C00); // F3D_CK_SEL #endif DRV_WriteReg32(MMSYS2_CONFG_BASE + 0x0504, 0x6); // MFG_CORE_CK_SEL DCM #endif //DRV_WriteReg32(MMSYS2_CONFG_BASE+0x400, DRV_Reg32(MMSYS2_CONFG_BASE+0x400)|0x4); enable_clock(MT65XX_PDN_MM_G3D, "MFG"); enable_clock(MT65XX_PDN_MM_MFG, "MFG"); enable_clock(MT65XX_PDN_MM_MFG_HALF, "MFG"); DRV_WriteReg32(MMSYS2_CONFG_BASE+0x400, DRV_Reg32(MMSYS2_CONFG_BASE+0x400)|0x4); #if defined(MTK_USE_GDC) SysInitGDC(); #endif #if 0 DRV_WriteReg16(0xF0007404, 0x6); DRV_WriteReg16(0xF0007400, 0x4800); DRV_WriteReg16(0xF0007400, 0x0800); DRV_WriteReg16(0xF0007400, 0x8800); while(DRV_Reg16(0xF0007404) & 0x8000){} PVRSRVReleasePrintf("MainPLL: 0x%x", DRV_Reg16(0xF0007410)); DRV_WriteReg16(0xF0007404, 0x15); DRV_WriteReg16(0xF0007400, 0x4800); DRV_WriteReg16(0xF0007400, 0x0800); DRV_WriteReg16(0xF0007400, 0x8800); while(DRV_Reg16(0xF0007404) & 0x8000){} PVRSRVReleasePrintf("MEMPLL: 0x%x", DRV_Reg16(0xF0007410)); #endif SysEnableSGXInterrupts(psSysData); atomic_set(&psSysSpecData->sSGXClocksEnabled, 1); #else PVR_UNREFERENCED_PARAMETER(psSysData); #endif return PVRSRV_OK; }
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_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 | /* FIXME: Client CCB Ctl should be read-only for the CPU (it is not because for now we initialize it from the host) */ 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; 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; }
static PVRSRV_ERROR SysLocateDevices(SYS_DATA *psSysData) { #if defined(NO_HARDWARE) PVRSRV_ERROR eError; IMG_CPU_PHYADDR sCpuPAddr; #else #if defined(PVR_LINUX_DYNAMIC_SGX_RESOURCE_INFO) struct resource *dev_res; int dev_irq; #endif #endif PVR_UNREFERENCED_PARAMETER(psSysData); gsSGXDeviceMap.ui32Flags = 0x0; #if defined(NO_HARDWARE) gsSGXDeviceMap.ui32RegsSize = SYS_OMAP3430_SGX_REGS_SIZE; eError = OSBaseAllocContigMemory(gsSGXDeviceMap.ui32RegsSize, &gsSGXRegsCPUVAddr, &sCpuPAddr); if(eError != PVRSRV_OK) { return eError; } gsSGXDeviceMap.sRegsCpuPBase = sCpuPAddr; gsSGXDeviceMap.sRegsSysPBase = SysCpuPAddrToSysPAddr(gsSGXDeviceMap.sRegsCpuPBase); #if defined(__linux__) gsSGXDeviceMap.pvRegsCpuVBase = gsSGXRegsCPUVAddr; #else gsSGXDeviceMap.pvRegsCpuVBase = IMG_NULL; #endif OSMemSet(gsSGXRegsCPUVAddr, 0, gsSGXDeviceMap.ui32RegsSize); gsSGXDeviceMap.ui32IRQ = 0; #else #if defined(PVR_LINUX_DYNAMIC_SGX_RESOURCE_INFO) dev_res = platform_get_resource(gpsPVRLDMDev, IORESOURCE_MEM, 0); if (dev_res == NULL) { PVR_DPF((PVR_DBG_ERROR, "%s: platform_get_resource failed", __FUNCTION__)); return PVRSRV_ERROR_INVALID_DEVICE; } dev_irq = platform_get_irq(gpsPVRLDMDev, 0); if (dev_irq < 0) { PVR_DPF((PVR_DBG_ERROR, "%s: platform_get_irq failed (%d)", __FUNCTION__, -dev_irq)); return PVRSRV_ERROR_INVALID_DEVICE; } gsSGXDeviceMap.sRegsSysPBase.uiAddr = dev_res->start; gsSGXDeviceMap.sRegsCpuPBase = SysSysPAddrToCpuPAddr(gsSGXDeviceMap.sRegsSysPBase); PVR_TRACE(("SGX register base: 0x%lx", (unsigned long)gsSGXDeviceMap.sRegsCpuPBase.uiAddr)); gsSGXDeviceMap.ui32RegsSize = (unsigned int)(dev_res->end - dev_res->start); PVR_TRACE(("SGX register size: %d",gsSGXDeviceMap.ui32RegsSize)); gsSGXDeviceMap.ui32IRQ = dev_irq; PVR_TRACE(("SGX IRQ: %d", gsSGXDeviceMap.ui32IRQ)); #else gsSGXDeviceMap.sRegsSysPBase.uiAddr = SYS_OMAP3430_SGX_REGS_SYS_PHYS_BASE; gsSGXDeviceMap.sRegsCpuPBase = SysSysPAddrToCpuPAddr(gsSGXDeviceMap.sRegsSysPBase); gsSGXDeviceMap.ui32RegsSize = SYS_OMAP3430_SGX_REGS_SIZE; gsSGXDeviceMap.ui32IRQ = SYS_OMAP3430_SGX_IRQ; #endif #if defined(SGX_OCP_REGS_ENABLED) gsSGXRegsCPUVAddr = OSMapPhysToLin(gsSGXDeviceMap.sRegsCpuPBase, gsSGXDeviceMap.ui32RegsSize, PVRSRV_HAP_UNCACHED|PVRSRV_HAP_KERNEL_ONLY, IMG_NULL); if (gsSGXRegsCPUVAddr == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR,"SysLocateDevices: Failed to map SGX registers")); return PVRSRV_ERROR_BAD_MAPPING; } gsSGXDeviceMap.pvRegsCpuVBase = gsSGXRegsCPUVAddr; gpvOCPRegsLinAddr = gsSGXRegsCPUVAddr; #endif #endif #if defined(PDUMP) { static IMG_CHAR pszPDumpDevName[] = "SGXMEM"; gsSGXDeviceMap.pszPDumpDevName = pszPDumpDevName; } #endif return PVRSRV_OK; }
static IMG_VOID _RGXClientCCBDumpCommands(RGX_CLIENT_CCB *psClientCCB, IMG_UINT32 ui32Offset, IMG_UINT32 ui32ByteCount) { #if defined(SUPPORT_DUMP_CLIENT_CCB_COMMANDS) IMG_UINT8 *pui8Ptr = psClientCCB->pui8ClientCCB + ui32Offset; IMG_UINT32 ui32ConsumeSize = ui32ByteCount; while (ui32ConsumeSize) { RGXFWIF_CCB_CMD_HEADER *psHeader = (RGXFWIF_CCB_CMD_HEADER *) pui8Ptr; IMG_BOOL bFenceUpdate = IMG_FALSE; PVR_DPF((SUPPORT_DUMP_CLIENT_CCB_COMMANDS_DBG_LEVEL, "@offset 0x%08x", pui8Ptr - psClientCCB->pui8ClientCCB)); switch(psHeader->eCmdType) { CHECK_COMMAND(TA, IMG_FALSE); CHECK_COMMAND(3D, IMG_FALSE); CHECK_COMMAND(CDM, IMG_FALSE); CHECK_COMMAND(TQ_3D, IMG_FALSE); CHECK_COMMAND(TQ_2D, IMG_FALSE); CHECK_COMMAND(3D_PR, IMG_FALSE); CHECK_COMMAND(NULL, IMG_FALSE); CHECK_COMMAND(SHG, IMG_FALSE); CHECK_COMMAND(RTU, IMG_FALSE); CHECK_COMMAND(RTU_FC, IMG_FALSE); CHECK_COMMAND(FENCE, IMG_TRUE); CHECK_COMMAND(UPDATE, IMG_TRUE); CHECK_COMMAND(FENCE_PR, IMG_TRUE); CHECK_COMMAND(PADDING, IMG_FALSE); default: PVR_DPF((SUPPORT_DUMP_CLIENT_CCB_COMMANDS_DBG_LEVEL, "Unknown command!")); break; } pui8Ptr += sizeof(*psHeader); if (bFenceUpdate) { IMG_UINT32 j; RGXFWIF_UFO *psUFOPtr = (RGXFWIF_UFO *) pui8Ptr; for (j=0;j<psHeader->ui32CmdSize/sizeof(RGXFWIF_UFO);j++) { PVR_DPF((SUPPORT_DUMP_CLIENT_CCB_COMMANDS_DBG_LEVEL, "Addr = 0x%08x, value = 0x%08x", psUFOPtr[j].puiAddrUFO.ui32Addr, psUFOPtr[j].ui32Value)); } } else { IMG_UINT32 *pui32Ptr = (IMG_UINT32 *) pui8Ptr; IMG_UINT32 ui32Remain = psHeader->ui32CmdSize/sizeof(IMG_UINT32); while(ui32Remain) { if (ui32Remain >= 4) { PVR_DPF((SUPPORT_DUMP_CLIENT_CCB_COMMANDS_DBG_LEVEL, "0x%08x 0x%08x 0x%08x 0x%08x", pui32Ptr[0], pui32Ptr[1], pui32Ptr[2], pui32Ptr[3])); pui32Ptr += 4; ui32Remain -= 4; } if (ui32Remain == 3) { PVR_DPF((SUPPORT_DUMP_CLIENT_CCB_COMMANDS_DBG_LEVEL, "0x%08x 0x%08x 0x%08x", pui32Ptr[0], pui32Ptr[1], pui32Ptr[2])); pui32Ptr += 3; ui32Remain -= 3; } if (ui32Remain == 2) { PVR_DPF((SUPPORT_DUMP_CLIENT_CCB_COMMANDS_DBG_LEVEL, "0x%08x 0x%08x", pui32Ptr[0], pui32Ptr[1])); pui32Ptr += 2; ui32Remain -= 2; } if (ui32Remain == 1) { PVR_DPF((SUPPORT_DUMP_CLIENT_CCB_COMMANDS_DBG_LEVEL, "0x%08x", pui32Ptr[0])); pui32Ptr += 1; ui32Remain -= 1; } } } pui8Ptr += psHeader->ui32CmdSize; ui32ConsumeSize -= sizeof(*psHeader) + psHeader->ui32CmdSize; } #else PVR_UNREFERENCED_PARAMETER(psClientCCB); PVR_UNREFERENCED_PARAMETER(ui32Offset); PVR_UNREFERENCED_PARAMETER(ui32ByteCount); #endif }
PVRSRV_ERROR SysInitialise(IMG_VOID) { IMG_UINT32 i; PVRSRV_ERROR eError; PVRSRV_DEVICE_NODE *psDeviceNode; #if !defined(PVR_NO_OMAP_TIMER) IMG_CPU_PHYADDR TimerRegPhysBase; #endif #if !defined(SGX_DYNAMIC_TIMING_INFO) SGX_TIMING_INFORMATION* psTimingInfo; #endif gpsSysData = &gsSysData; OSMemSet(gpsSysData, 0, sizeof(SYS_DATA)); gpsSysSpecificData = &gsSysSpecificData; OSMemSet(gpsSysSpecificData, 0, sizeof(SYS_SPECIFIC_DATA)); gpsSysData->pvSysSpecificData = gpsSysSpecificData; eError = OSInitEnvData(&gpsSysData->pvEnvSpecificData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to setup env structure")); (IMG_VOID)SysDeinitialise(gpsSysData); gpsSysData = IMG_NULL; return eError; } SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_ENVDATA); gpsSysData->ui32NumDevices = SYS_DEVICE_COUNT; for(i=0; i<SYS_DEVICE_COUNT; i++) { gpsSysData->sDeviceID[i].uiID = i; gpsSysData->sDeviceID[i].bInUse = IMG_FALSE; } gpsSysData->psDeviceNodeList = IMG_NULL; gpsSysData->psQueueList = IMG_NULL; eError = SysInitialiseCommon(gpsSysData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed in SysInitialiseCommon")); (IMG_VOID)SysDeinitialise(gpsSysData); gpsSysData = IMG_NULL; return eError; } #if !defined(SGX_DYNAMIC_TIMING_INFO) psTimingInfo = &gsSGXDeviceMap.sTimingInfo; psTimingInfo->ui32CoreClockSpeed = SYS_SGX_CLOCK_SPEED; psTimingInfo->ui32HWRecoveryFreq = SYS_SGX_HWRECOVERY_TIMEOUT_FREQ; #if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT) psTimingInfo->bEnableActivePM = IMG_TRUE; #else psTimingInfo->bEnableActivePM = IMG_FALSE; #endif psTimingInfo->ui32ActivePowManLatencyms = SYS_SGX_ACTIVE_POWER_LATENCY_MS; psTimingInfo->ui32uKernelFreq = SYS_SGX_PDS_TIMER_FREQ; #endif gpsSysSpecificData->ui32SrcClockDiv = 3; eError = SysLocateDevices(gpsSysData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to locate devices")); (IMG_VOID)SysDeinitialise(gpsSysData); gpsSysData = IMG_NULL; return eError; } SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_LOCATEDEV); #if 0 eError = SysPMRuntimeRegister(); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to register with OSPM!")); (IMG_VOID)SysDeinitialise(gpsSysData); gpsSysData = IMG_NULL; return eError; } SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_PM_RUNTIME); #endif eError = PVRSRVRegisterDevice(gpsSysData, SGXRegisterDevice, DEVICE_SGX_INTERRUPT, &gui32SGXDeviceID); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to register device!")); (IMG_VOID)SysDeinitialise(gpsSysData); gpsSysData = IMG_NULL; return eError; } SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_REGDEV); psDeviceNode = gpsSysData->psDeviceNodeList; while(psDeviceNode) { switch(psDeviceNode->sDevId.eDeviceType) { case PVRSRV_DEVICE_TYPE_SGX: { DEVICE_MEMORY_INFO *psDevMemoryInfo; DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap; psDeviceNode->psLocalDevMemArena = IMG_NULL; psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo; psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap; for(i=0; i<psDevMemoryInfo->ui32HeapCount; i++) { psDeviceMemoryHeap[i].ui32Attribs |= PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG; } gpsSGXDevNode = psDeviceNode; gsSysSpecificData.psSGXDevNode = psDeviceNode; break; } default: PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to find SGX device node!")); return PVRSRV_ERROR_INIT_FAILURE; } psDeviceNode = psDeviceNode->psNext; } eError = EnableSystemClocksWrap(gpsSysData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to Enable system clocks (%d)", eError)); (IMG_VOID)SysDeinitialise(gpsSysData); gpsSysData = IMG_NULL; return eError; } SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS); #if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT) eError = EnableSGXClocksWrap(gpsSysData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to Enable SGX clocks (%d)", eError)); (IMG_VOID)SysDeinitialise(gpsSysData); gpsSysData = IMG_NULL; return eError; } #endif eError = PVRSRVInitialiseDevice(gui32SGXDeviceID); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to initialise device!")); (IMG_VOID)SysDeinitialise(gpsSysData); gpsSysData = IMG_NULL; return eError; } SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_INITDEV); #if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT) DisableSGXClocks(gpsSysData); #endif #if !defined(PVR_NO_OMAP_TIMER) #if defined(PVR_OMAP_TIMER_BASE_IN_SYS_SPEC_DATA) TimerRegPhysBase = gsSysSpecificData.sTimerRegPhysBase; #else TimerRegPhysBase.uiAddr = SYS_OMAP3430_GP11TIMER_REGS_SYS_PHYS_BASE; #endif gpsSysData->pvSOCTimerRegisterKM = IMG_NULL; gpsSysData->hSOCTimerRegisterOSMemHandle = 0; if (TimerRegPhysBase.uiAddr != 0) { OSReservePhys(TimerRegPhysBase, 4, PVRSRV_HAP_MULTI_PROCESS|PVRSRV_HAP_UNCACHED, IMG_NULL, (IMG_VOID **)&gpsSysData->pvSOCTimerRegisterKM, &gpsSysData->hSOCTimerRegisterOSMemHandle); } #endif return PVRSRV_OK; }
static PVRSRV_ERROR _RGXCCBPDumpTransition(IMG_PVOID *pvData, IMG_BOOL bInto, IMG_BOOL bContinuous) { RGX_CLIENT_CCB *psClientCCB = (RGX_CLIENT_CCB *) pvData; IMG_UINT32 ui32PDumpFlags = bContinuous ? PDUMP_FLAGS_CONTINUOUS:0; /* We're about to Transition into capture range and we've submitted new commands since the last time we entered capture range so drain the CCB as required */ if (bInto) { volatile RGXFWIF_CCCB_CTL *psCCBCtl = psClientCCB->psClientCCBCtrl; PVRSRV_ERROR eError; /* Wait for the FW to catch up (retry will get pushed back out services client where we wait on the event object and try again later) */ if (psClientCCB->psClientCCBCtrl->ui32ReadOffset != psClientCCB->ui32HostWriteOffset) { return PVRSRV_ERROR_RETRY; } /* We drain whenever capture range is entered. Even if no commands have been issued while where out of capture range we have to wait for operations that we might have issued in the last capture range to finish so the sync prim update that will happen after all the PDumpTransition callbacks have been called doesn't clobber syncs which the FW is currently working on. Although this is suboptimal, while out of capture range for every persistent operation we serialise the PDump script processing and the FW, there is no easy solution. Not all modules that work on syncs register a PDumpTransition and thus we have no way of knowing if we can skip drain and the sync prim dump or not. */ PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "cCCB(%s@%p): Draining rgxfw_roff == woff (%d)", psClientCCB->szName, psClientCCB, psClientCCB->ui32LastPDumpWriteOffset); eError = DevmemPDumpDevmemPol32(psClientCCB->psClientCCBCtrlMemDesc, offsetof(RGXFWIF_CCCB_CTL, ui32ReadOffset), psClientCCB->ui32LastPDumpWriteOffset, 0xffffffff, PDUMP_POLL_OPERATOR_EQUAL, ui32PDumpFlags); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_WARNING, "_RGXCCBPDumpTransition: problem pdumping POL for cCCBCtl (%d)", eError)); } PVR_ASSERT(eError == PVRSRV_OK); /* If new command(s) have been written out of capture range then we need to fast forward past uncaptured operations. */ if (psClientCCB->ui32LastPDumpWriteOffset != psClientCCB->ui32HostWriteOffset) { /* There are commands that where not captured so after the simulation drain (above) we also need to fast-forward pass those commands so the FW can start with the 1st command which is in the new capture range */ psCCBCtl->ui32ReadOffset = psClientCCB->ui32HostWriteOffset; psCCBCtl->ui32DepOffset = psClientCCB->ui32HostWriteOffset; psCCBCtl->ui32WriteOffset = psClientCCB->ui32HostWriteOffset; PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "cCCB(%s@%p): Fast-forward from %d to %d", psClientCCB->szName, psClientCCB, psClientCCB->ui32LastPDumpWriteOffset, psClientCCB->ui32HostWriteOffset); DevmemPDumpLoadMem(psClientCCB->psClientCCBCtrlMemDesc, 0, sizeof(RGXFWIF_CCCB_CTL), ui32PDumpFlags); /* Although we've entered capture range we might not do any work on this CCB so update the ui32LastPDumpWriteOffset to reflect where we got to for next so we start the drain from where we got to last time */ psClientCCB->ui32LastPDumpWriteOffset = psClientCCB->ui32HostWriteOffset; } } return PVRSRV_OK; }
PVRSRV_ERROR SysDeinitialise (SYS_DATA *psSysData) { PVRSRV_ERROR eError; if(gpsSysData->pvSOCTimerRegisterKM) { OSUnReservePhys(gpsSysData->pvSOCTimerRegisterKM, 4, PVRSRV_HAP_MULTI_PROCESS|PVRSRV_HAP_UNCACHED, gpsSysData->hSOCTimerRegisterOSMemHandle); } #if defined(SYS_USING_INTERRUPTS) if (SYS_SPECIFIC_DATA_TEST(gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_LISR)) { eError = OSUninstallDeviceLISR(psSysData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: OSUninstallDeviceLISR failed")); return eError; } } #endif if (SYS_SPECIFIC_DATA_TEST(gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_MISR)) { eError = OSUninstallMISR(psSysData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: OSUninstallMISR failed")); return eError; } } if (SYS_SPECIFIC_DATA_TEST(gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_INITDEV)) { #if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT) PVR_ASSERT(SYS_SPECIFIC_DATA_TEST(gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS)); eError = EnableSGXClocksWrap(gpsSysData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: EnableSGXClocks failed")); return eError; } #endif eError = PVRSRVDeinitialiseDevice (gui32SGXDeviceID); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: failed to de-init the device")); return eError; } } #if 0 if (SYS_SPECIFIC_DATA_TEST(gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_PM_RUNTIME)) { eError = SysPMRuntimeUnregister(); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: Failed to unregister with OSPM!")); gpsSysData = IMG_NULL; return eError; } } #endif if (SYS_SPECIFIC_DATA_TEST(gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS)) { DisableSystemClocks(gpsSysData); } if (SYS_SPECIFIC_DATA_TEST(gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_ENVDATA)) { eError = OSDeInitEnvData(gpsSysData->pvEnvSpecificData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: failed to de-init env structure")); return eError; } } SysDeinitialiseCommon(gpsSysData); #if defined(NO_HARDWARE) || defined(SGX_OCP_REGS_ENABLED) if(gsSGXRegsCPUVAddr != IMG_NULL) { #if defined(NO_HARDWARE) OSBaseFreeContigMemory(SYS_OMAP3430_SGX_REGS_SIZE, gsSGXRegsCPUVAddr, gsSGXDeviceMap.sRegsCpuPBase); #else #if defined(SGX_OCP_REGS_ENABLED) OSUnMapPhysToLin(gsSGXRegsCPUVAddr, gsSGXDeviceMap.ui32RegsSize, PVRSRV_HAP_UNCACHED|PVRSRV_HAP_KERNEL_ONLY, IMG_NULL); gpvOCPRegsLinAddr = IMG_NULL; #endif #endif gsSGXRegsCPUVAddr = IMG_NULL; gsSGXDeviceMap.pvRegsCpuVBase = gsSGXRegsCPUVAddr; } #endif gpsSysSpecificData->ui32SysSpecificData = 0; gpsSysSpecificData->bSGXInitComplete = IMG_FALSE; gpsSysData = IMG_NULL; return PVRSRV_OK; }
/*********************************************************************************** Function Name : AddInstruction Inputs : psUSEASMInfo, uOpcode, uFlags1, uFlags2, uTest, psArgs, ui32NumArgs Outputs : psUSEASMInfo Returns : - Description : Sets up USEASM instruction structure and adds it to the list ************************************************************************************/ IMG_INTERNAL IMG_VOID AddInstruction(GLES1Context *gc, GLESUSEASMInfo *psUSEASMInfo, USEASM_OPCODE uOpcode, IMG_UINT32 uFlags1, IMG_UINT32 uFlags2, IMG_UINT32 uTest, USE_REGISTER *psArgs, IMG_UINT32 ui32NumArgs) { USE_INST *psNewInstruction; IMG_UINT32 i; PVR_UNREFERENCED_PARAMETER(gc); psNewInstruction = GLES1Calloc(gc, sizeof(USE_INST)); if(!psNewInstruction) { PVR_DPF((PVR_DBG_ERROR,"AddInstruction(): Failed to allocate memory for new instruction")); return; } psNewInstruction->uOpcode = uOpcode; switch(uOpcode) { #if defined(SGX_FEATURE_USE_UNLIMITED_PHASES) case USEASM_OP_PHASIMM: #endif case USEASM_OP_PADDING: case USEASM_OP_SMLSI: case USEASM_OP_PCOEFF: case USEASM_OP_ATST8: case USEASM_OP_DEPTHF: { psNewInstruction->uFlags1 = uFlags1; break; } case USEASM_OP_SOP2WM: case USEASM_OP_LRP1: { psNewInstruction->uFlags1 = uFlags1 | USEASM_OPFLAGS1_SKIPINVALID | (0x1<<USEASM_OPFLAGS1_MASK_SHIFT); break; } default: { if(uFlags1 & USEASM_OPFLAGS1_TESTENABLE) { /* Set skip invalid by default */ psNewInstruction->uFlags1 = uFlags1 | USEASM_OPFLAGS1_SKIPINVALID; } else { /* Set skip invalid by default and repeat of 1 */ psNewInstruction->uFlags1 = uFlags1 | USEASM_OPFLAGS1_SKIPINVALID | (1<<USEASM_OPFLAGS1_REPEAT_SHIFT); } break; } } psNewInstruction->uFlags2 = uFlags2; /* IMG_UINT32 uFlags3; */ psNewInstruction->uTest = uTest; for(i=0; i<ui32NumArgs; i++) { psNewInstruction->asArg[i] = psArgs[i]; } if(psUSEASMInfo->psLastUSEASMInstruction) { /* Add new instruction to the end of the list */ psUSEASMInfo->psLastUSEASMInstruction->psNext = psNewInstruction; psNewInstruction->psPrev = psUSEASMInfo->psLastUSEASMInstruction; psNewInstruction->psNext = IMG_NULL; } else { /* The new instruction is the first instruction of the list */ psUSEASMInfo->psFirstUSEASMInstruction = psNewInstruction; psNewInstruction->psPrev = IMG_NULL; psNewInstruction->psNext = IMG_NULL; } /* IMG_UINT32 uSourceLine; */ /* IMG_PCHAR pszSourceFile;*/ /* The new instruction is the last instruction of the list */ psUSEASMInfo->psLastUSEASMInstruction = psNewInstruction; if((uFlags2 & USEASM_OPFLAGS2_COISSUE) == 0) { psUSEASMInfo->ui32NumMainUSEASMInstructions++; } }
PVRSRV_ERROR IMG_CALLCONV PVRSRVSaveRestoreLiveSegments(IMG_HANDLE hArena, IMG_PBYTE pbyBuffer, IMG_SIZE_T *puiBufSize, IMG_BOOL bSave) { IMG_SIZE_T uiBytesSaved = 0; IMG_PVOID pvLocalMemCPUVAddr; RA_SEGMENT_DETAILS sSegDetails; if (hArena == IMG_NULL) { return (PVRSRV_ERROR_INVALID_PARAMS); } sSegDetails.uiSize = 0; sSegDetails.sCpuPhyAddr.uiAddr = 0; sSegDetails.hSegment = 0; while (RA_GetNextLiveSegment(hArena, &sSegDetails)) { if (pbyBuffer == IMG_NULL) { uiBytesSaved += sizeof(sSegDetails.uiSize) + sSegDetails.uiSize; } else { if ((uiBytesSaved + sizeof(sSegDetails.uiSize) + sSegDetails.uiSize) > *puiBufSize) { return (PVRSRV_ERROR_OUT_OF_MEMORY); } PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVSaveRestoreLiveSegments: Base %08x size %08x", sSegDetails.sCpuPhyAddr.uiAddr, sSegDetails.uiSize)); pvLocalMemCPUVAddr = OSMapPhysToLin(sSegDetails.sCpuPhyAddr, sSegDetails.uiSize, PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED, IMG_NULL); if (pvLocalMemCPUVAddr == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVSaveRestoreLiveSegments: Failed to map local memory to host")); return (PVRSRV_ERROR_OUT_OF_MEMORY); } if (bSave) { OSMemCopy(pbyBuffer, &sSegDetails.uiSize, sizeof(sSegDetails.uiSize)); pbyBuffer += sizeof(sSegDetails.uiSize); OSMemCopy(pbyBuffer, pvLocalMemCPUVAddr, sSegDetails.uiSize); pbyBuffer += sSegDetails.uiSize; } else { IMG_UINT32 uiSize; OSMemCopy(&uiSize, pbyBuffer, sizeof(sSegDetails.uiSize)); if (uiSize != sSegDetails.uiSize) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVSaveRestoreLiveSegments: Segment size error")); } else { pbyBuffer += sizeof(sSegDetails.uiSize); OSMemCopy(pvLocalMemCPUVAddr, pbyBuffer, sSegDetails.uiSize); pbyBuffer += sSegDetails.uiSize; } } uiBytesSaved += sizeof(sSegDetails.uiSize) + sSegDetails.uiSize; OSUnMapPhysToLin(pvLocalMemCPUVAddr, sSegDetails.uiSize, PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED, IMG_NULL); } } if (pbyBuffer == IMG_NULL) { *puiBufSize = uiBytesSaved; } return (PVRSRV_OK); }
IMG_VOID SysSGXIdleTransition(IMG_BOOL bSGXIdle) { PVR_DPF((PVR_DBG_MESSAGE, "SysSGXIdleTransition switch to %u", bSGXIdle)); }
PVRSRV_ERROR IMG_CALLCONV PVRSRVDeinitialiseDevice(IMG_UINT32 ui32DevIndex) { PVRSRV_DEVICE_NODE *psDeviceNode; SYS_DATA *psSysData; PVRSRV_ERROR eError; SysAcquireData(&psSysData); psDeviceNode = (PVRSRV_DEVICE_NODE*) List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList, &MatchDeviceKM_AnyVaCb, ui32DevIndex, IMG_TRUE); if (!psDeviceNode) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: requested device %d is not present", ui32DevIndex)); return PVRSRV_ERROR_DEVICEID_NOT_FOUND; } eError = PVRSRVSetDevicePowerStateKM(ui32DevIndex, PVRSRV_DEV_POWER_STATE_OFF, KERNEL_ID, IMG_FALSE); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed PVRSRVSetDevicePowerStateKM call")); return eError; } eError = ResManFreeResByCriteria(psDeviceNode->hResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_ALLOCATION, IMG_NULL, 0); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed ResManFreeResByCriteria call")); return eError; } if(psDeviceNode->pfnDeInitDevice != IMG_NULL) { eError = psDeviceNode->pfnDeInitDevice(psDeviceNode); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed DeInitDevice call")); return eError; } } PVRSRVResManDisconnect(psDeviceNode->hResManContext, IMG_TRUE); psDeviceNode->hResManContext = IMG_NULL; List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode); (IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex); OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL); return (PVRSRV_OK); }
/*! ****************************************************************************** @Function SysInitialise @Description Initialises kernel services at 'driver load' time @Return PVRSRV_ERROR : ******************************************************************************/ PVRSRV_ERROR SysInitialise(IMG_VOID) { IMG_UINT32 i; PVRSRV_ERROR eError; PVRSRV_DEVICE_NODE *psDeviceNode; #if !defined(PVR_NO_OMAP_TIMER) IMG_CPU_PHYADDR TimerRegPhysBase; #endif #if !defined(SGX_DYNAMIC_TIMING_INFO) SGX_TIMING_INFORMATION* psTimingInfo; #endif gpsSysData = &gsSysData; OSMemSet(gpsSysData, 0, sizeof(SYS_DATA)); gpsSysSpecificData = &gsSysSpecificData; OSMemSet(gpsSysSpecificData, 0, sizeof(SYS_SPECIFIC_DATA)); gpsSysData->pvSysSpecificData = gpsSysSpecificData; eError = OSInitEnvData(&gpsSysData->pvEnvSpecificData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to setup env structure")); (IMG_VOID)SysDeinitialise(gpsSysData); gpsSysData = IMG_NULL; return eError; } SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_ENVDATA); gpsSysData->ui32NumDevices = SYS_DEVICE_COUNT; /* init device ID's */ for(i=0; i<SYS_DEVICE_COUNT; i++) { gpsSysData->sDeviceID[i].uiID = i; gpsSysData->sDeviceID[i].bInUse = IMG_FALSE; } gpsSysData->psDeviceNodeList = IMG_NULL; gpsSysData->psQueueList = IMG_NULL; eError = SysInitialiseCommon(gpsSysData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed in SysInitialiseCommon")); (IMG_VOID)SysDeinitialise(gpsSysData); gpsSysData = IMG_NULL; return eError; } #if !defined(SGX_DYNAMIC_TIMING_INFO) /* Set up timing information*/ psTimingInfo = &gsSGXDeviceMap.sTimingInfo; psTimingInfo->ui32CoreClockSpeed = SYS_SGX_CLOCK_SPEED; psTimingInfo->ui32HWRecoveryFreq = SYS_SGX_HWRECOVERY_TIMEOUT_FREQ; #if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT) psTimingInfo->bEnableActivePM = IMG_TRUE; #else psTimingInfo->bEnableActivePM = IMG_FALSE; #endif /* SUPPORT_ACTIVE_POWER_MANAGEMENT */ psTimingInfo->ui32ActivePowManLatencyms = SYS_SGX_ACTIVE_POWER_LATENCY_MS; psTimingInfo->ui32uKernelFreq = SYS_SGX_PDS_TIMER_FREQ; #endif /* Setup the Source Clock Divider value */ gpsSysSpecificData->ui32SrcClockDiv = 3; /* Locate the devices within the system, specifying the physical addresses of each devices components (regs, mem, ports etc.) */ eError = SysLocateDevices(gpsSysData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to locate devices")); (IMG_VOID)SysDeinitialise(gpsSysData); gpsSysData = IMG_NULL; return eError; } SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_LOCATEDEV); eError = SysPMRuntimeRegister(); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to register with OSPM!")); (IMG_VOID)SysDeinitialise(gpsSysData); gpsSysData = IMG_NULL; return eError; } SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_PM_RUNTIME); eError = SysDvfsInitialize(gpsSysSpecificData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to initialize DVFS")); (IMG_VOID)SysDeinitialise(gpsSysData); gpsSysData = IMG_NULL; return eError; } SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_DVFS_INIT); /* Register devices with the system This also sets up their memory maps/heaps */ eError = PVRSRVRegisterDevice(gpsSysData, SGXRegisterDevice, DEVICE_SGX_INTERRUPT, &gui32SGXDeviceID); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to register device!")); (IMG_VOID)SysDeinitialise(gpsSysData); gpsSysData = IMG_NULL; return eError; } SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_REGDEV); /* Once all devices are registered, specify the backing store and, if required, customise the memory heap config */ psDeviceNode = gpsSysData->psDeviceNodeList; while(psDeviceNode) { /* perform any OEM SOC address space customisations here */ switch(psDeviceNode->sDevId.eDeviceType) { case PVRSRV_DEVICE_TYPE_SGX: { DEVICE_MEMORY_INFO *psDevMemoryInfo; DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap; /* specify the backing store to use for the devices MMU PT/PDs - the PT/PDs are always UMA in this system */ psDeviceNode->psLocalDevMemArena = IMG_NULL; /* useful pointers */ psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo; psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap; /* specify the backing store for all SGX heaps */ for(i=0; i<psDevMemoryInfo->ui32HeapCount; i++) { psDeviceMemoryHeap[i].ui32Attribs |= PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG; } gpsSGXDevNode = psDeviceNode; gsSysSpecificData.psSGXDevNode = psDeviceNode; break; } default: PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to find SGX device node!")); return PVRSRV_ERROR_INIT_FAILURE; } /* advance to next device */ psDeviceNode = psDeviceNode->psNext; } eError = EnableSystemClocksWrap(gpsSysData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to Enable system clocks (%d)", eError)); (IMG_VOID)SysDeinitialise(gpsSysData); gpsSysData = IMG_NULL; return eError; } SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS); #if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT) eError = EnableSGXClocksWrap(gpsSysData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to Enable SGX clocks (%d)", eError)); (IMG_VOID)SysDeinitialise(gpsSysData); gpsSysData = IMG_NULL; return eError; } #endif /* SUPPORT_ACTIVE_POWER_MANAGEMENT */ eError = PVRSRVInitialiseDevice(gui32SGXDeviceID); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to initialise device!")); (IMG_VOID)SysDeinitialise(gpsSysData); gpsSysData = IMG_NULL; return eError; } SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_INITDEV); #if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT) /* SGX defaults to D3 power state */ DisableSGXClocks(gpsSysData); #endif /* SUPPORT_ACTIVE_POWER_MANAGEMENT */ #if !defined(PVR_NO_OMAP_TIMER) #if defined(PVR_OMAP_TIMER_BASE_IN_SYS_SPEC_DATA) TimerRegPhysBase = gsSysSpecificData.sTimerRegPhysBase; #else TimerRegPhysBase.uiAddr = SYS_OMAP3430_GP11TIMER_REGS_SYS_PHYS_BASE; #endif gpsSysData->pvSOCTimerRegisterKM = IMG_NULL; gpsSysData->hSOCTimerRegisterOSMemHandle = 0; if (TimerRegPhysBase.uiAddr != 0) { OSReservePhys(TimerRegPhysBase, 4, PVRSRV_HAP_MULTI_PROCESS|PVRSRV_HAP_UNCACHED, IMG_NULL, (IMG_VOID **)&gpsSysData->pvSOCTimerRegisterKM, &gpsSysData->hSOCTimerRegisterOSMemHandle); } #endif /* !defined(PVR_NO_OMAP_TIMER) */ return PVRSRV_OK; }
/************************************************************************** * Function Name : PDumpMMUDumpPxEntries * Inputs : * Outputs : * Returns : PVRSRV_ERROR * Description : **************************************************************************/ PVRSRV_ERROR PDumpMMUDumpPxEntries(MMU_LEVEL eMMULevel, const IMG_CHAR *pszPDumpDevName, IMG_VOID *pvPxMem, IMG_DEV_PHYADDR sPxDevPAddr, IMG_UINT32 uiFirstEntry, IMG_UINT32 uiNumEntries, const IMG_CHAR *pszMemspaceName, const IMG_CHAR *pszSymbolicAddr, IMG_UINT64 uiSymbolicAddrOffset, IMG_UINT32 uiBytesPerEntry, IMG_UINT32 uiLog2Align, IMG_UINT32 uiAddrShift, IMG_UINT64 uiAddrMask, IMG_UINT64 uiPxEProtMask, IMG_UINT32 ui32Flags) { PVRSRV_ERROR eErr = PVRSRV_OK; IMG_UINT64 ui64PxSymAddr; IMG_UINT64 ui64PxEValueSymAddr; IMG_UINT32 ui32SymAddrOffset = 0; IMG_UINT32 *pui32PxMem; IMG_UINT64 *pui64PxMem; IMG_BOOL bPxEValid; IMG_UINT32 uiPxEIdx; IMG_INT32 iShiftAmount; IMG_CHAR *pszWrwSuffix = 0; IMG_VOID *pvRawBytes = 0; IMG_CHAR aszPxSymbolicAddr[MAX_SYMBOLIC_ADDRESS_LENGTH]; IMG_UINT64 ui64PxE64; IMG_UINT64 ui64Protflags64; PDUMP_GET_SCRIPT_STRING(); ui32Flags |= ( PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0; if (!PDumpOSJTInitialised()) { eErr = PVRSRV_ERROR_PDUMP_NOT_AVAILABLE; goto ErrOut; } if (PDumpOSIsSuspended()) { eErr = PVRSRV_OK; goto ErrOut; } if (pvPxMem == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "PDUMPMMUDUMPPxENTRIES: PxMem is Null")); eErr = PVRSRV_ERROR_INVALID_PARAMS; goto ErrOut; } /* create the symbolic address of the Px */ ui64PxSymAddr = sPxDevPAddr.uiAddr; OSSNPrintf(aszPxSymbolicAddr, MAX_SYMBOLIC_ADDRESS_LENGTH, ":%s:" MMUPT_FMT, pszPDumpDevName, ui64PxSymAddr); PDUMP_LOCK(); /* traverse PxEs, dumping entries */ for(uiPxEIdx = uiFirstEntry; uiPxEIdx < uiFirstEntry + uiNumEntries; uiPxEIdx++) { /* Calc the symbolic address offset of the PxE location */ ui32SymAddrOffset = (uiPxEIdx*uiBytesPerEntry); /* Calc the symbolic address of the PxE value and HW protflags */ /* just read it here */ switch(uiBytesPerEntry) { case 4: { pui32PxMem = pvPxMem; ui64PxE64 = pui32PxMem[uiPxEIdx]; pszWrwSuffix = ""; pvRawBytes = &pui32PxMem[uiPxEIdx]; break; } case 8: { pui64PxMem = pvPxMem; ui64PxE64 = pui64PxMem[uiPxEIdx]; pszWrwSuffix = "64"; pvRawBytes = &pui64PxMem[uiPxEIdx]; break; } default: { PVR_DPF((PVR_DBG_ERROR, "PDumpMMUPxEntries: error")); ui64PxE64 = 0; //!!error break; } } ui64PxEValueSymAddr = (ui64PxE64 & uiAddrMask) >> uiAddrShift << uiLog2Align; ui64Protflags64 = ui64PxE64 & uiPxEProtMask; bPxEValid = (ui64Protflags64 & 1) ? IMG_TRUE : IMG_FALSE; if(bPxEValid) { _ContiguousPDumpBytes(aszPxSymbolicAddr, ui32SymAddrOffset, IMG_TRUE, 0, 0, ui32Flags | PDUMP_FLAGS_CONTINUOUS); iShiftAmount = (IMG_INT32)(uiLog2Align - uiAddrShift); /* First put the symbolic representation of the actual address of the entry into a pdump internal register */ /* MOV seemed cleaner here, since (a) it's 64-bit; (b) the target is not memory. However, MOV cannot do the "reference" of the symbolic address. Apparently WRW is correct. */ if (pszSymbolicAddr == IMG_NULL) { pszSymbolicAddr = "none"; } if (eMMULevel == MMU_LEVEL_1) { if (iShiftAmount == 0) { eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "WRW%s :%s:" MMUPT_FMT ":0x%08X :%s:%s:0x%llx | 0x%llX\n", pszWrwSuffix, /* dest */ pszPDumpDevName, ui64PxSymAddr, ui32SymAddrOffset, /* src */ pszMemspaceName, pszSymbolicAddr, uiSymbolicAddrOffset, /* ORing prot flags */ ui64Protflags64); } else { eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "WRW :%s:$1 :%s:%s:0x%llx\n", /* dest */ pszPDumpDevName, /* src */ pszMemspaceName, pszSymbolicAddr, uiSymbolicAddrOffset); } } else { eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "WRW :%s:$1 :%s:" MMUPT_FMT ":0x0", /* dest */ pszPDumpDevName, /* src */ pszPDumpDevName, ui64PxEValueSymAddr); } if (eErr != PVRSRV_OK) { goto ErrUnlock; } PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS); /* Now shift it to the right place, if necessary: */ /* Now shift that value down, by the "Align shift" amount, to get it into units (ought to assert that we get an integer - i.e. we don't shift any bits off the bottom, don't know how to do PDUMP assertions yet) and then back up by the right amount to get it into the position of the field. This is optimised into a single shift right by the difference between the two. */ if (iShiftAmount > 0) { /* Page X Address is specified in units larger than the position in the PxE would suggest. */ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "SHR :%s:$1 :%s:$1 0x%X", /* dest */ pszPDumpDevName, /* src A */ pszPDumpDevName, /* src B */ iShiftAmount); if (eErr != PVRSRV_OK) { goto ErrUnlock; } PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS); } else if (iShiftAmount < 0) { /* Page X Address is specified in units smaller than the position in the PxE would suggest. */ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "SHL :%s:$1 :%s:$1 0x%X", /* dest */ pszPDumpDevName, /* src A */ pszPDumpDevName, /* src B */ -iShiftAmount); if (eErr != PVRSRV_OK) { goto ErrUnlock; } PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS); } if (eMMULevel == MMU_LEVEL_1) { if( iShiftAmount != 0) { eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "WRW%s :%s:" MMUPT_FMT ":0x%08X :%s:$1 | 0x%llX", pszWrwSuffix, /* dest */ pszPDumpDevName, ui64PxSymAddr, ui32SymAddrOffset, /* src */ pszPDumpDevName, /* ORing prot flags */ ui64Protflags64); if(eErr != PVRSRV_OK) { goto ErrUnlock; } PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS); } } else { /* Now we can "or" in the protection flags */ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "OR :%s:$1 :%s:$1 0x%llX", /* dest */ pszPDumpDevName, /* src A */ pszPDumpDevName, /* src B */ ui64Protflags64); if (eErr != PVRSRV_OK) { goto ErrUnlock; } PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS); /* Finally, we write the register into the actual PxE */ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "WRW%s :%s:" MMUPT_FMT ":0x%08X :%s:$1", pszWrwSuffix, /* dest */ pszPDumpDevName, ui64PxSymAddr, ui32SymAddrOffset, /* src */ pszPDumpDevName); if(eErr != PVRSRV_OK) { goto ErrUnlock; } PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS); } } else { /* If the entry was "invalid", simply write the actual value found to the memory location */ eErr = _ContiguousPDumpBytes(aszPxSymbolicAddr, ui32SymAddrOffset, IMG_FALSE, uiBytesPerEntry, pvRawBytes, ui32Flags | PDUMP_FLAGS_CONTINUOUS); if (eErr != PVRSRV_OK) { goto ErrUnlock; } } } /* flush out any partly accumulated stuff for LDB */ _ContiguousPDumpBytes(aszPxSymbolicAddr, ui32SymAddrOffset, IMG_TRUE, 0, 0, ui32Flags | PDUMP_FLAGS_CONTINUOUS); ErrUnlock: PDUMP_UNLOCK(); ErrOut: return eErr; }