示例#1
0
int RingBufferWrite(RING_BUFFER_INFO *OutRingInfo,
		    struct scatterlist *sglist, u32 sgcount)
{
	int i = 0;
	u32 byteAvailToWrite;
	u32 byteAvailToRead;
	u32 totalBytesToWrite = 0;

	struct scatterlist *sg;
	volatile u32 nextWriteLocation;
	u64 prevIndices = 0;
	unsigned long flags;

	DPRINT_ENTER(VMBUS);

	for_each_sg(sglist, sg, sgcount, i)
	{
		totalBytesToWrite += sg->length;
	}

	totalBytesToWrite += sizeof(u64);

	spin_lock_irqsave(&OutRingInfo->ring_lock, flags);

	GetRingBufferAvailBytes(OutRingInfo,
				&byteAvailToRead,
				&byteAvailToWrite);

	DPRINT_DBG(VMBUS, "Writing %u bytes...", totalBytesToWrite);

	/* DumpRingInfo(OutRingInfo, "BEFORE "); */

	/* If there is only room for the packet, assume it is full. */
	/* Otherwise, the next time around, we think the ring buffer */
	/* is empty since the read index == write index */
	if (byteAvailToWrite <= totalBytesToWrite) {
		DPRINT_DBG(VMBUS,
			"No more space left on outbound ring buffer "
			"(needed %u, avail %u)",
			totalBytesToWrite,
			byteAvailToWrite);

		spin_unlock_irqrestore(&OutRingInfo->ring_lock, flags);

		DPRINT_EXIT(VMBUS);

		return -1;
	}

	/* Write to the ring buffer */
	nextWriteLocation = GetNextWriteLocation(OutRingInfo);

	for_each_sg(sglist, sg, sgcount, i)
	{
		nextWriteLocation = CopyToRingBuffer(OutRingInfo,
						     nextWriteLocation,
						     sg_virt(sg),
						     sg->length);
	}
/*++

Name: 
	RingBufferRead()

Description:
	Read and advance the read index

--*/
int
RingBufferRead(
	RING_BUFFER_INFO*	InRingInfo,
	PVOID				Buffer,
	UINT32				BufferLen,
	UINT32				Offset
	)
{
	UINT32 bytesAvailToWrite;
	UINT32 bytesAvailToRead;
	UINT32 nextReadLocation=0;
	UINT64 prevIndices=0;

	ASSERT(BufferLen > 0);
	
	SpinlockAcquire(InRingInfo->RingLock);

	GetRingBufferAvailBytes(InRingInfo, &bytesAvailToRead, &bytesAvailToWrite);

	DPRINT_DBG(VMBUS, "Reading %u bytes...", BufferLen);

	//DumpRingInfo(InRingInfo, "BEFORE ");

	// Make sure there is something to read
	if (bytesAvailToRead < BufferLen )
	{
		DPRINT_DBG(VMBUS, "got callback but not enough to read <avail to read %d read size %d>!!", bytesAvailToRead, BufferLen);

		SpinlockRelease(InRingInfo->RingLock);

		return -1;
	}

	nextReadLocation = GetNextReadLocationWithOffset(InRingInfo, Offset);

	nextReadLocation = CopyFromRingBuffer(InRingInfo,
											Buffer,
											BufferLen,
											nextReadLocation);

	nextReadLocation = CopyFromRingBuffer(InRingInfo,
											&prevIndices,
											sizeof(UINT64),
											nextReadLocation);

	// Make sure all reads are done before we update the read index since 
	// the writer may start writing to the read area once the read index is updated
	MemoryFence();

	// Update the read index
	SetNextReadLocation(InRingInfo, nextReadLocation);
	
	//DumpRingInfo(InRingInfo, "AFTER ");

	SpinlockRelease(InRingInfo->RingLock);

	return 0;
}
示例#3
0
int RingBufferWrite(RING_BUFFER_INFO *OutRingInfo,
		    struct scatterlist *sglist, u32 sgcount)
{
	int i=0;
	u32 byteAvailToWrite;
	u32 byteAvailToRead;
	u32 totalBytesToWrite=0;

	struct scatterlist *sg;
	volatile u32 nextWriteLocation;
	u64 prevIndices=0;
	unsigned long flags;

	DPRINT_ENTER(VMBUS);

	for_each_sg(sglist, sg, sgcount, i)
	{
		totalBytesToWrite += sg->length;
	}

	totalBytesToWrite += sizeof(u64);

	spin_lock_irqsave(&OutRingInfo->ring_lock, flags);

	GetRingBufferAvailBytes(OutRingInfo, &byteAvailToRead, &byteAvailToWrite);

