PVRSRV_ERROR RGXKickSyncKM(PVRSRV_DEVICE_NODE        *psDeviceNode,
                           RGX_SERVER_COMMON_CONTEXT *psServerCommonContext,
						   RGXFWIF_DM                eDM,
						   IMG_CHAR                  *pszCommandName,
                           IMG_UINT32                ui32ClientFenceCount,
                           PRGXFWIF_UFO_ADDR         *pauiClientFenceUFOAddress,
                           IMG_UINT32                *paui32ClientFenceValue,
                           IMG_UINT32                ui32ClientUpdateCount,
                           PRGXFWIF_UFO_ADDR         *pauiClientUpdateUFOAddress,
                           IMG_UINT32                *paui32ClientUpdateValue,
                           IMG_UINT32                ui32ServerSyncPrims,
                           IMG_UINT32                *paui32ServerSyncFlags,
                           SERVER_SYNC_PRIMITIVE     **pasServerSyncs,
                           IMG_BOOL                  bPDumpContinuous)
{
	RGXFWIF_KCCB_CMD		sCmpKCCBCmd;
	RGX_CCB_CMD_HELPER_DATA	asCmdHelperData[1];
	IMG_BOOL				bKickRequired;
	PVRSRV_ERROR			eError;
	PVRSRV_ERROR			eError2;
	IMG_UINT32				i;

	/* Sanity check the server fences */
	for (i=0;i<ui32ServerSyncPrims;i++)
	{
		if (!(paui32ServerSyncFlags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK))
		{
			PVR_DPF((PVR_DBG_ERROR, "%s: Server fence (on %s) must fence", __FUNCTION__, pszCommandName));
			return PVRSRV_ERROR_INVALID_SYNC_PRIM_OP;
		}
	}

	eError = RGXCmdHelperInitCmdCCB(FWCommonContextGetClientCCB(psServerCommonContext),
									  ui32ClientFenceCount,
									  pauiClientFenceUFOAddress,
									  paui32ClientFenceValue,
									  ui32ClientUpdateCount,
									  pauiClientUpdateUFOAddress,
									  paui32ClientUpdateValue,
									  ui32ServerSyncPrims,
									  paui32ServerSyncFlags,
									  pasServerSyncs,
									  0,         /* ui32CmdSize */
									  IMG_NULL,  /* pui8DMCmd */
									  IMG_NULL,  /* ppPreAddr */
									  IMG_NULL,  /* ppPostAddr */
									  IMG_NULL,  /* ppRMWUFOAddr */
									  RGXFWIF_CCB_CMD_TYPE_NULL,
									  bPDumpContinuous,
									  pszCommandName,
									  asCmdHelperData);
	if (eError != PVRSRV_OK)
	{
		goto fail_cmdinit;
	}

	eError = RGXCmdHelperAcquireCmdCCB(IMG_ARR_NUM_ELEMS(asCmdHelperData),
	                                   asCmdHelperData, &bKickRequired);
	if ((eError != PVRSRV_OK) && (!bKickRequired))
	{
		/*
			Only bail if no new data was submitted into the client CCB, we might
			have already submitted a padding packet which we should flush through
			the FW.
		*/
		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create client CCB command", __FUNCTION__));
		goto fail_cmdaquire;
	}


	/*
		We should reserved space in the kernel CCB here and fill in the command
		directly.
		This is so if there isn't space in the kernel CCB we can return with
		retry back to services client before we take any operations
	*/

	/*
		We might only be kicking for flush out a padding packet so only submit
		the command if the create was successful
	*/
	if (eError == PVRSRV_OK)
	{
		/*
			All the required resources are ready at this point, we can't fail so
			take the required server sync operations and commit all the resources
		*/
		RGXCmdHelperReleaseCmdCCB(1, asCmdHelperData, pszCommandName, FWCommonContextGetFWAddress(psServerCommonContext).ui32Addr);
	}

	/* Construct the kernel compute CCB command. */
	sCmpKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_KICK;
	sCmpKCCBCmd.uCmdData.sCmdKickData.psContext = FWCommonContextGetFWAddress(psServerCommonContext);
	sCmpKCCBCmd.uCmdData.sCmdKickData.ui32CWoffUpdate = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psServerCommonContext));
	sCmpKCCBCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl = 0;

	/*
	 * Submit the compute command to the firmware.
	 */
	LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
	{
		eError2 = RGXScheduleCommand(psDeviceNode->pvDevice,
									eDM,
									&sCmpKCCBCmd,
									sizeof(sCmpKCCBCmd),
									bPDumpContinuous);
		if (eError2 != PVRSRV_ERROR_RETRY)
		{
			break;
		}
		OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
	} END_LOOP_UNTIL_TIMEOUT();
	
	if (eError2 != PVRSRV_OK)
	{
		PVR_DPF((PVR_DBG_ERROR, "%s failed to schedule kernel CCB command. (0x%x)", __FUNCTION__, eError));
	}
	/*
	 * Now check eError (which may have returned an error from our earlier call
	 * to RGXCmdHelperAcquireCmdCCB) - we needed to process any flush command first
	 * so we check it now...
	 */
	if (eError != PVRSRV_OK )
	{
		goto fail_cmdaquire;
	}

	return PVRSRV_OK;

