Example #1
0
static PVRSRV_ERROR _Destroy3DTransferContext(RGX_SERVER_TQ_3D_DATA *ps3DData,
											  PVRSRV_DEVICE_NODE *psDeviceNode,
											  PVRSRV_CLIENT_SYNC_PRIM *psCleanupSync)
{
	PVRSRV_ERROR eError;

	/* Check if the FW has finished with this resource ... */
	eError = RGXFWRequestCommonContextCleanUp(psDeviceNode,
											  FWCommonContextGetFWAddress(ps3DData->psServerCommonContext),
											  psCleanupSync,
											  RGXFWIF_DM_3D);
	if (eError == PVRSRV_ERROR_RETRY)
	{
		return eError;
	}
	else if (eError != PVRSRV_OK)
	{
		PVR_LOG(("%s: Unexpected error from RGXFWRequestCommonContextCleanUp (%s)",
				 __FUNCTION__,
				 PVRSRVGetErrorStringKM(eError)));
	}

	/* ... it has so we can free it's resources */
	DevmemFwFree(ps3DData->psFWContextStateMemDesc);
	FWCommonContextFree(ps3DData->psServerCommonContext);

	return PVRSRV_OK;
}
Example #2
0
/*!
******************************************************************************

 @Function	PVRSRVLookupHandleAnyType

 @Description	Lookup the data pointer and type corresponding to a handle

 @Input		ppvData - location to return data pointer
		peType - location to return handle type
		hHandle - handle from client

 @Output	ppvData - points to the data pointer
		peType - points to handle type

 @Return	Error code or PVRSRV_OK

******************************************************************************/
PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase,
				       IMG_PVOID *ppvData,
				       PVRSRV_HANDLE_TYPE *peType,
				       IMG_HANDLE hHandle)
{
	HANDLE_DATA *psHandleData = IMG_NULL;
	PVRSRV_ERROR eError;

	PVR_ASSERT(gpsHandleFuncs);

	if (psBase == IMG_NULL)
	{
		PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupHandleAnyType: Missing handle base"));
		eError = PVRSRV_ERROR_INVALID_PARAMS;
		goto err;
	}

	eError = GetHandleData(psBase, &psHandleData, hHandle, PVRSRV_HANDLE_TYPE_NONE);
	if (eError != PVRSRV_OK)
	{
		PVR_DPF((PVR_DBG_ERROR,
			 "PVRSRVLookupHandleAnyType: Error looking up handle (%s)",
			 PVRSRVGetErrorStringKM(eError)));
		OSDumpStack();
		goto err;
	}

	*ppvData = psHandleData->pvData;
	*peType = psHandleData->eType;

	eError = PVRSRV_OK;

	err:
	return eError;
}
Example #3
0
/*!
******************************************************************************

 @Function	PVRSRVHandleDeInit

 @Description	De-initialise handle management

 @Return	Error code or PVRSRV_OK

******************************************************************************/
PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID)
{
	PVRSRV_ERROR eError = PVRSRV_OK;

	if (gpsHandleFuncs != IMG_NULL)
	{
		if (gpsKernelHandleBase != IMG_NULL)
		{
			eError = PVRSRVFreeHandleBase(gpsKernelHandleBase);
			if (eError == PVRSRV_OK)
			{
				gpsKernelHandleBase = IMG_NULL;
			}
			else
			{
				PVR_DPF((PVR_DBG_ERROR,
					 "PVRSRVHandleDeInit: FreeHandleBase failed (%s)",
					 PVRSRVGetErrorStringKM(eError)));
			}
		}

		if (eError == PVRSRV_OK)
		{
			gpsHandleFuncs = IMG_NULL;
		}
	}
	else
	{
		/* If we don't have a handle function table we shouldn't have a handle base either */
		PVR_ASSERT(gpsKernelHandleBase == IMG_NULL);
	}

	return eError;
}
/*!
******************************************************************************

 @Function	DestroyHandleBase

 @Description	Destroy a handle base structure

 @Input 	psBase - pointer to handle base structure

 @Return	Error code or PVRSRV_OK

******************************************************************************/
static PVRSRV_ERROR DestroyHandleBase(HANDLE_IMPL_BASE *psBase)
{
	PVRSRV_ERROR eError;

	PVR_ASSERT(psBase);

	if (psBase->ui32TotalHandCount != psBase->ui32TotalFreeHandCount)
	{
		PVR_DPF((PVR_DBG_WARNING, "%s: Handles still exist (%u found)", 
			 __FUNCTION__, 
			 psBase->ui32TotalHandCount - psBase->ui32TotalFreeHandCount));
	}

	eError = ReallocHandleBlockArray(psBase, 0);
	if (eError != PVRSRV_OK)
	{
		PVR_DPF((PVR_DBG_ERROR, "%s: Couldn't free handle array (%s)", 
			 __FUNCTION__, 
			 PVRSRVGetErrorStringKM(eError)));

		return eError;
	}

	OSFreeMem(psBase);

	return PVRSRV_OK;
}
Example #5
0
IMG_EXPORT
PVRSRV_ERROR PVRSRVRGXDestroyComputeContextKM(RGX_SERVER_COMPUTE_CONTEXT *psComputeContext)
{
	PVRSRV_ERROR				eError = PVRSRV_OK;

	/* Check if the FW has finished with this resource ... */
	eError = RGXFWRequestCommonContextCleanUp(psComputeContext->psDeviceNode,
											  FWCommonContextGetFWAddress(psComputeContext->psServerCommonContext),
											  psComputeContext->psSync,
											  RGXFWIF_DM_CDM);

	if (eError == PVRSRV_ERROR_RETRY)
	{
		return eError;
	}
	else if (eError != PVRSRV_OK)
	{
		PVR_LOG(("%s: Unexpected error from RGXFWRequestCommonContextCleanUp (%s)",
				__FUNCTION__,
				PVRSRVGetErrorStringKM(eError)));
	}

	/* ... it has so we can free its resources */

	dllist_remove_node(&(psComputeContext->sListNode));

	FWCommonContextFree(psComputeContext->psServerCommonContext);
	DevmemFwFree(psComputeContext->psFWFrameworkMemDesc);
	DevmemFwFree(psComputeContext->psFWComputeContextStateMemDesc);
	SyncPrimFree(psComputeContext->psSync);
	OSFreeMem(psComputeContext);

	return PVRSRV_OK;
}
Example #6
0
/*!
******************************************************************************

 @Function	PVRSRVHandleInit

 @Description	Initialise handle management

 @Return	Error code or PVRSRV_OK

******************************************************************************/
PVRSRV_ERROR PVRSRVHandleInit(IMG_VOID)
{
	PVRSRV_ERROR eError;

	PVR_ASSERT(gpsKernelHandleBase == IMG_NULL);
	PVR_ASSERT(gpsHandleFuncs == IMG_NULL);

	eError = PVRSRVHandleGetFuncTable(&gpsHandleFuncs);
	if (eError != PVRSRV_OK)
	{
		PVR_DPF((PVR_DBG_ERROR,
			 "PVRSRVHandleInit: PVRSRVHandleGetFuncTable failed (%s)",
			 PVRSRVGetErrorStringKM(eError)));
		goto error;
	}

	eError = PVRSRVAllocHandleBase(&gpsKernelHandleBase);
	if (eError != PVRSRV_OK)
	{
		PVR_DPF((PVR_DBG_ERROR,
			 "PVRSRVHandleInit: PVRSRVAllocHandleBase failed (%s)",
			 PVRSRVGetErrorStringKM(eError)));
		goto error;
	}

	eError = gpsHandleFuncs->pfnEnableHandlePurging(gpsKernelHandleBase->psImplBase);
	if (eError != PVRSRV_OK)
	{
		PVR_DPF((PVR_DBG_ERROR,
			 "PVRSRVHandleInit: PVRSRVEnableHandlePurging failed (%s)",
			 PVRSRVGetErrorStringKM(eError)));
		goto error;
	}

	return PVRSRV_OK;

error:
	(IMG_VOID) PVRSRVHandleDeInit();
	return eError;
}
Example #7
0
/*!
******************************************************************************

 @Function	PVRSRVLookupSubHandle

 @Description	Lookup the data pointer corresponding to a subhandle

 @Input		ppvData - location to return data pointer
		hHandle - handle from client
		eType - handle type
		hAncestor - ancestor handle

 @Output	ppvData - points to the data pointer

 @Return	Error code or PVRSRV_OK

******************************************************************************/
PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase,
				   IMG_PVOID *ppvData,
				   IMG_HANDLE hHandle,
				   PVRSRV_HANDLE_TYPE eType,
				   IMG_HANDLE hAncestor)
{
	HANDLE_DATA *psPHandleData = IMG_NULL;
	HANDLE_DATA *psCHandleData = IMG_NULL;
	PVRSRV_ERROR eError;

	/* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */
	PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
	PVR_ASSERT(gpsHandleFuncs);

	if (psBase == IMG_NULL)
	{
		PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupSubHandle: Missing handle base"));
		eError = PVRSRV_ERROR_INVALID_PARAMS;
		goto err;
	}

	eError = GetHandleData(psBase, &psCHandleData, hHandle, eType);
	if (eError != PVRSRV_OK)
	{
		PVR_DPF((PVR_DBG_ERROR,
			 "PVRSRVLookupSubHandle: Error looking up subhandle (%s)",
			 PVRSRVGetErrorStringKM(eError)));
		OSDumpStack();
		goto err;
	}

	/* Look for hAncestor among the handle's ancestors */
	for (psPHandleData = psCHandleData; ParentHandle(psPHandleData) != hAncestor; )
	{
		eError = GetHandleData(psBase, &psPHandleData, ParentHandle(psPHandleData), PVRSRV_HANDLE_TYPE_NONE);
		if (eError != PVRSRV_OK)
		{
			PVR_DPF((PVR_DBG_ERROR,"PVRSRVLookupSubHandle: Subhandle doesn't belong to given ancestor"));
			eError = PVRSRV_ERROR_INVALID_SUBHANDLE;
			goto err;
		}
	}

	*ppvData = psCHandleData->pvData;

	eError = PVRSRV_OK;

	err:
	return eError;
}
IMG_EXPORT
PVRSRV_ERROR PVRSRVRGXDestroyComputeContextKM(RGX_SERVER_COMPUTE_CONTEXT *psComputeContext)
{
	PVRSRV_ERROR				eError = PVRSRV_OK;
	PVRSRV_RGXDEV_INFO *psDevInfo = psComputeContext->psDeviceNode->pvDevice;

	/* Check if the FW has finished with this resource ... */
	eError = RGXFWRequestCommonContextCleanUp(psComputeContext->psDeviceNode,
											  psComputeContext->psServerCommonContext,
											  psComputeContext->psSync,
											  RGXFWIF_DM_CDM);

	if (eError == PVRSRV_ERROR_RETRY)
	{
		return eError;
	}
	else if (eError != PVRSRV_OK)
	{
		PVR_LOG(("%s: Unexpected error from RGXFWRequestCommonContextCleanUp (%s)",
				__FUNCTION__,
				PVRSRVGetErrorStringKM(eError)));
		return eError;
	}

	/* ... it has so we can free its resources */

	OSWRLockAcquireWrite(psDevInfo->hComputeCtxListLock);
	dllist_remove_node(&(psComputeContext->sListNode));
	OSWRLockReleaseWrite(psDevInfo->hComputeCtxListLock);

	FWCommonContextFree(psComputeContext->psServerCommonContext);
	DevmemFwFree(psComputeContext->psFWFrameworkMemDesc);
	DevmemFwFree(psComputeContext->psFWComputeContextStateMemDesc);
	SyncPrimFree(psComputeContext->psSync);

	SyncAddrListDeinit(&psComputeContext->sSyncAddrListFence);
	SyncAddrListDeinit(&psComputeContext->sSyncAddrListUpdate);

	OSFreeMem(psComputeContext);

	return PVRSRV_OK;
}
/*!
******************************************************************************

 @Function	EnsureFreeHandles

 @Description	Ensure there are enough free handles

 @Input		psBase - Pointer to handle base structure
		ui32Free - Number of free handles required

 @Return	Error code or PVRSRV_OK

******************************************************************************/
static PVRSRV_ERROR EnsureFreeHandles(HANDLE_IMPL_BASE *psBase, 
				      IMG_UINT32 ui32Free)
{
	PVRSRV_ERROR eError = PVRSRV_OK;

	if (ui32Free > psBase->ui32TotalFreeHandCount)
	{
		IMG_UINT32 ui32FreeHandDelta = ui32Free - psBase->ui32TotalFreeHandCount;

		eError = IncreaseHandleArraySize(psBase, ui32FreeHandDelta);
		if (eError != PVRSRV_OK)
		{
			PVR_DPF((PVR_DBG_ERROR, "%s: Couldn't allocate %u handles to ensure %u free "
				 "handles (IncreaseHandleArraySize failed with error %s)",
				 __FUNCTION__, ui32FreeHandDelta, ui32Free, PVRSRVGetErrorStringKM(eError)));
		}
	}

	return eError;
}
Example #10
0
/*!
******************************************************************************

 @Function	PVRSRVGetParentHandle

 @Description	Lookup the parent of a handle

 @Input		phParent - location for returning parent handle
		hHandle - handle for which the parent handle is required
		eType - handle type
		hParent - parent handle

 @Output	*phParent - parent handle, or IMG_NULL if there is no parent

 @Return	Error code or PVRSRV_OK.  Note that not having a parent is
		not regarded as an error.

******************************************************************************/
PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase,
				   IMG_HANDLE *phParent,
				   IMG_HANDLE hHandle,
				   PVRSRV_HANDLE_TYPE eType)
{
	HANDLE_DATA *psHandleData = IMG_NULL;
	PVRSRV_ERROR eError;

	/* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */
	PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
	PVR_ASSERT(gpsHandleFuncs);

	if (psBase == IMG_NULL)
	{
		PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetParentHandle: Missing handle base"));
		eError = PVRSRV_ERROR_INVALID_PARAMS;
		goto err;
	}

	eError = GetHandleData(psBase, &psHandleData, hHandle, eType);
	if (eError != PVRSRV_OK)
	{
		PVR_DPF((PVR_DBG_ERROR,
			 "PVRSRVGetParentHandle: Error looking up subhandle (%s)",
			 PVRSRVGetErrorStringKM(eError)));
		OSDumpStack();
		goto err;
	}

	*phParent = ParentHandle(psHandleData);

	eError = PVRSRV_OK;

	err:
	return eError;
}
Example #11
0
/*
 * 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;
}
Example #12
0
/*!
******************************************************************************

 @Function	PVRSRVAllocHandle

 @Description	Allocate a handle

 @Input		phHandle - location for new handle
		pvData - pointer to resource to be associated with the handle
		eType - the type of resource

 @Output	phHandle - points to new handle

 @Return	Error code or PVRSRV_OK

******************************************************************************/
PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase,
			       IMG_HANDLE *phHandle,
			       IMG_VOID *pvData,
			       PVRSRV_HANDLE_TYPE eType,
			       PVRSRV_HANDLE_ALLOC_FLAG eFlag)
{
	IMG_HANDLE hHandle;
	PVRSRV_ERROR eError;

	*phHandle = IMG_NULL;

	/* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */
	PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
	PVR_ASSERT(gpsHandleFuncs);

	if (psBase == IMG_NULL)
	{
		PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandle: Missing handle base"));
		eError = PVRSRV_ERROR_INVALID_PARAMS;
		goto exit_AllocHandle;
	}

	if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
	{
		/* See if there is already a handle for this data pointer */
		hHandle = FindHandle(psBase, pvData, eType, IMG_NULL);
		if (hHandle != IMG_NULL)
		{
			HANDLE_DATA *psHandleData = IMG_NULL;

			eError = GetHandleData(psBase, &psHandleData, hHandle, eType);
			if (eError != PVRSRV_OK)
			{
				PVR_DPF((PVR_DBG_ERROR,
					 "PVRSRVAllocHandle: Lookup of existing handle failed (%s)",
					 PVRSRVGetErrorStringKM(eError)));
				goto exit_AllocHandle;
			}

			/*
			 * If the client is willing to share a handle, and the
			 * existing handle is marked as shareable, return the
			 * existing handle.
			 */
			if (TEST_FLAG(psHandleData->eFlag & eFlag, PVRSRV_HANDLE_ALLOC_FLAG_SHARED))
			{
				psHandleData->ui32Refs++;
				*phHandle = hHandle;
				eError = PVRSRV_OK;
				goto exit_AllocHandle;
			}
			eError = PVRSRV_ERROR_HANDLE_NOT_SHAREABLE;
			goto exit_AllocHandle;
		}
	}

	eError = AllocHandle(psBase, phHandle, pvData, eType, eFlag, IMG_NULL);

	exit_AllocHandle:

	return eError;
}
Example #13
0
PVRSRV_ERROR RGXPreKickCacheCommand(PVRSRV_RGXDEV_INFO 	*psDevInfo)
{
	PVRSRV_DEVICE_NODE *psDeviceNode = psDevInfo->psDeviceNode;
	RGXFWIF_KCCB_CMD sFlushCmd;
	PVRSRV_ERROR eError = PVRSRV_OK;
	RGXFWIF_DM eDMcount = RGXFWIF_DM_MAX;

	if (!ui32CacheOpps)
	{
		goto _PVRSRVPowerLock_Exit;
	}

	sFlushCmd.eCmdType = RGXFWIF_KCCB_CMD_MMUCACHE;
	/* Set which memory context this command is for (all ctxs for now) */
	ui32CacheOpps |= RGXFWIF_MMUCACHEDATA_FLAGS_CTX_ALL;
#if 0
	sFlushCmd.uCmdData.sMMUCacheData.psMemoryContext = ???
#endif

	/* PVRSRVPowerLock guarantees atomicity between commands and global variables consistency.
	 * This is helpful in a scenario with several applications allocating resources. */
	eError = PVRSRVPowerLock();

	if (eError != PVRSRV_OK)
	{
		PVR_DPF((PVR_DBG_WARNING, "RGXPreKickCacheCommand: failed to acquire powerlock (%s)",
					PVRSRVGetErrorStringKM(eError)));
		goto _PVRSRVPowerLock_Exit;
	}

	PDUMPPOWCMDSTART();
	eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
										 PVRSRV_DEV_POWER_STATE_ON,
										 IMG_FALSE);
	PDUMPPOWCMDEND();

	if (eError != PVRSRV_OK)
	{
		PVR_DPF((PVR_DBG_WARNING, "RGXPreKickCacheCommand: failed to transition RGX to ON (%s)",
					PVRSRVGetErrorStringKM(eError)));

		goto _PVRSRVSetDevicePowerStateKM_Exit;
	}

	sFlushCmd.uCmdData.sMMUCacheData.ui32Flags = ui32CacheOpps;
	sFlushCmd.uCmdData.sMMUCacheData.ui32CacheSequenceNum = ++ui32CacheOpSequence;

