예제 #1
0
void IPC_PoolDumpStats(IPC_BufferPool Pool)
{
	IPC_BufferPool_T *PoolPtr = IPC_PoolToPtr(Pool);

	if (!PoolPtr) {
		IPC_TRACE(IPC_Channel_General, "IPC_Stats", "Pool %08X Invalid",
			  Pool, 0, 0, 0);
		return;
	};

	IPC_TRACE(IPC_Channel_General, "IPC_Stats",
		  "Pool %08X: UserP %08X, BufSize %d, BufCount %d", Pool,
		  PoolPtr->UserParameter, PoolPtr->MaxDataSize,
		  PoolPtr->MaxBuffers);

	IPC_TRACE(IPC_Channel_General, "         ",
		  "Alloc %d, Fail %d, FcStart %d, FcStop %d",
		  PoolPtr->Allocations, PoolPtr->AllocationFailures,
		  PoolPtr->FlowStartCalls, PoolPtr->FlowStopCalls);

	IPC_TRACE(IPC_Channel_General, "         ",
		  "Sent %d, FreeBufs %d, LowWaterMark %d, FcState %d",
		  PoolPtr->BytesSent, PoolPtr->FreeBuffers,
		  PoolPtr->LowWaterMark, PoolPtr->FlowControlState);
}
예제 #2
0
IPC_U32 IPC_PoolFreeBuffers(IPC_BufferPool Pool)
{
	IPC_BufferPool_T *PoolPtr = IPC_PoolToPtr(Pool);
	if (!PoolPtr) {
		IPC_TRACE(IPC_Channel_Error, "IPC_PoolFreeBuffers",
			  "Invalid Pool %d", Pool, 0, 0, 0);
		return 0;
	}
	return PoolPtr->FreeBuffers;
}
예제 #3
0
//**************************************************
IPC_U32 IPC_PoolUserParameterGet (IPC_BufferPool Pool)
{
	IPC_BufferPool_T *	PoolPtr	= IPC_PoolToPtr (Pool);

	if (!Pool)
	{
		IPC_TRACE (IPC_Channel_Error, "IPC_PoolUserParameterGet", "Invalid Pool %d", Pool, 0, 0, 0);
		return 0;
	}

	return PoolPtr->UserParameter;
}
예제 #4
0
//**************************************************
void  IPC_PoolSetFreeCallback (IPC_BufferPool Pool, IPC_BufferFreeFPtr_T	BufferFreeFunction)
{
	IPC_BufferPool_T *	PoolPtr	= IPC_PoolToPtr (Pool);

	if (!PoolPtr)
	{
		IPC_TRACE (IPC_Channel_Error, "IPC_PoolSetFreeCallback", "Invalid Pool %d", Pool, 0, 0, 0);
		return;
	}

	PoolPtr->BufferFreeFunction = BufferFreeFunction;
}
예제 #5
0
//**************************************************
void IPC_PoolAddBytesSent (IPC_BufferPool Pool, IPC_U32 Bytes)
{
	IPC_BufferPool_T *	PoolPtr	= IPC_PoolToPtr (Pool);

	if (!PoolPtr)
	{
		IPC_TRACE (IPC_Channel_Error, "IPC_PoolAddBytesSent", "Invalid Pool %d", Pool, 0, 0, 0);
		return;
	}

	PoolPtr->BytesSent += Bytes;
}
예제 #6
0
//**************************************************
IPC_CPU_ID_T IPC_PoolOwningCpu (IPC_BufferPool Pool)
{
	IPC_BufferPool_T *	PoolPtr	= IPC_PoolToPtr (Pool);

	if (!PoolPtr)
	{
		IPC_TRACE (IPC_Channel_Error, "IPC_PoolMaxDataSize", "Invalid Pool %d", Pool, 0, 0, 0);
		return IPC_NO_CPU;
	}

	return PoolPtr->Cpu;
}
예제 #7
0
//**************************************************
IPC_U32 IPC_PoolMaxHeaderSize (IPC_BufferPool Pool)
{
	IPC_BufferPool_T *	PoolPtr	= IPC_PoolToPtr (Pool);

	if (!PoolPtr)
	{
		IPC_TRACE (IPC_Channel_Error, "IPC_PoolMaxHeaderSize", "Invalid Pool %d", Pool, 0, 0, 0);
		return 0;
	}

	return PoolPtr->MaxHeaderSize;
}
예제 #8
0
//**************************************************
IPC_EndpointId_T IPC_PoolDestinationEndpointId (IPC_BufferPool Pool)
{
	IPC_BufferPool_T *	PoolPtr	= IPC_PoolToPtr (Pool);

	if (!PoolPtr)
	{
		IPC_TRACE (IPC_Channel_Error, "IPC_PoolDestinationEndpointId", "Invalid Pool %d", Pool, 0, 0, 0);
		return IPC_EP_None;
	}

	return PoolPtr->DestinationEndpointId;
}
예제 #9
0
void IPC_PoolDump(IPC_BufferPool Pool)
{
	IPC_BufferPool_T *PoolPtr = IPC_PoolToPtr(Pool);
	IPC_U32 Id;
	IPC_SmPtr Buffer;
	IPC_U32 BufferSize;
	IPC_Buffer_T *BufferPtr;

	IPC_TRACE(IPC_Channel_General, "----- IPC_PoolDump -----", "", 0, 0, 0,
		  0);

	if (!PoolPtr) {
		IPC_TRACE(IPC_Channel_General, "IPC_PoolDump",
			  "Pool %08X Invalid", Pool, 0, 0, 0);
		return;
	};

	IPC_TRACE(IPC_Channel_General, "IPC_PoolDump",
		  "Pool %08X, CPU %s, SrcEp %02X, DestEp %02X", Pool,
		  (IPC_U32)IPC_GetCpuName(PoolPtr->Cpu),
		  PoolPtr->SourceEndpointId, PoolPtr->DestinationEndpointId);
	IPC_TRACE(IPC_Channel_General, "            ",
		  "SrcEp Id=%02X Name=%s, DestEp Id=%02X Name=%s",
		  PoolPtr->SourceEndpointId,
		  (IPC_U32)IPC_GetEndPointName(PoolPtr->SourceEndpointId),
		  PoolPtr->DestinationEndpointId,
		  (IPC_U32)IPC_GetEndPointName(PoolPtr->DestinationEndpointId));

	IPC_TRACE(IPC_Channel_General, "            ",
		  "BufCount %d, Free  %d, FlowState %01d, Param %08X",
		  PoolPtr->MaxBuffers, PoolPtr->FreeBuffers,
		  PoolPtr->FlowControlState, PoolPtr->UserParameter);

	IPC_PoolDumpStats(Pool);

	/* Dump IPC buffer not consumed by receiver to debug
	   IPC memory depletion issue */
	if (PoolPtr->MaxBuffers == PoolPtr->FreeBuffers)
		return;

	Buffer = Pool + sizeof(IPC_BufferPool_T);
	BufferSize =
	    IPC_BufferOverhead() + PoolPtr->MaxHeaderSize +
	    PoolPtr->MaxDataSize;
	IPC_TRACE(IPC_Channel_General, "IPC_PoolDump", "Allocated Buffers:", 0,
		  0, 0, 0);
	for (Id = 0; Id < PoolPtr->MaxBuffers; Id++) {
		BufferPtr = IPC_BufferToPtr(Buffer);
		if (BufferPtr->StatusCode != IPC_BUFFER_STATUS_FREE)
			IPC_BufferDump(Buffer);
		Buffer += BufferSize;
	}
}
예제 #10
0
//**************************************************
IPC_Boolean IPC_PoolUserParameterSet (IPC_BufferPool Pool, IPC_U32 Parameter)
{
	IPC_BufferPool_T *	PoolPtr	= IPC_PoolToPtr (Pool);

	if (!PoolPtr)
	{
		IPC_TRACE (IPC_Channel_Error, "IPC_PoolUserParameterSet", "Invalid Pool %d", Pool, 0, 0, 0);
		return IPC_FALSE;
	}

	PoolPtr->UserParameter = Parameter;

	return IPC_TRUE;
}
예제 #11
0
void IPC_BufferReturn(IPC_Buffer Buffer, IPC_BufferPool Pool)
{
	IPC_BufferPool_T *PoolPtr = IPC_PoolToPtr(Pool);

	if (PoolPtr == 0) {
		IPC_TRACE(IPC_Channel_Error, "IPC_BufferReturn",
			  "Invalid Pool for Buffer %08X", Buffer, 0, 0, 0);
		return;
	}

	if (PoolPtr->BufferFreeFunction) {
		IPC_TRACE(IPC_Channel_Buffer, "IPC_BufferReturn",
			  "User Function %08X called for Buffer %08X",
			  PoolPtr->BufferFreeFunction, Buffer, 0, 0);
		(PoolPtr->BufferFreeFunction) (Pool, Buffer);
	} else {
		IPC_BufferReturnToPool(Buffer, Pool);
	}
}
예제 #12
0
void IPC_BufferReturnToPool(IPC_Buffer Buffer, IPC_BufferPool Pool)
{
	IPC_BufferPool_T *PoolPtr = IPC_PoolToPtr(Pool);
	IPC_U32 BufferCount;
	IPC_Boolean FlowControlCallNeeded = IPC_FALSE;

	CRITICAL_REIGON_SETUP
	    IPC_TRACE(IPC_Channel_Buffer, "IPC_BufferReturnToPool",
		      "Buffer %d (%08X), now %d in pool", IPC_BufferId(Buffer),
		      Buffer, PoolPtr->FreeBuffers + 1, 0);

	CRITICAL_REIGON_ENTER(PoolPtr->Lock);

	BufferCount = ++PoolPtr->FreeBuffers;

#ifdef IPC_DEBUG
	IPC_QRemove(IPC_BufferQueue(Buffer));
#endif
	IPC_QAddBack(IPC_BufferQueue(Buffer),
		     IPC_POOLFreeQ(IPC_SmOffset(PoolPtr)));

	/* Flow Control Check */
	if (BufferCount == PoolPtr->FlowStartLimit)
		CHECK_FLOW_STATE(PoolPtr, IPC_FLOW_START, FlowControlCallNeeded)

		    CRITICAL_REIGON_LEAVE(PoolPtr->Lock);

	if (FlowControlCallNeeded)
		IPC_ReportFlowControlEvent(PoolPtr, IPC_FLOW_START);

	/* Last ditch check - should never happen */
	if (PoolPtr->FlowControlState == IPC_FLOW_STOP
	    && !PoolPtr->FlowControlCallPending
	    && PoolPtr->FlowStartLimit < BufferCount) {
		IPC_TRACE(IPC_Channel_FlowControl, "IPC_BufferReturnToPool",
			  "Retry Flow Start", 0, 0, 0, 0);
		IPC_ReportFlowControlEvent(PoolPtr, IPC_FLOW_START);
	}

	/* For IPC_AllocateBufferWait () */
	if ((BufferCount == 1) && (PoolPtr->EmptyEvent))
		IPC_EVENT_SET(PoolPtr->EmptyEvent);
}
예제 #13
0
void IPC_BufferDump(IPC_Buffer Buffer)
{
	IPC_Buffer_T *BufferPtr = IPC_BufferToPtr(Buffer);
	/**
	 * DataPtr is used to dump the contents of the first 4 U32s
	 * of the memory location
	 *
	 * coverity[returned_pointer]
	 */
	IPC_U32 *DataPtr = IPC_BufferDataPointer(Buffer);
	IPC_BufferPool_T *PoolPtr = IPC_PoolToPtr(BufferPtr->Pool);

	if (BufferPtr == 0) {
		IPC_TRACE(IPC_Channel_General, "IPC_BufferDump",
			  "Invalid Buffer %08X", Buffer, 0, 0, 0);
		return;
	}

	IPC_TRACE(IPC_Channel_General, "IPC_BufferDump",
		  "Id %d, Pool %08X, Next %08X, Prev %08X", BufferPtr->BufferId,
		  BufferPtr->Pool, BufferPtr->Q.Next, BufferPtr->Q.Previous);

	IPC_TRACE(IPC_Channel_General, "              ",
		  "Buffer %08X, DataOffset %08X, DataSize %d, HeaderSize %d",
		  BufferPtr->DataBufferStart, BufferPtr->DataOffset,
		  BufferPtr->DataSize, BufferPtr->HeaderSize);

	if (BufferPtr->StatusCode == IPC_BUFFER_STATUS_FREE) {
		IPC_TRACE(IPC_Channel_General, "              ",
			  "Free  FreeTime %d, prevAllocTime %d, prevSendTime %d",
			  BufferPtr->TimeStampFree, BufferPtr->TimeStampAlloc,
			  BufferPtr->TimeStampSend, 0);
	} else if (BufferPtr->StatusCode == IPC_BUFFER_STATUS_ALLOC) {
		IPC_TRACE(IPC_Channel_General, "              ",
			  "Alloc  AllocTime %d, prevSendTime %d, prevFreeTime %d",
			  BufferPtr->TimeStampAlloc, BufferPtr->TimeStampSend,
			  BufferPtr->TimeStampFree, 0);
	} else if (BufferPtr->StatusCode == IPC_BUFFER_STATUS_SENT) {
		IPC_TRACE(IPC_Channel_General, "              ",
			  "Sent  SendTime %d, AllocTime %d, prevFreeTime %d",
			  BufferPtr->TimeStampSend, BufferPtr->TimeStampAlloc,
			  BufferPtr->TimeStampFree, 0);
	} else {
		IPC_TRACE(IPC_Channel_General, "              ",
			  "Invalid Status", 0, 0, 0, 0);
	}

	IPC_TRACE(IPC_Channel_General, "              ",
		  "Data 0..3 %08X %08X %08X %08X", DataPtr[0], DataPtr[1],
		  DataPtr[2], DataPtr[3]);

	IPC_TRACE(IPC_Channel_General, "              ",
		  "Data 4..7 %08X %08X %08X %08X", DataPtr[4], DataPtr[5],
		  DataPtr[6], DataPtr[7]);

	/* Print RPC message ID located at byte 18-19 of IPC buffer */
	if (PoolPtr->SourceEndpointId == IPC_EP_Capi2Cp ||
	    PoolPtr->DestinationEndpointId == IPC_EP_Capi2Cp) {
		UInt8 *rpcDataPtr = (UInt8 *)DataPtr;
		UInt32 rpcMsgId;
		rpcMsgId =
		    ((UInt32)(rpcDataPtr[19])) | ((UInt32)(rpcDataPtr[18]) <<
						  8);
		IPC_TRACE(IPC_Channel_General, "              ",
			  "RPC message ID %08X", rpcMsgId, 0, 0, 0);
	}

}
예제 #14
0
IPC_Buffer IPC_AllocateBufferWait(IPC_BufferPool Pool, IPC_U32 MilliSeconds)
{
	IPC_BufferPool_T *PoolPtr = IPC_PoolToPtr(Pool);
	IPC_Buffer Buffer;
	IPC_ReturnCode_T errCode;
	UInt32 curTick, endTick;
	UInt32 beforeTick, afterTick;

	curTick = 0;
	endTick = MilliSeconds;

	while (curTick < endTick) {
		/* Try straight allocate first
		   (saves event operations most of the time) */
		Buffer = IPC_AllocateBuffer(Pool);
		if (Buffer)
			return Buffer;

		/* Check Event exists */
		if (!PoolPtr->EmptyEvent) {
			/* Can't suspend without an event flag */
			IPC_TRACE(IPC_Channel_Error, "IPC_AllocateBufferWait",
				  "No Event Flag for Pool %08X", Pool, 0, 0, 0);
			return 0;
		}

		/* Clear event before waiting on it */
		if (IPC_OK != IPC_EVENT_CLEAR(PoolPtr->EmptyEvent)) {
			IPC_TRACE(IPC_Channel_Error, "IPC_AllocateBufferWait",
				  "Cannot clear Event Flag %08P for Pool %08X",
				  PoolPtr->EmptyEvent, Pool, 0, 0);
			return 0;
		}

		/* Check in case the event was set  before the clear */
		Buffer = IPC_AllocateBuffer(Pool);
		if (Buffer)
			return Buffer;

		/* Now can safely wait for the event to be set
		 * by the buffer free */
		IPC_TRACE(IPC_Channel_FlowControl, "IPC_AllocateBufferWait",
			  "Pool %08X Empty, waiting for %d Milliseconds, total=%d",
			  Pool, (endTick - curTick), MilliSeconds, 0);

		beforeTick = TIMER_GetValue();
		errCode =
		    IPC_EVENT_WAIT(PoolPtr->EmptyEvent, (endTick - curTick));
		afterTick = TIMER_GetValue();

		/* Handle wrap around for 0xFFFFFFFF */
		curTick += (UInt32)(afterTick - beforeTick);

		if (IPC_ERROR == errCode) {
			IPC_TRACE(IPC_Channel_Error, "IPC_AllocateBufferWait",
				  "Error from IPC_EVENT_WAIT; Event Flag %08P for Pool %08X",
				  PoolPtr->EmptyEvent, Pool, 0, 0);
			return 0;
		} else if (IPC_OK == errCode) {
			continue;	/* retry */
		} else {	/* IPC_TIMEOUT */
			break;
		}
	}

	return IPC_AllocateBuffer(Pool);
}
예제 #15
0
IPC_Buffer IPC_AllocateBuffer(IPC_BufferPool Pool)
{
	CRITICAL_REIGON_SETUP IPC_BufferPool_T *PoolPtr = IPC_PoolToPtr(Pool);
	IPC_SmQEntry QElement;
	IPC_U32 BufferCount;
	IPC_Buffer Buffer;
	IPC_Boolean FlowControlCallNeeded = IPC_FALSE;

	if (!Pool) {
		IPC_TRACE(IPC_Channel_Error, "IPC_AllocateBuffer",
			  "Invalid Pool %08X", Pool, 0, 0, 0);
		return 0;
	}

	CRITICAL_REIGON_ENTER(PoolPtr->Lock);

	QElement = IPC_QGetFirst(IPC_POOLFreeQ(Pool));

	if (!QElement) {
		PoolPtr->FlowControlState = IPC_FLOW_STOP;
		PoolPtr->AllocationFailures++;
		CRITICAL_REIGON_LEAVE(PoolPtr->Lock);

		if (PoolPtr->DestinationEndpointId != IPC_EP_LogApps)
			IPC_TRACE(IPC_Channel_FlowControl,
				  "IPC_ReportFlowControlEvent",
				  "Pool %08X Empty, Allocations %d AllocationFailures %d FlowStopCalls %d",
				  Pool, PoolPtr->Allocations,
				  PoolPtr->AllocationFailures,
				  PoolPtr->FlowStopCalls);
		return 0;
	}
#ifdef IPC_DEBUG
	IPC_QAddBack(QElement, IPC_SmOffset(&PoolPtr->AllocatedBufferQ));
#endif

	BufferCount = --PoolPtr->FreeBuffers;

	/* Flow Control Check */
	if (BufferCount == PoolPtr->FlowStopLimit)
		CHECK_FLOW_STATE(PoolPtr, IPC_FLOW_STOP, FlowControlCallNeeded)

		    CRITICAL_REIGON_LEAVE(PoolPtr->Lock);

	if (FlowControlCallNeeded)
		IPC_ReportFlowControlEvent(PoolPtr, IPC_FLOW_STOP);

	Buffer = IPC_QEntryPtr(QElement)->Item;
	if (Buffer) {
		IPC_Buffer_T *BufferPtr = IPC_SmOffsetToPointer(IPC_Buffer_T,
								Buffer);

		BufferPtr->HeaderSize = 0;
		BufferPtr->DataSize = 0;
		BufferPtr->UserParameter = 0;
		BufferPtr->TimeStampAlloc = TIMER_GetValue();
		BufferPtr->StatusCode = IPC_BUFFER_STATUS_ALLOC;
		BufferPtr->DataOffset = BufferPtr->DataBufferStart +
		    IPC_PoolPtr(BufferPtr->Pool)->MaxHeaderSize;
	}

	IPC_TRACE(IPC_Channel_Buffer, "IPC_AllocateBuffer",
		  "Buf %d (%08X) Pool %08X, %d Left", IPC_BufferId(Buffer),
		  Buffer, Pool, BufferCount);

	/* Update Statistics */
	PoolPtr->Allocations++;

	if (BufferCount < PoolPtr->LowWaterMark)
		PoolPtr->LowWaterMark = BufferCount;

	return Buffer;
}
예제 #16
0
void IPC_PoolDelete(IPC_BufferPool Pool)
{
	IPC_BufferPool_T *PoolPtr = IPC_PoolToPtr(Pool);
	IPC_EVENT_DELETE(PoolPtr->EmptyEvent);
	CRITICAL_REIGON_DELETE(PoolPtr->Lock);
}