fail_cmdaquire:
fail_cmdinit:

	return eError;
}
IMG_EXPORT
PVRSRV_ERROR PVRSRVRGXKickCDMKM(RGX_SERVER_COMPUTE_CONTEXT	*psComputeContext,
								IMG_UINT32					ui32ClientFenceCount,
								SYNC_PRIMITIVE_BLOCK			**pauiClientFenceUFOSyncPrimBlock,
								IMG_UINT32					*paui32ClientFenceSyncOffset,
								IMG_UINT32					*paui32ClientFenceValue,
								IMG_UINT32					ui32ClientUpdateCount,
								SYNC_PRIMITIVE_BLOCK			**pauiClientUpdateUFOSyncPrimBlock,
								IMG_UINT32					*paui32ClientUpdateSyncOffset,
								IMG_UINT32					*paui32ClientUpdateValue,
								IMG_UINT32					ui32ServerSyncPrims,
								IMG_UINT32					*paui32ServerSyncFlags,
								SERVER_SYNC_PRIMITIVE 		**pasServerSyncs,
								IMG_UINT32					ui32CmdSize,
								IMG_PBYTE					pui8DMCmd,
								IMG_BOOL					bPDumpContinuous,
							    IMG_UINT32					ui32ExtJobRef,
								IMG_UINT32					ui32IntJobRef)
{
	RGXFWIF_KCCB_CMD		sCmpKCCBCmd;
	RGX_CCB_CMD_HELPER_DATA	asCmdHelperData[1];
	IMG_BOOL				bKickRequired;
	PVRSRV_ERROR			eError;
	PVRSRV_ERROR			eError2;
	IMG_UINT32				i;

	RGXFWIF_DEV_VIRTADDR	pPreTimestamp;
	RGXFWIF_DEV_VIRTADDR	pPostTimestamp;
	PRGXFWIF_UFO_ADDR		pRMWUFOAddr;

	eError = SyncAddrListPopulate(&psComputeContext->sSyncAddrListFence,
									ui32ClientFenceCount,
									pauiClientFenceUFOSyncPrimBlock,
									paui32ClientFenceSyncOffset);
	if(eError != PVRSRV_OK)
	{
		goto err_populate_sync_addr_list;
	}

	eError = SyncAddrListPopulate(&psComputeContext->sSyncAddrListUpdate,
									ui32ClientUpdateCount,
									pauiClientUpdateUFOSyncPrimBlock,
									paui32ClientUpdateSyncOffset);
	if(eError != PVRSRV_OK)
	{
		goto err_populate_sync_addr_list;
	}


	/* Sanity check the server fences */
	for (i=0;i<ui32ServerSyncPrims;i++)
	{
		if (!(paui32ServerSyncFlags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK))
		{
			PVR_DPF((PVR_DBG_ERROR, "%s: Server fence (on CDM) must fence", __FUNCTION__));
			return PVRSRV_ERROR_INVALID_SYNC_PRIM_OP;
		}
	}

	RGX_GetTimestampCmdHelper((PVRSRV_RGXDEV_INFO*) psComputeContext->psDeviceNode->pvDevice,
	                          & pPreTimestamp,
	                          & pPostTimestamp,
	                          & pRMWUFOAddr);

	eError = RGXCmdHelperInitCmdCCB(FWCommonContextGetClientCCB(psComputeContext->psServerCommonContext),
	                                ui32ClientFenceCount,
	                                psComputeContext->sSyncAddrListFence.pasFWAddrs,
	                                paui32ClientFenceValue,
	                                ui32ClientUpdateCount,
	                                psComputeContext->sSyncAddrListUpdate.pasFWAddrs,
	                                paui32ClientUpdateValue,
	                                ui32ServerSyncPrims,
	                                paui32ServerSyncFlags,
	                                pasServerSyncs,
	                                ui32CmdSize,
	                                pui8DMCmd,
	                                & pPreTimestamp,
	                                & pPostTimestamp,
	                                & pRMWUFOAddr,
	                                RGXFWIF_CCB_CMD_TYPE_CDM,
	                                bPDumpContinuous,
	                                "Compute",
	                                asCmdHelperData);
	if (eError != PVRSRV_OK)
	{
		goto fail_cmdinit;
	}

	eError = RGXCmdHelperAcquireCmdCCB(IMG_ARR_NUM_ELEMS(asCmdHelperData), 
	                                   asCmdHelperData, &bKickRequired);
	if ((eError != PVRSRV_OK) && (!bKickRequired))
	{
		/*
			Only bail if no new data was submitted into the client CCB, we might
			have already submitted a padding packet which we should flush through
			the FW.
		*/
		PVR_DPF((PVR_DBG_ERROR, "RGXKickCDM: Failed to create client CCB command"));
		goto fail_cmdaquire;
	}


	/*
		We should reserved space in the kernel CCB here and fill in the command
		directly.
		This is so if there isn't space in the kernel CCB we can return with
		retry back to services client before we take any operations
	*/

	/*
		We might only be kicking for flush out a padding packet so only submit
		the command if the create was successful
	*/
	if (eError == PVRSRV_OK)
	{
		/*
			All the required resources are ready at this point, we can't fail so
			take the required server sync operations and commit all the resources
		*/
		RGXCmdHelperReleaseCmdCCB(1, asCmdHelperData, "CDM", FWCommonContextGetFWAddress(psComputeContext->psServerCommonContext).ui32Addr);
	}

	/* Construct the kernel compute CCB command. */
	sCmpKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_KICK;
	sCmpKCCBCmd.uCmdData.sCmdKickData.psContext = FWCommonContextGetFWAddress(psComputeContext->psServerCommonContext);
	sCmpKCCBCmd.uCmdData.sCmdKickData.ui32CWoffUpdate = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psComputeContext->psServerCommonContext));
	sCmpKCCBCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl = 0;

	/*
	 * Submit the compute command to the firmware.
	 */
	LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
	{
		eError2 = RGXScheduleCommand(psComputeContext->psDeviceNode->pvDevice,
									RGXFWIF_DM_CDM,
									&sCmpKCCBCmd,
									sizeof(sCmpKCCBCmd),
									bPDumpContinuous);
		if (eError2 != PVRSRV_ERROR_RETRY)
		{
			break;
		}
		OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
	} END_LOOP_UNTIL_TIMEOUT();
	
	if (eError2 != PVRSRV_OK)
	{
		PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXKickCDMKM failed to schedule kernel CCB command. (0x%x)", eError));
	}