	DPRINT_DBG(VMBUS, "Writing %u bytes...", totalBytesToWrite);

	

	
	
	if (byteAvailToWrite <= totalBytesToWrite)
	{
		DPRINT_DBG(VMBUS, "No more space left on outbound ring buffer (needed %u, avail %u)", totalBytesToWrite, byteAvailToWrite);

		spin_unlock_irqrestore(&OutRingInfo->ring_lock, flags);

		DPRINT_EXIT(VMBUS);

		return -1;
	}

	
	nextWriteLocation = GetNextWriteLocation(OutRingInfo);

	for_each_sg(sglist, sg, sgcount, i)
	{
		nextWriteLocation = CopyToRingBuffer(OutRingInfo,
						     nextWriteLocation,
						     sg_virt(sg),
						     sg->length);
	}
示例#4
0
/*++

Name:
	DumpRingInfo()

Description:
	Dump out to console the ring buffer info

--*/
void DumpRingInfo(RING_BUFFER_INFO *RingInfo, char *Prefix)
{
	u32 bytesAvailToWrite;
	u32 bytesAvailToRead;

	GetRingBufferAvailBytes(RingInfo, &bytesAvailToRead, &bytesAvailToWrite);

	DPRINT(VMBUS, DEBUG_RING_LVL, "%s <<ringinfo %p buffer %p avail write %u avail read %u read idx %u write idx %u>>",
		Prefix,
		RingInfo,
		RingInfo->RingBuffer->Buffer,
		bytesAvailToWrite,
		bytesAvailToRead,
		RingInfo->RingBuffer->ReadIndex,
		RingInfo->RingBuffer->WriteIndex);
}
示例#5
0
/*++

Name:
	RingBufferGetDebugInfo()

Description:
	Get various debug metrics for the specified ring buffer

--*/
void RingBufferGetDebugInfo(RING_BUFFER_INFO *RingInfo,
			    RING_BUFFER_DEBUG_INFO *DebugInfo)
{
	u32 bytesAvailToWrite;
	u32 bytesAvailToRead;

	if (RingInfo->RingBuffer)
	{
		GetRingBufferAvailBytes(RingInfo, &bytesAvailToRead, &bytesAvailToWrite);

		DebugInfo->BytesAvailToRead = bytesAvailToRead;
		DebugInfo->BytesAvailToWrite = bytesAvailToWrite;
		DebugInfo->CurrentReadIndex = RingInfo->RingBuffer->ReadIndex;
		DebugInfo->CurrentWriteIndex = RingInfo->RingBuffer->WriteIndex;

		DebugInfo->CurrentInterruptMask = RingInfo->RingBuffer->InterruptMask;
	}
}
示例#6
0
/*++

Name:
	RingBufferGetDebugInfo()

Description:
	Get various debug metrics for the specified ring buffer

--*/
void RingBufferGetDebugInfo(struct hv_ring_buffer_info *RingInfo,
			    struct hv_ring_buffer_debug_info *debug_info)
{
	u32 bytesAvailToWrite;
	u32 bytesAvailToRead;