#if defined(PDUMP)
	PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
							"Submit MMU flush and invalidate (flags = 0x%08x, cache operation sequence = %u)",
							ui32CacheOpps, ui32CacheOpSequence);
#endif

	ui32CacheOpps = 0;

	/* Schedule MMU cache command */
	do
	{
		eDMcount--;
		eError = RGXSendCommandRaw(psDevInfo, eDMcount, &sFlushCmd, sizeof(RGXFWIF_KCCB_CMD), PDUMP_FLAGS_CONTINUOUS);

		if (eError != PVRSRV_OK)
		{
			PVR_DPF((PVR_DBG_ERROR,"RGXPreKickCacheCommand: Failed to schedule MMU cache command \
									to DM=%d with error (%u)", eDMcount, eError));
			break;
		}
	}
	while(eDMcount > 0);

_PVRSRVSetDevicePowerStateKM_Exit:
	PVRSRVPowerUnlock();

_PVRSRVPowerLock_Exit:
	return eError;
}
/*!
******************************************************************************

 @Function	AcquireHandle

 @Description	Acquire a new handle

 @Input		psBase - Pointer to handle base structure
		phHandle - Points to a handle pointer
		pvData - Pointer to resource to be associated with the handle

 @Output	phHandle - Points to a handle pointer

 @Return	Error code or PVRSRV_OK

******************************************************************************/
static PVRSRV_ERROR AcquireHandle(HANDLE_IMPL_BASE *psBase, 
				  IMG_HANDLE *phHandle, 
				  IMG_VOID *pvData)
{
	IMG_UINT32 ui32NewIndex = BASE_TO_TOTAL_INDICES(psBase);
	HANDLE_IMPL_DATA *psNewHandleData = IMG_NULL;
	PVRSRV_ERROR eError;

	PVR_ASSERT(psBase != IMG_NULL);
	PVR_ASSERT(phHandle != IMG_NULL);
	PVR_ASSERT(pvData != IMG_NULL);

	/* Ensure there is a free handle */
	eError = EnsureFreeHandles(psBase, 1);
	if (eError != PVRSRV_OK)
	{
		PVR_DPF((PVR_DBG_ERROR, "%s: EnsureFreeHandles failed (%s)",
			 __FUNCTION__, PVRSRVGetErrorStringKM(eError)));
		return eError;
	}
	PVR_ASSERT(psBase->ui32TotalFreeHandCount != 0);

	if (!psBase->bPurgingEnabled)
	{
		/* Array index of first free handle */
		ui32NewIndex = psBase->ui32FirstFreeIndex;

		/* Get handle array entry */
		psNewHandleData = INDEX_TO_HANDLE_DATA(psBase, ui32NewIndex);
	}
	else
	{
		IMG_UINT32 ui32BlockedIndex;

		/*
		 * If purging is enabled, we always try to allocate handles
		 * at the front of the array, to increase the chances that
		 * the size of the handle array can be reduced by a purge.
		 * No linked list of free handles is kept; we search for
		 * free handles as required.
		 */

		/*
		 * ui32FirstFreeIndex should only be set when a new batch of
		 * handle structures is allocated, and should always be a
		 * multiple of the block size.
		 */
		PVR_ASSERT((psBase->ui32FirstFreeIndex % HANDLE_BLOCK_SIZE) == 0);

		for (ui32BlockedIndex = ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(psBase->ui32FirstFreeIndex); ui32BlockedIndex < psBase->ui32TotalHandCount; ui32BlockedIndex += HANDLE_BLOCK_SIZE)
		{
			HANDLE_BLOCK *psHandleBlock = BASE_AND_INDEX_TO_HANDLE_BLOCK(psBase, ui32BlockedIndex);

			if (psHandleBlock->ui32FreeHandCount == 0)
			{
				continue;
			}

			for (ui32NewIndex = ui32BlockedIndex; ui32NewIndex < ui32BlockedIndex + HANDLE_BLOCK_SIZE; ui32NewIndex++)
			{
				psNewHandleData = INDEX_TO_HANDLE_DATA(psBase, ui32NewIndex);
				if (psNewHandleData->pvData == IMG_NULL)
				{
					break;
				}
			}
		}
		psBase->ui32FirstFreeIndex = 0;
		PVR_ASSERT(INDEX_IS_VALID(psBase, ui32NewIndex));
	}
	PVR_ASSERT(psNewHandleData != IMG_NULL);

	psBase->ui32TotalFreeHandCount--;

	PVR_ASSERT(INDEX_TO_BLOCK_FREE_HAND_COUNT(psBase, ui32NewIndex) <= HANDLE_BLOCK_SIZE);
	PVR_ASSERT(INDEX_TO_BLOCK_FREE_HAND_COUNT(psBase, ui32NewIndex) > 0);

	INDEX_TO_BLOCK_FREE_HAND_COUNT(psBase, ui32NewIndex)--;

	/* No free list management if purging is enabled */
	if (!psBase->bPurgingEnabled)
	{
		/* Check whether the last free handle has been allocated */
		if (psBase->ui32TotalFreeHandCount == 0)
		{
			PVR_ASSERT(psBase->ui32FirstFreeIndex == ui32NewIndex);
			PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == (ui32NewIndex + 1));

			psBase->ui32LastFreeIndexPlusOne = 0;
			psBase->ui32FirstFreeIndex = 0;
		}
		else
		{
			/*
			 * Update the first free handle index.
			 * If the "next free index plus one" field in the new
			 * handle structure is zero, the next free index is
			 * the index of the new handle plus one.  This
			 * convention has been adopted to simplify the
			 * initialisation of freshly allocated handle
			 * space.
			 */
			if (psNewHandleData->ui32NextIndexPlusOne == 0)
			{
				psBase->ui32FirstFreeIndex = ui32NewIndex + 1;
			}
			else
			{
				psBase->ui32FirstFreeIndex = psNewHandleData->ui32NextIndexPlusOne - 1;
			}
		}
	}

	PVR_ASSERT(HANDLE_DATA_TO_HANDLE(psNewHandleData) == INDEX_TO_HANDLE(ui32NewIndex));

	psNewHandleData->pvData = pvData;
	psNewHandleData->ui32NextIndexPlusOne = 0;

	/* Return the new handle to the client */
	*phHandle = INDEX_TO_HANDLE(ui32NewIndex);

