blob: f7332f300c4555df34f0523a763e8e65fee3d1d8 [file] [log] [blame]
Hank Janssen3e7ee492009-07-13 16:02:34 -07001/*
2 *
3 * Copyright (c) 2009, Microsoft Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16 * Place - Suite 330, Boston, MA 02111-1307 USA.
17 *
18 * Authors:
19 * Haiyang Zhang <haiyangz@microsoft.com>
20 * Hank Janssen <hjanssen@microsoft.com>
21 *
22 */
23
Greg Kroah-Hartmana0086dc2009-08-17 17:22:08 -070024#include <linux/kernel.h>
25#include <linux/mm.h>
Greg Kroah-Hartman09d50ff2009-07-13 17:09:34 -070026#include "include/logging.h"
Hank Janssen3e7ee492009-07-13 16:02:34 -070027#include "RingBuffer.h"
28
Hank Janssen3e7ee492009-07-13 16:02:34 -070029
Bill Pemberton454f18a2009-07-27 16:47:24 -040030/* #defines */
31
32
33/* Amount of space to write to */
Hank Janssen3e7ee492009-07-13 16:02:34 -070034#define BYTES_AVAIL_TO_WRITE(r, w, z) ((w) >= (r))?((z) - ((w) - (r))):((r) - (w))
35
36
37/*++
38
39Name:
40 GetRingBufferAvailBytes()
41
42Description:
43 Get number of bytes available to read and to write to
44 for the specified ring buffer
45
46--*/
47static inline void
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -070048GetRingBufferAvailBytes(RING_BUFFER_INFO *rbi, u32 *read, u32 *write)
Hank Janssen3e7ee492009-07-13 16:02:34 -070049{
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -070050 u32 read_loc,write_loc;
Hank Janssen3e7ee492009-07-13 16:02:34 -070051
Bill Pemberton454f18a2009-07-27 16:47:24 -040052 /* Capture the read/write indices before they changed */
Hank Janssen3e7ee492009-07-13 16:02:34 -070053 read_loc = rbi->RingBuffer->ReadIndex;
54 write_loc = rbi->RingBuffer->WriteIndex;
55
56 *write = BYTES_AVAIL_TO_WRITE(read_loc, write_loc, rbi->RingDataSize);
57 *read = rbi->RingDataSize - *write;
58}
59
60/*++
61
62Name:
63 GetNextWriteLocation()
64
65Description:
66 Get the next write location for the specified ring buffer
67
68--*/
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -070069static inline u32
Hank Janssen3e7ee492009-07-13 16:02:34 -070070GetNextWriteLocation(RING_BUFFER_INFO* RingInfo)
71{
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -070072 u32 next = RingInfo->RingBuffer->WriteIndex;
Hank Janssen3e7ee492009-07-13 16:02:34 -070073
74 ASSERT(next < RingInfo->RingDataSize);
75
76 return next;
77}
78
79/*++
80
81Name:
82 SetNextWriteLocation()
83
84Description:
85 Set the next write location for the specified ring buffer
86
87--*/
88static inline void
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -070089SetNextWriteLocation(RING_BUFFER_INFO* RingInfo, u32 NextWriteLocation)
Hank Janssen3e7ee492009-07-13 16:02:34 -070090{
91 RingInfo->RingBuffer->WriteIndex = NextWriteLocation;
92}
93
94/*++
95
96Name:
97 GetNextReadLocation()
98
99Description:
100 Get the next read location for the specified ring buffer
101
102--*/
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700103static inline u32
Hank Janssen3e7ee492009-07-13 16:02:34 -0700104GetNextReadLocation(RING_BUFFER_INFO* RingInfo)
105{
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700106 u32 next = RingInfo->RingBuffer->ReadIndex;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700107
108 ASSERT(next < RingInfo->RingDataSize);
109
110 return next;
111}
112
113/*++
114
115Name:
116 GetNextReadLocationWithOffset()
117
118Description:
119 Get the next read location + offset for the specified ring buffer.
120 This allows the caller to skip
121
122--*/
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700123static inline u32
124GetNextReadLocationWithOffset(RING_BUFFER_INFO* RingInfo, u32 Offset)
Hank Janssen3e7ee492009-07-13 16:02:34 -0700125{
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700126 u32 next = RingInfo->RingBuffer->ReadIndex;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700127
128 ASSERT(next < RingInfo->RingDataSize);
129 next += Offset;
130 next %= RingInfo->RingDataSize;
131
132 return next;
133}
134
135/*++
136
137Name:
138 SetNextReadLocation()
139
140Description:
141 Set the next read location for the specified ring buffer
142
143--*/
144static inline void
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700145SetNextReadLocation(RING_BUFFER_INFO* RingInfo, u32 NextReadLocation)
Hank Janssen3e7ee492009-07-13 16:02:34 -0700146{
147 RingInfo->RingBuffer->ReadIndex = NextReadLocation;
148}
149
150
151/*++
152
153Name:
154 GetRingBuffer()
155
156Description:
157 Get the start of the ring buffer
158
159--*/
Greg Kroah-Hartman8282c402009-07-14 15:06:28 -0700160static inline void *
Hank Janssen3e7ee492009-07-13 16:02:34 -0700161GetRingBuffer(RING_BUFFER_INFO* RingInfo)
162{
Greg Kroah-Hartman8282c402009-07-14 15:06:28 -0700163 return (void *)RingInfo->RingBuffer->Buffer;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700164}
165
166
167/*++
168
169Name:
170 GetRingBufferSize()
171
172Description:
173 Get the size of the ring buffer
174
175--*/
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700176static inline u32
Hank Janssen3e7ee492009-07-13 16:02:34 -0700177GetRingBufferSize(RING_BUFFER_INFO* RingInfo)
178{
179 return RingInfo->RingDataSize;
180}
181
182/*++
183
184Name:
185 GetRingBufferIndices()
186
187Description:
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700188 Get the read and write indices as u64 of the specified ring buffer
Hank Janssen3e7ee492009-07-13 16:02:34 -0700189
190--*/
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700191static inline u64
Hank Janssen3e7ee492009-07-13 16:02:34 -0700192GetRingBufferIndices(RING_BUFFER_INFO* RingInfo)
193{
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700194 return ((u64)RingInfo->RingBuffer->WriteIndex << 32) || RingInfo->RingBuffer->ReadIndex;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700195}
196
197
198/*++
199
200Name:
201 DumpRingInfo()
202
203Description:
204 Dump out to console the ring buffer info
205
206--*/
Greg Kroah-Hartman3523a802009-08-17 17:22:08 -0700207void DumpRingInfo(RING_BUFFER_INFO *RingInfo, char *Prefix)
Hank Janssen3e7ee492009-07-13 16:02:34 -0700208{
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700209 u32 bytesAvailToWrite;
210 u32 bytesAvailToRead;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700211
212 GetRingBufferAvailBytes(RingInfo, &bytesAvailToRead, &bytesAvailToWrite);
213
214 DPRINT(VMBUS, DEBUG_RING_LVL, "%s <<ringinfo %p buffer %p avail write %u avail read %u read idx %u write idx %u>>",
215 Prefix,
216 RingInfo,
217 RingInfo->RingBuffer->Buffer,
218 bytesAvailToWrite,
219 bytesAvailToRead,
220 RingInfo->RingBuffer->ReadIndex,
221 RingInfo->RingBuffer->WriteIndex);
222}
223
Bill Pemberton454f18a2009-07-27 16:47:24 -0400224
225/* Internal routines */
226
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700227static u32
Hank Janssen3e7ee492009-07-13 16:02:34 -0700228CopyToRingBuffer(
229 RING_BUFFER_INFO *RingInfo,
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700230 u32 StartWriteOffset,
Greg Kroah-Hartman8282c402009-07-14 15:06:28 -0700231 void * Src,
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700232 u32 SrcLen);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700233
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700234static u32
Hank Janssen3e7ee492009-07-13 16:02:34 -0700235CopyFromRingBuffer(
236 RING_BUFFER_INFO *RingInfo,
Greg Kroah-Hartman8282c402009-07-14 15:06:28 -0700237 void * Dest,
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700238 u32 DestLen,
239 u32 StartReadOffset);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700240
241
242
243/*++
244
245Name:
246 RingBufferGetDebugInfo()
247
248Description:
249 Get various debug metrics for the specified ring buffer
250
251--*/
Greg Kroah-Hartman3523a802009-08-17 17:22:08 -0700252void RingBufferGetDebugInfo(RING_BUFFER_INFO *RingInfo,
253 RING_BUFFER_DEBUG_INFO *DebugInfo)
Hank Janssen3e7ee492009-07-13 16:02:34 -0700254{
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700255 u32 bytesAvailToWrite;
256 u32 bytesAvailToRead;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700257
258 if (RingInfo->RingBuffer)
259 {
260 GetRingBufferAvailBytes(RingInfo, &bytesAvailToRead, &bytesAvailToWrite);
261
262 DebugInfo->BytesAvailToRead = bytesAvailToRead;
263 DebugInfo->BytesAvailToWrite = bytesAvailToWrite;
264 DebugInfo->CurrentReadIndex = RingInfo->RingBuffer->ReadIndex;
265 DebugInfo->CurrentWriteIndex = RingInfo->RingBuffer->WriteIndex;
266
267 DebugInfo->CurrentInterruptMask = RingInfo->RingBuffer->InterruptMask;
268 }
269}
270
271
272/*++
273
274Name:
275 GetRingBufferInterruptMask()
276
277Description:
278 Get the interrupt mask for the specified ring buffer
279
280--*/
Greg Kroah-Hartman3523a802009-08-17 17:22:08 -0700281u32 GetRingBufferInterruptMask(RING_BUFFER_INFO *rbi)
Hank Janssen3e7ee492009-07-13 16:02:34 -0700282{
283 return rbi->RingBuffer->InterruptMask;
284}
285
286/*++
287
288Name:
289 RingBufferInit()
290
291Description:
292 Initialize the ring buffer
293
294--*/
Greg Kroah-Hartman3523a802009-08-17 17:22:08 -0700295int RingBufferInit(RING_BUFFER_INFO *RingInfo, void *Buffer, u32 BufferLen)
Hank Janssen3e7ee492009-07-13 16:02:34 -0700296{
297 ASSERT(sizeof(RING_BUFFER) == PAGE_SIZE);
298
299 memset(RingInfo, 0, sizeof(RING_BUFFER_INFO));
300
301 RingInfo->RingBuffer = (RING_BUFFER*)Buffer;
302 RingInfo->RingBuffer->ReadIndex = RingInfo->RingBuffer->WriteIndex = 0;
303
304 RingInfo->RingSize = BufferLen;
305 RingInfo->RingDataSize = BufferLen - sizeof(RING_BUFFER);
306
Greg Kroah-Hartmana98f96e2009-07-15 14:55:14 -0700307 spin_lock_init(&RingInfo->ring_lock);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700308
309 return 0;
310}
311
312/*++
313
314Name:
315 RingBufferCleanup()
316
317Description:
318 Cleanup the ring buffer
319
320--*/
Greg Kroah-Hartman3523a802009-08-17 17:22:08 -0700321void RingBufferCleanup(RING_BUFFER_INFO* RingInfo)
Hank Janssen3e7ee492009-07-13 16:02:34 -0700322{
Hank Janssen3e7ee492009-07-13 16:02:34 -0700323}
324
325/*++
326
327Name:
328 RingBufferWrite()
329
330Description:
331 Write to the ring buffer
332
333--*/
Greg Kroah-Hartman3523a802009-08-17 17:22:08 -0700334int RingBufferWrite(RING_BUFFER_INFO *OutRingInfo,
335 struct scatterlist *sglist, u32 sgcount)
Hank Janssen3e7ee492009-07-13 16:02:34 -0700336{
337 int i=0;
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700338 u32 byteAvailToWrite;
339 u32 byteAvailToRead;
340 u32 totalBytesToWrite=0;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700341
Nicolas Palixb219b3f2009-07-30 17:37:23 +0200342 struct scatterlist *sg;
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700343 volatile u32 nextWriteLocation;
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700344 u64 prevIndices=0;
Greg Kroah-Hartmana98f96e2009-07-15 14:55:14 -0700345 unsigned long flags;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700346
347 DPRINT_ENTER(VMBUS);
348
Nicolas Palixb219b3f2009-07-30 17:37:23 +0200349 for_each_sg(sglist, sg, sgcount, i)
Hank Janssen3e7ee492009-07-13 16:02:34 -0700350 {
Nicolas Palixb219b3f2009-07-30 17:37:23 +0200351 totalBytesToWrite += sg->length;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700352 }
353
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700354 totalBytesToWrite += sizeof(u64);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700355
Greg Kroah-Hartmana98f96e2009-07-15 14:55:14 -0700356 spin_lock_irqsave(&OutRingInfo->ring_lock, flags);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700357
358 GetRingBufferAvailBytes(OutRingInfo, &byteAvailToRead, &byteAvailToWrite);
359
360 DPRINT_DBG(VMBUS, "Writing %u bytes...", totalBytesToWrite);
361
Bill Pemberton454f18a2009-07-27 16:47:24 -0400362 /* DumpRingInfo(OutRingInfo, "BEFORE "); */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700363
Bill Pemberton454f18a2009-07-27 16:47:24 -0400364 /* If there is only room for the packet, assume it is full. Otherwise, the next time around, we think the ring buffer */
365 /* is empty since the read index == write index */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700366 if (byteAvailToWrite <= totalBytesToWrite)
367 {
368 DPRINT_DBG(VMBUS, "No more space left on outbound ring buffer (needed %u, avail %u)", totalBytesToWrite, byteAvailToWrite);
369
Greg Kroah-Hartmana98f96e2009-07-15 14:55:14 -0700370 spin_unlock_irqrestore(&OutRingInfo->ring_lock, flags);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700371
372 DPRINT_EXIT(VMBUS);
373
374 return -1;
375 }
376
Bill Pemberton454f18a2009-07-27 16:47:24 -0400377 /* Write to the ring buffer */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700378 nextWriteLocation = GetNextWriteLocation(OutRingInfo);
379
Nicolas Palixb219b3f2009-07-30 17:37:23 +0200380 for_each_sg(sglist, sg, sgcount, i)
Hank Janssen3e7ee492009-07-13 16:02:34 -0700381 {
Nicolas Palixb219b3f2009-07-30 17:37:23 +0200382 nextWriteLocation = CopyToRingBuffer(OutRingInfo,
383 nextWriteLocation,
384 sg_virt(sg),
385 sg->length);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700386 }
387
Bill Pemberton454f18a2009-07-27 16:47:24 -0400388 /* Set previous packet start */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700389 prevIndices = GetRingBufferIndices(OutRingInfo);
390
391 nextWriteLocation = CopyToRingBuffer(OutRingInfo,
Nicolas Palixb219b3f2009-07-30 17:37:23 +0200392 nextWriteLocation,
393 &prevIndices,
394 sizeof(u64));
Hank Janssen3e7ee492009-07-13 16:02:34 -0700395
Bill Pemberton454f18a2009-07-27 16:47:24 -0400396 /* Make sure we flush all writes before updating the writeIndex */
Greg Kroah-Hartman28b6ca92009-07-16 12:34:20 -0700397 mb();
Hank Janssen3e7ee492009-07-13 16:02:34 -0700398
Bill Pemberton454f18a2009-07-27 16:47:24 -0400399 /* Now, update the write location */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700400 SetNextWriteLocation(OutRingInfo, nextWriteLocation);
401
Bill Pemberton454f18a2009-07-27 16:47:24 -0400402 /* DumpRingInfo(OutRingInfo, "AFTER "); */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700403
Greg Kroah-Hartmana98f96e2009-07-15 14:55:14 -0700404 spin_unlock_irqrestore(&OutRingInfo->ring_lock, flags);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700405
406 DPRINT_EXIT(VMBUS);
407
408 return 0;
409}
410
411
412/*++
413
414Name:
415 RingBufferPeek()
416
417Description:
418 Read without advancing the read index
419
420--*/
Greg Kroah-Hartman3523a802009-08-17 17:22:08 -0700421int RingBufferPeek(RING_BUFFER_INFO *InRingInfo, void *Buffer, u32 BufferLen)
Hank Janssen3e7ee492009-07-13 16:02:34 -0700422{
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700423 u32 bytesAvailToWrite;
424 u32 bytesAvailToRead;
425 u32 nextReadLocation=0;
Greg Kroah-Hartmana98f96e2009-07-15 14:55:14 -0700426 unsigned long flags;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700427
Greg Kroah-Hartmana98f96e2009-07-15 14:55:14 -0700428 spin_lock_irqsave(&InRingInfo->ring_lock, flags);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700429
430 GetRingBufferAvailBytes(InRingInfo, &bytesAvailToRead, &bytesAvailToWrite);
431
Bill Pemberton454f18a2009-07-27 16:47:24 -0400432 /* Make sure there is something to read */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700433 if (bytesAvailToRead < BufferLen )
434 {
Bill Pemberton454f18a2009-07-27 16:47:24 -0400435 /* DPRINT_DBG(VMBUS, "got callback but not enough to read <avail to read %d read size %d>!!", bytesAvailToRead, BufferLen); */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700436
Greg Kroah-Hartmana98f96e2009-07-15 14:55:14 -0700437 spin_unlock_irqrestore(&InRingInfo->ring_lock, flags);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700438
439 return -1;
440 }
441
Bill Pemberton454f18a2009-07-27 16:47:24 -0400442 /* Convert to byte offset */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700443 nextReadLocation = GetNextReadLocation(InRingInfo);
444
445 nextReadLocation = CopyFromRingBuffer(InRingInfo,
446 Buffer,
447 BufferLen,
448 nextReadLocation);
449
Greg Kroah-Hartmana98f96e2009-07-15 14:55:14 -0700450 spin_unlock_irqrestore(&InRingInfo->ring_lock, flags);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700451
452 return 0;
453}
454
455
456/*++
457
458Name:
459 RingBufferRead()
460
461Description:
462 Read and advance the read index
463
464--*/
Greg Kroah-Hartman3523a802009-08-17 17:22:08 -0700465int RingBufferRead(RING_BUFFER_INFO *InRingInfo, void *Buffer,
466 u32 BufferLen, u32 Offset)
Hank Janssen3e7ee492009-07-13 16:02:34 -0700467{
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700468 u32 bytesAvailToWrite;
469 u32 bytesAvailToRead;
470 u32 nextReadLocation=0;
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700471 u64 prevIndices=0;
Greg Kroah-Hartmana98f96e2009-07-15 14:55:14 -0700472 unsigned long flags;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700473
474 ASSERT(BufferLen > 0);
475
Greg Kroah-Hartmana98f96e2009-07-15 14:55:14 -0700476 spin_lock_irqsave(&InRingInfo->ring_lock, flags);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700477
478 GetRingBufferAvailBytes(InRingInfo, &bytesAvailToRead, &bytesAvailToWrite);
479
480 DPRINT_DBG(VMBUS, "Reading %u bytes...", BufferLen);
481
Bill Pemberton454f18a2009-07-27 16:47:24 -0400482 /* DumpRingInfo(InRingInfo, "BEFORE "); */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700483
Bill Pemberton454f18a2009-07-27 16:47:24 -0400484 /* Make sure there is something to read */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700485 if (bytesAvailToRead < BufferLen )
486 {
487 DPRINT_DBG(VMBUS, "got callback but not enough to read <avail to read %d read size %d>!!", bytesAvailToRead, BufferLen);
488
Greg Kroah-Hartmana98f96e2009-07-15 14:55:14 -0700489 spin_unlock_irqrestore(&InRingInfo->ring_lock, flags);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700490
491 return -1;
492 }
493
494 nextReadLocation = GetNextReadLocationWithOffset(InRingInfo, Offset);
495
496 nextReadLocation = CopyFromRingBuffer(InRingInfo,
497 Buffer,
498 BufferLen,
499 nextReadLocation);
500
501 nextReadLocation = CopyFromRingBuffer(InRingInfo,
502 &prevIndices,
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700503 sizeof(u64),
Hank Janssen3e7ee492009-07-13 16:02:34 -0700504 nextReadLocation);
505
Bill Pemberton454f18a2009-07-27 16:47:24 -0400506 /* Make sure all reads are done before we update the read index since */
507 /* the writer may start writing to the read area once the read index is updated */
Greg Kroah-Hartman28b6ca92009-07-16 12:34:20 -0700508 mb();
Hank Janssen3e7ee492009-07-13 16:02:34 -0700509
Bill Pemberton454f18a2009-07-27 16:47:24 -0400510 /* Update the read index */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700511 SetNextReadLocation(InRingInfo, nextReadLocation);
512
Bill Pemberton454f18a2009-07-27 16:47:24 -0400513 /* DumpRingInfo(InRingInfo, "AFTER "); */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700514
Greg Kroah-Hartmana98f96e2009-07-15 14:55:14 -0700515 spin_unlock_irqrestore(&InRingInfo->ring_lock, flags);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700516
517 return 0;
518}
519
520
521/*++
522
523Name:
524 CopyToRingBuffer()
525
526Description:
527 Helper routine to copy from source to ring buffer.
528 Assume there is enough room. Handles wrap-around in dest case only!!
529
530--*/
Greg Kroah-Hartmanbd1de702009-07-29 09:04:51 -0700531static u32
Hank Janssen3e7ee492009-07-13 16:02:34 -0700532CopyToRingBuffer(
533 RING_BUFFER_INFO *RingInfo,
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700534 u32 StartWriteOffset,
Greg Kroah-Hartman8282c402009-07-14 15:06:28 -0700535 void * Src,
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700536 u32 SrcLen)
Hank Janssen3e7ee492009-07-13 16:02:34 -0700537{
Greg Kroah-Hartman8282c402009-07-14 15:06:28 -0700538 void * ringBuffer=GetRingBuffer(RingInfo);
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700539 u32 ringBufferSize=GetRingBufferSize(RingInfo);
540 u32 fragLen;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700541
Bill Pemberton454f18a2009-07-27 16:47:24 -0400542 if (SrcLen > ringBufferSize - StartWriteOffset) /* wrap-around detected! */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700543 {
544 DPRINT_DBG(VMBUS, "wrap-around detected!");
545
546 fragLen = ringBufferSize - StartWriteOffset;
547 memcpy(ringBuffer + StartWriteOffset, Src, fragLen);
548 memcpy(ringBuffer, Src + fragLen, SrcLen - fragLen);
549 }
550 else
551 {
552 memcpy(ringBuffer + StartWriteOffset, Src, SrcLen);
553 }
554
555 StartWriteOffset += SrcLen;
556 StartWriteOffset %= ringBufferSize;
557
558 return StartWriteOffset;
559}
560
561
562/*++
563
564Name:
565 CopyFromRingBuffer()
566
567Description:
568 Helper routine to copy to source from ring buffer.
569 Assume there is enough room. Handles wrap-around in src case only!!
570
571--*/
Greg Kroah-Hartmanbd1de702009-07-29 09:04:51 -0700572static u32
Hank Janssen3e7ee492009-07-13 16:02:34 -0700573CopyFromRingBuffer(
574 RING_BUFFER_INFO *RingInfo,
Greg Kroah-Hartman8282c402009-07-14 15:06:28 -0700575 void * Dest,
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700576 u32 DestLen,
577 u32 StartReadOffset)
Hank Janssen3e7ee492009-07-13 16:02:34 -0700578{
Greg Kroah-Hartman8282c402009-07-14 15:06:28 -0700579 void * ringBuffer=GetRingBuffer(RingInfo);
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700580 u32 ringBufferSize=GetRingBufferSize(RingInfo);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700581
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700582 u32 fragLen;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700583
Bill Pemberton454f18a2009-07-27 16:47:24 -0400584 if (DestLen > ringBufferSize - StartReadOffset) /* wrap-around detected at the src */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700585 {
586 DPRINT_DBG(VMBUS, "src wrap-around detected!");
587
588 fragLen = ringBufferSize - StartReadOffset;
589
590 memcpy(Dest, ringBuffer + StartReadOffset, fragLen);
591 memcpy(Dest + fragLen, ringBuffer, DestLen - fragLen);
592 }
593 else
594 {
595 memcpy(Dest, ringBuffer + StartReadOffset, DestLen);
596 }
597
598 StartReadOffset += DestLen;
599 StartReadOffset %= ringBufferSize;
600
601 return StartReadOffset;
602}
603
604
Bill Pemberton454f18a2009-07-27 16:47:24 -0400605/* eof */