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); }
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); }
/* Write to the ring buffer */ nextWriteLocation = GetNextWriteLocation(OutRingInfo); for_each_sg(sglist, sg, sgcount, i) { nextWriteLocation = CopyToRingBuffer(OutRingInfo, nextWriteLocation, sg_virt(sg), sg->length); } /* Set previous packet start */ prevIndices = GetRingBufferIndices(OutRingInfo); nextWriteLocation = CopyToRingBuffer(OutRingInfo, nextWriteLocation, &prevIndices, sizeof(u64)); /* Make sure we flush all writes before updating the writeIndex */ mb(); /* Now, update the write location */ SetNextWriteLocation(OutRingInfo, nextWriteLocation); /* DumpRingInfo(OutRingInfo, "AFTER "); */ spin_unlock_irqrestore(&OutRingInfo->ring_lock, flags); DPRINT_EXIT(VMBUS); return 0;
/*++ 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; }