#if defined(DEBUG_HANDLEALLOC_KM)
	PVR_DPF((PVR_DBG_MESSAGE, "Handle acquire base %p hdl %p", psBase, *phHandle));
#endif

	return PVRSRV_OK;
}
Example #15
0
PVRSRV_ERROR PVRSRVRGXSetComputeContextPriorityKM(CONNECTION_DATA *psConnection,
												  RGX_SERVER_COMPUTE_CONTEXT *psComputeContext,
												  IMG_UINT32 ui32Priority)
{
	PVRSRV_ERROR eError;

	eError = ContextSetPriority(psComputeContext->psServerCommonContext,
								psConnection,
								psComputeContext->psDeviceNode->pvDevice,
								ui32Priority,
								RGXFWIF_DM_CDM);
	if (eError != PVRSRV_OK)
	{
		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to set the priority of the compute context (%s)", __FUNCTION__, PVRSRVGetErrorStringKM(eError)));
	}
	return eError;
}
Example #16
0
/*!
******************************************************************************

 @Function	PVRSRVSetPowerStateKM

 @Description	Set the system into a new state

 @Input		eNewPowerState :
 @Input		bForced : TRUE if the transition should not fail (e.g. OS request)

 @Return	PVRSRV_ERROR

******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState, IMG_BOOL bForced)
{
	PVRSRV_ERROR	eError;
	PVRSRV_DATA		*psPVRSRVData = PVRSRVGetPVRSRVData();
	IMG_UINT        uiStage = 0;

	PVRSRV_DEV_POWER_STATE eNewDevicePowerState = 
	  _IsSystemStatePowered(eNewSysPowerState)? PVRSRV_DEV_POWER_STATE_DEFAULT : PVRSRV_DEV_POWER_STATE_OFF;

	/* require a proper power state */
	if (eNewSysPowerState == PVRSRV_SYS_POWER_STATE_Unspecified)
	{
		return PVRSRV_ERROR_INVALID_PARAMS;
	}

	/* no power transition requested, so do nothing */
	if (eNewSysPowerState == psPVRSRVData->eCurrentPowerState)
	{
		return PVRSRV_OK;
	}

	/* Prevent simultaneous SetPowerStateKM calls */
	PVRSRVForcedPowerLock();

	/* Perform pre transitions: first device and then sys layer */
	eError = PVRSRVDevicePrePowerStateKM(IMG_TRUE, 0, eNewDevicePowerState, bForced);
	if (eError != PVRSRV_OK)
	{
		uiStage++;
		goto ErrorExit;
	}
	eError = PVRSRVSysPrePowerState(eNewSysPowerState, bForced);
	if (eError != PVRSRV_OK)
	{
		uiStage++;
		goto ErrorExit;
	}

	/* Perform system-specific post power transitions: first sys layer and then device */
	eError = PVRSRVSysPostPowerState(eNewSysPowerState, bForced);
	if (eError != PVRSRV_OK)
	{
		uiStage++;
		goto ErrorExit;
	}
	eError = PVRSRVDevicePostPowerStateKM(IMG_TRUE, 0, eNewDevicePowerState, bForced);
	if (eError != PVRSRV_OK)
	{
		uiStage++;
		goto ErrorExit;
	}

	psPVRSRVData->eCurrentPowerState = eNewSysPowerState;
	psPVRSRVData->eFailedPowerState = PVRSRV_SYS_POWER_STATE_Unspecified;

	PVRSRVPowerUnlock();

	/*
		Reprocess the devices' queues in case commands were blocked during
		the power transition.
	*/
	if (_IsSystemStatePowered(eNewSysPowerState) &&
			PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL))
	{
		PVRSRVCheckStatus(IMG_NULL);
	}

	return PVRSRV_OK;

