Ejemplo n.º 1
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);
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
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;
}