#if defined(SUPPORT_GPUTRACE_EVENTS)
	else
	{
		RGXHWPerfFTraceGPUEnqueueEvent(psComputeContext->psDeviceNode->pvDevice,
				ui32ExtJobRef, ui32IntJobRef, "CDM");
	}
#endif
	/*
	 * Now check eError (which may have returned an error from our earlier call
	 * to RGXCmdHelperAcquireCmdCCB) - we needed to process any flush command first
	 * so we check it now...
	 */
	if (eError != PVRSRV_OK )
	{
		goto fail_cmdaquire;
	}

	return PVRSRV_OK;

fail_cmdaquire:
fail_cmdinit:
err_populate_sync_addr_list:
	return eError;
}
示例#3
0
/*
	SysCreateConfigData
*/
PVRSRV_ERROR SysCreateConfigData(PVRSRV_SYSTEM_CONFIG **ppsSysConfig)
{
    /* Sunxi Init */
    RgxSunxiInit();

    /*
     * Setup information about physical memory heap(s) we have
     */
    gsPhysHeapFuncs.pfnCpuPAddrToDevPAddr = UMAPhysHeapCpuPAddrToDevPAddr;
    gsPhysHeapFuncs.pfnDevPAddrToCpuPAddr = UMAPhysHeapDevPAddrToCpuPAddr;

    gsPhysHeapConfig[0].ui32PhysHeapID = 0;
    gsPhysHeapConfig[0].pszPDumpMemspaceName = "SYSMEM";
    gsPhysHeapConfig[0].eType = PHYS_HEAP_TYPE_UMA;
    gsPhysHeapConfig[0].psMemFuncs = &gsPhysHeapFuncs;
    gsPhysHeapConfig[0].hPrivData = IMG_NULL;

#if defined(TDMETACODE)
    gsPhysHeapConfig[1].ui32PhysHeapID = 1;
    gsPhysHeapConfig[1].pszPDumpMemspaceName = "TDMETACODEMEM";
    gsPhysHeapConfig[1].eType = PHYS_HEAP_TYPE_UMA;
    gsPhysHeapConfig[1].psMemFuncs = &gsPhysHeapFuncs;
    gsPhysHeapConfig[1].hPrivData = IMG_NULL;

    gsPhysHeapConfig[2].ui32PhysHeapID = 2;
    gsPhysHeapConfig[2].pszPDumpMemspaceName = "TDSECUREBUFMEM";
    gsPhysHeapConfig[2].eType = PHYS_HEAP_TYPE_UMA;
    gsPhysHeapConfig[2].psMemFuncs = &gsPhysHeapFuncs;
    gsPhysHeapConfig[2].hPrivData = IMG_NULL;
#endif

    gsSysConfig.pasPhysHeaps = &(gsPhysHeapConfig[0]);
    gsSysConfig.ui32PhysHeapCount = IMG_ARR_NUM_ELEMS(gsPhysHeapConfig);

    gsSysConfig.pui32BIFTilingHeapConfigs = gauiBIFTilingHeapXStrides;
    gsSysConfig.ui32BIFTilingHeapCount = IMG_ARR_NUM_ELEMS(gauiBIFTilingHeapXStrides);

    /*
     * Setup RGX specific timing data
     */
    gsRGXTimingInfo.ui32CoreClockSpeed        = RGX_SUNXI_CORE_CLOCK_SPEED;
    gsRGXTimingInfo.bEnableActivePM           = IMG_TRUE;
    gsRGXTimingInfo.bEnableRDPowIsland        = IMG_TRUE;
    gsRGXTimingInfo.ui32ActivePMLatencyms     = SYS_RGX_ACTIVE_POWER_LATENCY_MS;

    /*
     *Setup RGX specific data
     */
    gsRGXData.psRGXTimingInfo = &gsRGXTimingInfo;
#if defined(TDMETACODE)
    gsRGXData.bHasTDMetaCodePhysHeap = IMG_TRUE;
    gsRGXData.uiTDMetaCodePhysHeapID = 1;

    gsRGXData.bHasTDSecureBufPhysHeap = IMG_TRUE;
    gsRGXData.uiTDSecureBufPhysHeapID = 2;
#endif

    /*
     * Setup RGX device
     */
    gsDevices[0].eDeviceType            = PVRSRV_DEVICE_TYPE_RGX;
    gsDevices[0].pszName                = "RGX";

    /* Device setup information */
    gsDevices[0].sRegsCpuPBase.uiAddr   = SUNXI_GPU_PBASE;
    gsDevices[0].ui32RegsSize           = SUNXI_GPU_SIZE;
    gsDevices[0].ui32IRQ                = SUNXI_IRQ_GPU;
    gsDevices[0].bIRQIsShared           = IMG_FALSE;

    /* Device's physical heap IDs */
    gsDevices[0].aui32PhysHeapID[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL] = 0;
    gsDevices[0].aui32PhysHeapID[PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL] = 0;

    /* Power management on SUNXI system */
    gsDevices[0].pfnPrePowerState       = AwPrePowerState;
    gsDevices[0].pfnPostPowerState      = AwPostPowerState;

    /* No clock frequency either */
    gsDevices[0].pfnClockFreqGet        = NULL;

    /* No interrupt handled either */
    gsDevices[0].pfnInterruptHandled    = IMG_NULL;

    gsDevices[0].pfnCheckMemAllocSize   = SysCheckMemAllocSize;

    gsDevices[0].hDevData               = &gsRGXData;

    /*
     * Setup system config
     */
    gsSysConfig.pszSystemName = RGX_SUNXI_SYSTEM_NAME;
    gsSysConfig.uiDeviceCount = sizeof(gsDevices)/sizeof(gsDevices[0]);
    gsSysConfig.pasDevices = &gsDevices[0];

    /* Power management on no SUNXI system */
    gsSysConfig.pfnSysPrePowerState = AwSysPrePowerState;
    gsSysConfig.pfnSysPostPowerState = AwSysPostPowerState;

    /* no cache snooping */
    gsSysConfig.eCacheSnoopingMode = PVRSRV_SYSTEM_SNOOP_NONE;

    /* Setup other system specific stuff */
#if defined(SUPPORT_ION)
    IonInit(NULL);
#endif

    *ppsSysConfig = &gsSysConfig;

    return PVRSRV_OK;
}