ErrorExit:
	/* save the power state for the re-attempt */
	psPVRSRVData->eFailedPowerState = eNewSysPowerState;

	PVRSRVPowerUnlock();

	PVR_DPF((PVR_DBG_ERROR,
			"PVRSRVSetPowerStateKM: Transition from %d to %d FAILED (%s) at stage %d, forced: %d. Dumping debug info.",
			psPVRSRVData->eCurrentPowerState, eNewSysPowerState, PVRSRVGetErrorStringKM(eError), uiStage, bForced));

	PVRSRVDebugRequest(DEBUG_REQUEST_VERBOSITY_MAX);

	return eError;
}
Example #17
0
/*!
******************************************************************************

 @Function	PVRSRVSetDevicePowerStateKM

 @Description	Set the Device into a new state

 @Input		ui32DeviceIndex : device index
 @Input		eNewPowerState : New power state
 @Input		bForced : TRUE if the transition should not fail (e.g. OS request)

 @Return	PVRSRV_ERROR

******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(IMG_UINT32				ui32DeviceIndex,
										 PVRSRV_DEV_POWER_STATE	eNewPowerState,
										 IMG_BOOL				bForced)
{
	PVRSRV_DATA*    psPVRSRVData = PVRSRVGetPVRSRVData();
	PVRSRV_ERROR	eError;
	PVRSRV_DEV_POWER_STATE eOldPowerState;

	eError = PVRSRVGetDevicePowerState(ui32DeviceIndex, &eOldPowerState);
	if (eError != PVRSRV_OK)
	{
		PVR_DPF((PVR_DBG_WARNING, "PVRSRVSetDevicePowerStateKM: Couldn't read power state."));
		eOldPowerState = PVRSRV_DEV_POWER_STATE_DEFAULT;
	}

	#if defined(PDUMP)
	if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT)
	{
		/*
			Pdump a power-up regardless of the default state.
			Then disable pdump and transition to the default power state.
			This ensures that a power-up is always present in the pdump when necessary.
		*/
		eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_ON, bForced);
		if(eError != PVRSRV_OK)
		{
			goto Exit;
		}

		eError = PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_ON, bForced);

		if (eError != PVRSRV_OK)
		{
			goto Exit;
		}

		PDUMPPOWCMDSTART();
	}
	#endif /* PDUMP */

	eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState, bForced);
	if(eError != PVRSRV_OK)
	{
		if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT)
		{
			PDUMPPOWCMDEND();
		}
		goto Exit;
	}

	eError = PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState, bForced);

	if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT)
	{
		PDUMPPOWCMDEND();
	}

	/* Signal Device Watchdog Thread about power mode change. */
	if (eOldPowerState != eNewPowerState && eNewPowerState == PVRSRV_DEV_POWER_STATE_ON)
	{
		psPVRSRVData->ui32DevicesWatchdogPwrTrans++;

		if (psPVRSRVData->ui32DevicesWatchdogTimeout == DEVICES_WATCHDOG_POWER_OFF_SLEEP_TIMEOUT)
		{
			if (psPVRSRVData->hDevicesWatchdogEvObj)
			{
				eError = OSEventObjectSignal(psPVRSRVData->hDevicesWatchdogEvObj);
				PVR_LOG_IF_ERROR(eError, "OSEventObjectSignal");
			}
		}
	}