	if (RingInfo->RingBuffer) {
		GetRingBufferAvailBytes(RingInfo,
					&bytesAvailToRead,
					&bytesAvailToWrite);

		debug_info->BytesAvailToRead = bytesAvailToRead;
		debug_info->BytesAvailToWrite = bytesAvailToWrite;
		debug_info->CurrentReadIndex = RingInfo->RingBuffer->ReadIndex;
		debug_info->CurrentWriteIndex = RingInfo->RingBuffer->WriteIndex;
		debug_info->CurrentInterruptMask = RingInfo->RingBuffer->InterruptMask;
	}
}
/*++

Name: 
	RingBufferPeek()

Description:
	Read without advancing the read index

--*/
int
RingBufferPeek(
	RING_BUFFER_INFO*	InRingInfo,
	void*				Buffer,
	UINT32				BufferLen
	)
{
	UINT32 bytesAvailToWrite;
	UINT32 bytesAvailToRead;
	UINT32 nextReadLocation=0;

	SpinlockAcquire(InRingInfo->RingLock);

	GetRingBufferAvailBytes(InRingInfo, &bytesAvailToRead, &bytesAvailToWrite);

	// Make sure there is something to read
	if (bytesAvailToRead < BufferLen )
	{
		//DPRINT_DBG(VMBUS, "got callback but not enough to read <avail to read %d read size %d>!!", bytesAvailToRead, BufferLen);

		SpinlockRelease(InRingInfo->RingLock);

		return -1;
	}

	// Convert to byte offset
	nextReadLocation = GetNextReadLocation(InRingInfo);

	nextReadLocation = CopyFromRingBuffer(InRingInfo,
											Buffer,
											BufferLen,
											nextReadLocation);

	SpinlockRelease(InRingInfo->RingLock);

	return 0;
}
int 
RingBufferCheck(RING_BUFFER_INFO *rbi)
{
#if 1
	UINT32 ri, wi, len;

	// Capture the read/write indices before they changed
        ri = rbi->RingBuffer->ReadIndex;
        wi = rbi->RingBuffer->WriteIndex;

	len = (ri <= wi) ? (wi - ri) : (rbi->RingDataSize - (ri - wi));

	if (len < sizeof(VMPACKET_DESCRIPTOR))
		return 0;

	_PREFETCHT0(rbi->RingBuffer->Buffer + ri);
#if 0
	if (ri <= wi) {
		/* no wrap */
		while (len > 0) {
			_PREFETCHT0(rbi->RingBuffer->Buffer + ri);
			len -= 128;
			ri += 128;
		}
	} else {
		/* wrap */
		while (ri < rbi->RingDataSize) {
			_PREFETCHT0(rbi->RingBuffer->Buffer + ri);
			len -= 128;
			ri += 128;
		}
		ri = 0;
		while (len > 0) {
			_PREFETCHT0(rbi->RingBuffer->Buffer + ri);
			len -= 128;
			ri += 128;
		}
	}
#endif

	return 1;


#else
	UINT32 toRead = 0;
	UINT32 toWrite;
	UINT32 addr;
	int i;

	GetRingBufferAvailBytes(rbi, &toRead, &toWrite);

	if (toRead < sizeof(VMPACKET_DESCRIPTOR))
		return 0;
	else {
		r = rbi->Ringbuffer;
		rdindx =  r->ReadIndex;

		addr = r->Buffer + rdindx;
		toRead += (addr & 0x~07f);
		addr &= ~0x7f;

		if (toRead > r->size - rdindx) {
			end = buf + size;
			for(;addr < end; ) {
				_PREFETCHT0(addr & ~0x7f);
				addr += 128;
				
			}
		} else {
			_PREFETCH0(addr & ~0x7f);
		}
		return 1;
	}
#endif

}
/*++

Name: 
	RingBufferWrite()

Description:
	Write to the ring buffer

--*/
int
RingBufferWrite(
	RING_BUFFER_INFO*	OutRingInfo,
	SG_BUFFER_LIST		SgBuffers[],
	UINT32				SgBufferCount
	)
{
	int i=0;
	UINT32 byteAvailToWrite;
	UINT32 byteAvailToRead;
	UINT32 totalBytesToWrite=0;

	volatile UINT32 nextWriteLocation;
	UINT64 prevIndices=0;

	DPRINT_ENTER(VMBUS);

	for (i=0; i < SgBufferCount; i++)
	{
		totalBytesToWrite += SgBuffers[i].Length;
	}

	totalBytesToWrite += sizeof(UINT64);

	SpinlockAcquire(OutRingInfo->RingLock);

	GetRingBufferAvailBytes(OutRingInfo, &byteAvailToRead, &byteAvailToWrite);
	
	DPRINT_DBG(VMBUS, "Writing %u bytes...", totalBytesToWrite);

	//DumpRingInfo(OutRingInfo, "BEFORE ");
	
	// If there is only room for the packet, assume it is full. Otherwise, the next time around, we think the ring buffer
	// is empty since the read index == write index
	if (byteAvailToWrite <= totalBytesToWrite)
	{
		DPRINT_DBG(VMBUS, "No more space left on outbound ring buffer (needed %u, avail %u)", totalBytesToWrite, byteAvailToWrite);

		SpinlockRelease(OutRingInfo->RingLock);

		DPRINT_EXIT(VMBUS);

		return -1;
	}

	// Write to the ring buffer
	nextWriteLocation = GetNextWriteLocation(OutRingInfo);

	for (i=0; i < SgBufferCount; i++)
	{
		 nextWriteLocation = CopyToRingBuffer(OutRingInfo,
												nextWriteLocation,
												SgBuffers[i].Data,
												SgBuffers[i].Length);
	}

	// Set previous packet start
	prevIndices = GetRingBufferIndices(OutRingInfo);

	nextWriteLocation = CopyToRingBuffer(OutRingInfo,
												nextWriteLocation,
												&prevIndices,
												sizeof(UINT64));

	// Make sure we flush all writes before updating the writeIndex
	MemoryFence();

	// Now, update the write location
	SetNextWriteLocation(OutRingInfo, nextWriteLocation);

	//DumpRingInfo(OutRingInfo, "AFTER ");

	SpinlockRelease(OutRingInfo->RingLock);
		
	DPRINT_EXIT(VMBUS);

	return 0;
}