コード例 #1
0
IPC_Boolean IPC_SmIsEndpointRegistered(IPC_EndpointId_T EndpointId)
{
	IPC_Endpoint EndpointPtr = IPC_SmEndpointInfo(EndpointId);

	if (EndpointPtr == 0)
		return IPC_FALSE;
	else
		return IPC_TRUE;
}
コード例 #2
0
void IPC_SmSendBuffer(IPC_Buffer Buffer)
{
	IPC_EndpointId_T DestinationEpId;
	IPC_Endpoint DestinationEpPtr;
	IPC_CPU_ID_T DestinationCpu;

	DestinationEpId = IPC_BufferDestinationEndpointId(Buffer);

#ifdef IPC_DEBUG
	if (DestinationEpId == IPC_EP_None) {
		IPC_TRACE(IPC_Channel_Error,
			  "IPC_SmSendBuffer",
			  "Invalid Destination Endpoint %08X for Buffer %08X",
			  DestinationEpId, Buffer, 0, 0);
		return;
	}
#endif

#ifdef FUSE_IPC_CRASH_SUPPORT
	if (g_bCpCrashed == IPC_TRUE) {
		IPC_TRACE(IPC_Channel_Error,
			  "IPC_SmSendBuffer",
			  "Trying to send after CP has crashed for Buffer %08X",
			  Buffer, 0, 0, 0);
		return;
	}
#endif

	DestinationEpPtr = IPC_SmEndpointInfo(DestinationEpId);
	DestinationCpu = DestinationEpPtr->Cpu;

	IPC_TRACE(IPC_Channel_Sm,
		  "IPC_SmSendBuffer",
		  "DestinationCpu %02X, Buffer %08X",
		  DestinationCpu, Buffer, 0, 0);

	if (DestinationCpu == IPC_SM_CURRENT_CPU) {
		(*DestinationEpPtr->DeliveryFunction) (Buffer);
	} else {
		IPC_Fifo SendFifo =
		    &SmLocalControl.SmControl->
		    Fifos[IPC_CPU_ID_INDEX(DestinationCpu)].SendFifo;
		IPC_SmFifoWrite(SendFifo, Buffer);
	}
}
コード例 #3
0
void IPC_ReportFlowControlEvent(IPC_BufferPool_T *PoolPtr,
				IPC_FlowCtrlEvent_T Event)
{
	IPC_FlowCtrlEvent_T ReportedFlowControlState;
	IPC_Endpoint SourceEp = IPC_SmEndpointInfo(PoolPtr->SourceEndpointId);
	IPC_BufferPool Pool = IPC_SmOffset(PoolPtr);

	CRITICAL_REIGON_SETUP if (!SourceEp->FlowControlFunction) {
		/* No Flow Control callback defined */
		PoolPtr->FlowControlCallPending = IPC_FALSE;
		return;
	}

	CRITICAL_REIGON_ENTER if (Event != PoolPtr->FlowControlState) {
		/* State has already changed back - do not report change */
		PoolPtr->FlowControlCallPending = IPC_FALSE;
		CRITICAL_REIGON_LEAVE return;
	}
コード例 #4
0
//**************************************************
IPC_BufferPool IPC_CreateBufferPoolWithDescriptor
(
	IPC_EndpointId_T		SourceEndpointId,
	IPC_EndpointId_T		DestinationEndpointId,
	IPC_U32					NumberOfBuffers,
	IPC_U32					BufferSize,
	IPC_U32					FlowStartLimit,
	IPC_U32					FlowStopLimit,
	IPC_U32					LocalDescriptorSize
)
{
	IPC_U32				MaxDataSize		= ALIGN4 (BufferSize);
	IPC_BufferPool		Pool;
	IPC_BufferPool_T *	PoolPtr;
	IPC_Endpoint		DestinationEpPtr;
	IPC_SmPtr			Buffer;
	IPC_U32				Id;
	char *				LocalData;

	IPC_TRACE (IPC_Channel_Pool, "IPC_CreateBufferPool",
				"Source %02X, Destination %02X, Buffer Count %d, Buffer Size %d",
				SourceEndpointId, DestinationEndpointId, NumberOfBuffers, BufferSize);

	// Sanity Checks
	if (NumberOfBuffers == 0)
	{
		IPC_TRACE (IPC_Channel_Error, "IPC_CreateBufferPool", "Invalid NumberOfBuffers %d", NumberOfBuffers, 0, 0, 0);
		return 0;
	}

	if (!IPC_SmEndpointInfo (SourceEndpointId))
	{
		IPC_TRACE (IPC_Channel_Error, "IPC_CreateBufferPool", "Invalid Source Endpoint %d", SourceEndpointId, 0, 0, 0);
		return 0;
	}

	if (0 == (DestinationEpPtr = IPC_SmEndpointInfo (DestinationEndpointId)))
	{
		IPC_TRACE (IPC_Channel_Error, "IPC_CreateBufferPool", "Invalid Destination Endpoint %d", DestinationEndpointId, 0, 0, 0);
		return 0;
	}

	if (FlowStartLimit > NumberOfBuffers)
	{
		IPC_TRACE (IPC_Channel_Error, "IPC_CreateBufferPool", "Invalid FlowStartLimit %d", FlowStartLimit, 0, 0, 0);
		return 0;
	}

	if (FlowStopLimit >= NumberOfBuffers)
	{
		IPC_TRACE (IPC_Channel_Error, "IPC_CreateBufferPool", "Invalid FlowStopLimit %d", FlowStopLimit, 0, 0, 0);
		return 0;
	}

	// Allocate Sm For Pool
	Pool = IPC_SmPoolAlloc (sizeof (IPC_BufferPool_T), DestinationEpPtr->MaxHeaderSize, MaxDataSize, NumberOfBuffers);

	if (!Pool)
	{
		IPC_TRACE (IPC_Channel_Error, "IPC_CreateBufferPool", "IPC_SmPoolAlloc Failed", 0, 0, 0, 0);
		return 0;
	}

	if (LocalDescriptorSize != 0)
	{
#ifdef UNDER_LINUX
        // Use kmalloc instead of OSHEAP_Alloc in Linux platform
		LocalData = kmalloc ((LocalDescriptorSize * NumberOfBuffers), GFP_KERNEL);
#else
		LocalData = (char *) OSHEAP_Alloc (LocalDescriptorSize * NumberOfBuffers);
#endif  // UNDER_LINUX

		if (!LocalData)
		{
			IPC_TRACE (IPC_Channel_Error, "IPC_CreateBufferPool", "LocalData OSHEAP_Alloc Failed", 0, 0, 0, 0);
			return 0;
		}
	} else {
		LocalData = 0;
	}

	// Initialise Pool
	PoolPtr	= IPC_PoolPtr(Pool);

	PoolPtr->Cpu					= IPC_SM_CURRENT_CPU;
	PoolPtr->SourceEndpointId		= SourceEndpointId;
	PoolPtr->DestinationEndpointId	= DestinationEndpointId;
	PoolPtr->MaxDataSize			= MaxDataSize;
	PoolPtr->MaxHeaderSize			= DestinationEpPtr->MaxHeaderSize;
	PoolPtr->FlowStartLimit			= FlowStartLimit;
	PoolPtr->FlowStopLimit			= FlowStopLimit;
	PoolPtr->FlowControlState		= IPC_FLOW_START;
	PoolPtr->FlowControlCallPending	= IPC_FALSE;
	PoolPtr->FreeBuffers			= NumberOfBuffers;
	PoolPtr->MaxBuffers				= NumberOfBuffers;
	PoolPtr->LowWaterMark			= NumberOfBuffers;
	PoolPtr->NextPool				= 0;
	PoolPtr->BufferFreeFunction		= NULL;
	PoolPtr->AllocationFailures		= 0;
	PoolPtr->Allocations			= 0;
	PoolPtr->BytesSent				= 0;
	PoolPtr->FlowStopCalls			= 0;
	PoolPtr->FlowStartCalls			= 0;

	PoolPtr->EmptyEvent				= IPC_EVENT_CREATE;

	IPC_QInitialise			(IPC_SmOffset(&PoolPtr->FreeBufferQ), Pool);
	IPC_QInitialise			(IPC_SmOffset(&PoolPtr->AllocatedBufferQ), Pool);



	// Initialise Buffers in pool
	Buffer = Pool + sizeof (IPC_BufferPool_T);

	for (Id = 0; Id < NumberOfBuffers; Id++)
	{
		IPC_BufferToPtr (Buffer)->LocalData = LocalData;

		LocalData += LocalDescriptorSize;

		IPC_QAddBack (Buffer, IPC_POOLFreeQ(Pool));
		Buffer = IPC_BufferInitialise (Pool, Buffer, Id, PoolPtr->MaxHeaderSize, MaxDataSize);

	}

	// For Debug
	{
		IPC_PoolList_T * EpPools = &PoolList [PoolPtr->SourceEndpointId];

		if (EpPools->Count < IPC_POOLLIST_LENGTH)
		{
			EpPools->Pool [EpPools->Count++] = PoolPtr;
		}
	}

	IPC_TRACE (IPC_Channel_Pool, "IPC_CreateBufferPool", "Pool %08X", Pool, 0, 0, 0);

	return Pool;
}
コード例 #5
0
void IPC_ReportFlowControlEvent(IPC_BufferPool_T *PoolPtr,
				IPC_FlowCtrlEvent_T Event)
{
	IPC_FlowCtrlEvent_T ReportedFlowControlState;
	IPC_Endpoint SourceEp = IPC_SmEndpointInfo(PoolPtr->SourceEndpointId);
	IPC_BufferPool Pool = IPC_SmOffset(PoolPtr);

	CRITICAL_REIGON_SETUP if (!SourceEp->FlowControlFunction) {
		/* No Flow Control callback defined */
		PoolPtr->FlowControlCallPending = IPC_FALSE;
		return;
	}

	CRITICAL_REIGON_ENTER(PoolPtr->Lock);

	if (Event != PoolPtr->FlowControlState) {
		/* State has already changed back - do not report change */
		PoolPtr->FlowControlCallPending = IPC_FALSE;
		CRITICAL_REIGON_LEAVE(PoolPtr->Lock);
		return;
	}
	CRITICAL_REIGON_LEAVE(PoolPtr->Lock);

	ReportedFlowControlState = Event;

	while (1) {
		/* Update Statistics */
		switch (ReportedFlowControlState) {
		case IPC_FLOW_START:
			PoolPtr->FlowStartCalls++;
			break;

		case IPC_FLOW_STOP:
			PoolPtr->FlowStopCalls++;
			break;

		default:
			/* Something badly wrong */
			break;
		}

#ifndef UNDER_LINUX
		if (PoolPtr->DestinationEndpointId != IPC_EP_LogApps) {
			IPC_TRACE(IPC_Channel_FlowControl,
				  "IPC_ReportFlowControlEvent",
				  "Pool %08X, Function %08X, FlowEvent %01d, ReportedEvent %01d",
				  Pool, SourceEp->FlowControlFunction, Event,
				  ReportedFlowControlState);
		}
#endif

#ifndef UNDER_LINUX
		(*SourceEp->FlowControlFunction) (Pool,
						  ReportedFlowControlState);
		CRITICAL_REIGON_ENTER(PoolPtr->Lock);
#else
		/*
		   Linux Issue:
		   ==> Before PoolPtr->FlowControlCallPending is set to FALSE,
		   the cbk ( IPC_FLOW_START ) will trigger Net IRQ calling
		   IPC_AllocateBufferWait()
		   ==> Now the buffer count is zero but the
		   IPC_AllocateBuffer() does not report IPC_FLOW_STOP since the
		   PoolPtr->FlowControlCallPending is still TRUE
		   ==> The Net IRQ calls IPC_AllocateBufferWait() again
		   (since IPC_FLOW_STOP was not sent ) and caz of no buffer,
		   it will try to Wait on Event
		   ==> Waiting on event is not permitted in Net IRQ and
		   results in crash.

		   Solution:
		   ==> Enter Critical region before calling cbk(IPC_FLOW_START).
		   The critical region disables Net IRQ
		   ==> PoolPtr->FlowControlCallPending is set to FALSE and then
		   the Critical region exits which then triggers Net IRQ.
		 */
		CRITICAL_REIGON_ENTER(PoolPtr->Lock);
		(*SourceEp->FlowControlFunction) (Pool,
						  ReportedFlowControlState);
#endif

		if (ReportedFlowControlState == PoolPtr->FlowControlState) {
			PoolPtr->FlowControlCallPending = IPC_FALSE;
			CRITICAL_REIGON_LEAVE(PoolPtr->Lock);
			return;
		}

		ReportedFlowControlState = PoolPtr->FlowControlState;

		CRITICAL_REIGON_LEAVE(PoolPtr->Lock);
	}
}
コード例 #6
0
void IPC_ProcessEvents(void)
{
	IPC_Buffer Buffer;
	IPC_CPU_ID_T Cpu = IPC_SM_CURRENT_CPU;

	IPC_TRACE(IPC_Channel_Hisr, "IPC_ProcessEvents", "CPU %02X", Cpu, 0, 0,
		  0);

	if (!SmLocalControl.ConfiguredReported) {

		if ((SmLocalControl.SmControl->
		     Initialised[IPC_CPU_ID_INDEX(Cpu)] == IPC_SmConfigured)
		    && (SmLocalControl.SmControl->
			Initialised[IPC_CPU_ID_INDEX(IPC_OTHER_CPU[Cpu])] ==
			IPC_SmConfigured)) {
			SmLocalControl.ConfiguredReported = IPC_TRUE;
			(*SmLocalControl.IPCInitialisedFunction) ();
		} else {
			IPC_TRACE(IPC_Channel_Error, "IPC_ProcessEvents",
				  "CPU %02X, Not Initialised", Cpu, 0, 0, 0);
			return;
		}
	}
#ifdef FUSE_IPC_CRASH_SUPPORT
	if ((Cpu == IPC_AP_CPU) && (g_bCpCrashed == IPC_FALSE)
	    && (SmLocalControl.SmControl->CrashCode != IPC_CP_NOT_CRASHED)) {
		/* CP has crashed so set the crash status */
		g_bCpCrashed = IPC_TRUE;

		/**
		 * CP should be analysing crach here as this is the first
		 * indication - but call crash function in case finished.
		 */
		if (SmLocalControl.IPCCPCrashed)
			SmLocalControl.IPCCPCrashed(SmLocalControl.SmControl->
						    CrashCode);

	}

	if (g_bCpCrashed == IPC_TRUE) {
		if ((SmLocalControl.SmControl->CrashCode !=
		     IPC_CP_ANALYSING_CRASH)
		    && (SmLocalControl.SmControl->CrashCode !=
			IPC_CP_NOT_CRASHED)) {

			/**
			 * if CP is not analysing any more than we should
			 * have crash dump now
			 *
			 * call the function to handle the crash dump
			 */
			if (SmLocalControl.IPCCPCrashed)
				SmLocalControl.IPCCPCrashed(SmLocalControl.
							    SmControl->
							    CrashCode);
			/**
			 * This function can call  IPCAP_GetCrashData to get
			 * crash location.
			 */
		} else {
			g_bCpCrashed = IPC_FALSE;
		}
	} else
#endif /* FUSE_IPC_CRASH_SUPPORT */
	{
		{
			IPC_Fifo SendFifo = SmLocalControl.SendFifo;

			while (0 != (Buffer = IPC_SmFifoRead(SendFifo))) {
				IPC_EndpointId_T DestinationEpId =
				    IPC_PoolDestinationEndpointId
				    (IPC_BufferOwningPool(Buffer));
				IPC_Endpoint DestinationEpPtr =
				    IPC_SmEndpointInfo(DestinationEpId);

#ifdef IPC_DEBUG
				if (DestinationEpPtr
				    && DestinationEpPtr->DeliveryFunction
				    && DestinationEpPtr->Cpu ==
				    IPC_SM_CURRENT_CPU) {
					IPC_TRACE(IPC_Channel_Hisr,
						  "IPC_ProcessEvents",
						  "Buffer %08X, size %d, EP %d, Fn %08X",
						  Buffer,
						  IPC_BufferDataSize(Buffer),
						  DestinationEpId,
						  (IPC_U32) DestinationEpPtr->
						  DeliveryFunction);

					(DestinationEpPtr->
					 DeliveryFunction) (Buffer);

				} else {
					IPC_TRACE(IPC_Channel_Error,
						  "IPC_ProcessEvents",
						  "No Delivery Function for EP %d, Function %08X, CpuId %d",
						  DestinationEpId,
						  (IPC_U32) DestinationEpPtr->
						  DeliveryFunction,
						  DestinationEpPtr->Cpu, 0);

					IPC_FreeBuffer(Buffer);
				}
#else
				(DestinationEpPtr->DeliveryFunction) (Buffer);
#endif
			}
		}
		{

			IPC_Fifo FreeFifo = SmLocalControl.FreeFifo;
			while (0 != (Buffer = IPC_SmFifoRead(FreeFifo))) {
				IPC_BufferReturn(Buffer,
						 IPC_BufferOwningPool(Buffer));
			}
		}
	}
}