Exit:

	if (eError == PVRSRV_ERROR_DEVICE_POWER_CHANGE_DENIED)
	{
		PVR_DPF((PVR_DBG_MESSAGE,
				"PVRSRVSetDevicePowerStateKM : Transition to %d was denied, Forced=%d", eNewPowerState, bForced));
	}
	else if(eError != PVRSRV_OK)
	{
		PVR_DPF((PVR_DBG_WARNING,
				"PVRSRVSetDevicePowerStateKM : Transition to %d FAILED (%s)", eNewPowerState, PVRSRVGetErrorStringKM(eError)));
	}
	
	return eError;
}
Example #18
0
/*!
******************************************************************************

 @Function	FreeHandle

 @Description	Free a handle data structure.

 @Input		psBase - Pointer to handle base structure
		hHandle - Handle to be freed
		eType - Type of the handle to be freed
		ppvData - Location for data associated with the freed handle

 @Output 		ppvData - Points to data that was associated with the freed handle

 @Return	PVRSRV_OK or PVRSRV_ERROR

******************************************************************************/
static PVRSRV_ERROR FreeHandle(PVRSRV_HANDLE_BASE *psBase,
			       IMG_HANDLE hHandle,
			       PVRSRV_HANDLE_TYPE eType,
			       IMG_VOID **ppvData)
{
	HANDLE_DATA *psHandleData = IMG_NULL;
	HANDLE_DATA *psReleasedHandleData;
	PVRSRV_ERROR eError;

	eError = GetHandleData(psBase, &psHandleData, hHandle, eType);
	if (eError != PVRSRV_OK)
	{
		return eError;
	}

	PVR_ASSERT(psHandleData->ui32Refs>0);

	psHandleData->ui32Refs--;
	if (psHandleData->ui32Refs > 0)
	{
		/* Reference count still positive, only possible for shared handles */
		PVR_ASSERT(TEST_ALLOC_FLAG(psHandleData, PVRSRV_HANDLE_ALLOC_FLAG_SHARED));
		return PVRSRV_OK;
	}
	/* else reference count zero, time to clean up */

	if (!TEST_ALLOC_FLAG(psHandleData, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
	{
		HAND_KEY aKey;
		IMG_HANDLE hRemovedHandle;

		InitKey(aKey, psBase, psHandleData->pvData, psHandleData->eType, ParentIfPrivate(psHandleData));

		hRemovedHandle = (IMG_HANDLE)HASH_Remove_Extended(psBase->psHashTab, aKey);

		PVR_ASSERT(hRemovedHandle != IMG_NULL);
		PVR_ASSERT(hRemovedHandle == psHandleData->hHandle);
		PVR_UNREFERENCED_PARAMETER(hRemovedHandle);
	}

	eError = UnlinkFromParent(psBase, psHandleData);
	if (eError != PVRSRV_OK)
	{
		PVR_DPF((PVR_DBG_ERROR,
			 "FreeHandle: Error whilst unlinking from parent handle (%s)", 
			 PVRSRVGetErrorStringKM(eError)));
		return eError;
	}

	/* Free children */
	eError = IterateOverChildren(psBase, psHandleData, FreeHandleWrapper);
	if (eError != PVRSRV_OK)
	{
		PVR_DPF((PVR_DBG_ERROR,
			 "FreeHandle: Error whilst freeing subhandles (%s)",
			 PVRSRVGetErrorStringKM(eError)));
		return eError;
	}

	eError = gpsHandleFuncs->pfnReleaseHandle(psBase->psImplBase, psHandleData->hHandle, (IMG_VOID **)&psReleasedHandleData);
	if (eError == PVRSRV_OK)
	{
		PVR_ASSERT(psReleasedHandleData == psHandleData);
	}

	if (ppvData)
	{
		*ppvData = psHandleData->pvData;
	}

	OSFreeMem(psHandleData);

	return eError;
}
Example #19
0
PVRSRV_ERROR RGXCreateCCB(PVRSRV_DEVICE_NODE	*psDeviceNode,
						  IMG_UINT32			ui32CCBSizeLog2,
						  CONNECTION_DATA		*psConnectionData,
						  const IMG_CHAR		*pszName,
						  RGX_SERVER_COMMON_CONTEXT *psServerCommonContext,
						  RGX_CLIENT_CCB		**ppsClientCCB,
						  DEVMEM_MEMDESC 		**ppsClientCCBMemDesc,
						  DEVMEM_MEMDESC 		**ppsClientCCBCtrlMemDesc)
{
	PVRSRV_ERROR	eError;
	DEVMEM_FLAGS_T	uiClientCCBMemAllocFlags, uiClientCCBCtlMemAllocFlags;
	IMG_UINT32		ui32AllocSize = (1U << ui32CCBSizeLog2);
	RGX_CLIENT_CCB	*psClientCCB;

	psClientCCB = OSAllocMem(sizeof(*psClientCCB));
	if (psClientCCB == IMG_NULL)
	{
		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
		goto fail_alloc;
	}
	psClientCCB->psServerCommonContext = psServerCommonContext;

	uiClientCCBMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
	                            PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(META_CACHED) |
								PVRSRV_MEMALLOCFLAG_GPU_READABLE |
								PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
								PVRSRV_MEMALLOCFLAG_CPU_READABLE |
								PVRSRV_MEMALLOCFLAG_UNCACHED |
								PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
								PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE;

	uiClientCCBCtlMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
								PVRSRV_MEMALLOCFLAG_GPU_READABLE |
								PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
								PVRSRV_MEMALLOCFLAG_CPU_READABLE |
								
								PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE | 
								PVRSRV_MEMALLOCFLAG_UNCACHED |
								PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
								PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE;

	PDUMPCOMMENT("Allocate RGXFW cCCB");
	eError = DevmemFwAllocateExportable(psDeviceNode,
										ui32AllocSize,
										uiClientCCBMemAllocFlags,
										"FirmwareClientCCB",
										&psClientCCB->psClientCCBMemDesc);

	if (eError != PVRSRV_OK)
	{
		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateCCBKM: Failed to allocate RGX client CCB (%s)",
				PVRSRVGetErrorStringKM(eError)));
		goto fail_alloc_ccb;
	}

	eError = DevmemAcquireCpuVirtAddr(psClientCCB->psClientCCBMemDesc,
									  (IMG_VOID **) &psClientCCB->pui8ClientCCB);
	if (eError != PVRSRV_OK)
	{
		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateCCBKM: Failed to map RGX client CCB (%s)",
				PVRSRVGetErrorStringKM(eError)));
		goto fail_map_ccb;
	}

	PDUMPCOMMENT("Allocate RGXFW cCCB control");
	eError = DevmemFwAllocateExportable(psDeviceNode,
										sizeof(RGXFWIF_CCCB_CTL),
										uiClientCCBCtlMemAllocFlags,
										"FirmwareClientCCBControl",
										&psClientCCB->psClientCCBCtrlMemDesc);

	if (eError != PVRSRV_OK)
	{
		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateCCBKM: Failed to allocate RGX client CCB control (%s)",
				PVRSRVGetErrorStringKM(eError)));
		goto fail_alloc_ccbctrl;
	}

	eError = DevmemAcquireCpuVirtAddr(psClientCCB->psClientCCBCtrlMemDesc,
									  (IMG_VOID **) &psClientCCB->psClientCCBCtrl);
	if (eError != PVRSRV_OK)
	{
		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateCCBKM: Failed to map RGX client CCB (%s)",
				PVRSRVGetErrorStringKM(eError)));
		goto fail_map_ccbctrl;
	}

	psClientCCB->psClientCCBCtrl->ui32WriteOffset = 0;
	psClientCCB->psClientCCBCtrl->ui32ReadOffset = 0;
	psClientCCB->psClientCCBCtrl->ui32DepOffset = 0;
	psClientCCB->psClientCCBCtrl->ui32WrapMask = ui32AllocSize - 1;
	OSStringCopy(psClientCCB->szName, pszName);

	PDUMPCOMMENT("cCCB control");
	DevmemPDumpLoadMem(psClientCCB->psClientCCBCtrlMemDesc,
					   0,
					   sizeof(RGXFWIF_CCCB_CTL),
					   PDUMP_FLAGS_CONTINUOUS);
	PVR_ASSERT(eError == PVRSRV_OK);

	psClientCCB->ui32HostWriteOffset = 0;
	psClientCCB->ui32LastPDumpWriteOffset = 0;
	psClientCCB->ui32Size = ui32AllocSize;

#if defined REDUNDANT_SYNCS_DEBUG
	psClientCCB->ui32UpdateWriteIndex = 0;
	OSMemSet(psClientCCB->asFenceUpdateList, 0, sizeof(psClientCCB->asFenceUpdateList));
#endif

	eError = PDumpRegisterTransitionCallback(psConnectionData->psPDumpConnectionData,
											  _RGXCCBPDumpTransition,
											  psClientCCB,
											  &psClientCCB->hTransition);
	if (eError != PVRSRV_OK)
	{
		goto fail_pdumpreg;
	}
	/*
		Note:
		Due to resman the connection structure could be freed before the client
		CCB so rather then saving off the connection structure save the PDump
		specific memory which is refcounted to ensure it's not freed too early
	*/
	psClientCCB->psPDumpConnectionData = psConnectionData->psPDumpConnectionData;
	PDUMPCOMMENT("New RGXFW cCCB(%s@%p) created",
				 psClientCCB->szName,
				 psClientCCB);

	*ppsClientCCB = psClientCCB;
	*ppsClientCCBMemDesc = psClientCCB->psClientCCBMemDesc;
	*ppsClientCCBCtrlMemDesc = psClientCCB->psClientCCBCtrlMemDesc;
	return PVRSRV_OK;

fail_pdumpreg:
	DevmemReleaseCpuVirtAddr(psClientCCB->psClientCCBCtrlMemDesc);
fail_map_ccbctrl:
	DevmemFwFree(psClientCCB->psClientCCBCtrlMemDesc);
fail_alloc_ccbctrl:
	DevmemReleaseCpuVirtAddr(psClientCCB->psClientCCBMemDesc);
fail_map_ccb:
	DevmemFwFree(psClientCCB->psClientCCBMemDesc);
fail_alloc_ccb:
	OSFreeMem(psClientCCB);
fail_alloc:
	PVR_ASSERT(eError != PVRSRV_OK);
	return eError;
}