staging: hv: Convert camel cased local variables in ring_buffer.c to lower cases
[deliverable/linux.git] / drivers / staging / hv / ring_buffer.c
CommitLineData
3e7ee490
HJ
1/*
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
a0086dc5
GKH
24#include <linux/kernel.h>
25#include <linux/mm.h>
4983b39a 26#include "osd.h"
645954c5 27#include "logging.h"
8f078ca6 28#include "ring_buffer.h"
3e7ee490 29
3e7ee490 30
454f18a9
BP
31/* #defines */
32
33
34/* Amount of space to write to */
0686e4f4 35#define BYTES_AVAIL_TO_WRITE(r, w, z) ((w) >= (r)) ? ((z) - ((w) - (r))) : ((r) - (w))
3e7ee490
HJ
36
37
38/*++
39
40Name:
41 GetRingBufferAvailBytes()
42
43Description:
44 Get number of bytes available to read and to write to
45 for the specified ring buffer
46
47--*/
48static inline void
8a0e1c55 49GetRingBufferAvailBytes(struct hv_ring_buffer_info *rbi, u32 *read, u32 *write)
3e7ee490 50{
4408f531 51 u32 read_loc, write_loc;
3e7ee490 52
454f18a9 53 /* Capture the read/write indices before they changed */
82f8bd40
HZ
54 read_loc = rbi->ring_buffer->read_index;
55 write_loc = rbi->ring_buffer->write_index;
3e7ee490 56
82f8bd40
HZ
57 *write = BYTES_AVAIL_TO_WRITE(read_loc, write_loc, rbi->ring_datasize);
58 *read = rbi->ring_datasize - *write;
3e7ee490
HJ
59}
60
61/*++
62
63Name:
64 GetNextWriteLocation()
65
66Description:
67 Get the next write location for the specified ring buffer
68
69--*/
4d643114 70static inline u32
fc8c72eb 71GetNextWriteLocation(struct hv_ring_buffer_info *ring_info)
3e7ee490 72{
fc8c72eb 73 u32 next = ring_info->ring_buffer->write_index;
3e7ee490 74
fc8c72eb 75 /* ASSERT(next < ring_info->RingDataSize); */
3e7ee490
HJ
76
77 return next;
78}
79
80/*++
81
82Name:
83 SetNextWriteLocation()
84
85Description:
86 Set the next write location for the specified ring buffer
87
88--*/
89static inline void
fc8c72eb
HZ
90SetNextWriteLocation(struct hv_ring_buffer_info *ring_info,
91 u32 next_write_location)
3e7ee490 92{
fc8c72eb 93 ring_info->ring_buffer->write_index = next_write_location;
3e7ee490
HJ
94}
95
96/*++
97
98Name:
99 GetNextReadLocation()
100
101Description:
102 Get the next read location for the specified ring buffer
103
104--*/
4d643114 105static inline u32
fc8c72eb 106GetNextReadLocation(struct hv_ring_buffer_info *ring_info)
3e7ee490 107{
fc8c72eb 108 u32 next = ring_info->ring_buffer->read_index;
3e7ee490 109
fc8c72eb 110 /* ASSERT(next < ring_info->RingDataSize); */
3e7ee490
HJ
111
112 return next;
113}
114
115/*++
116
117Name:
118 GetNextReadLocationWithOffset()
119
120Description:
121 Get the next read location + offset for the specified ring buffer.
122 This allows the caller to skip
123
124--*/
4d643114 125static inline u32
fc8c72eb 126GetNextReadLocationWithOffset(struct hv_ring_buffer_info *ring_info, u32 offset)
3e7ee490 127{
fc8c72eb 128 u32 next = ring_info->ring_buffer->read_index;
3e7ee490 129
fc8c72eb
HZ
130 /* ASSERT(next < ring_info->RingDataSize); */
131 next += offset;
132 next %= ring_info->ring_datasize;
3e7ee490
HJ
133
134 return next;
135}
136
137/*++
138
139Name:
140 SetNextReadLocation()
141
142Description:
143 Set the next read location for the specified ring buffer
144
145--*/
146static inline void
fc8c72eb
HZ
147SetNextReadLocation(struct hv_ring_buffer_info *ring_info,
148 u32 next_read_location)
3e7ee490 149{
fc8c72eb 150 ring_info->ring_buffer->read_index = next_read_location;
3e7ee490
HJ
151}
152
153
154/*++
155
156Name:
157 GetRingBuffer()
158
159Description:
160 Get the start of the ring buffer
161
162--*/
8282c400 163static inline void *
fc8c72eb 164GetRingBuffer(struct hv_ring_buffer_info *ring_info)
3e7ee490 165{
fc8c72eb 166 return (void *)ring_info->ring_buffer->buffer;
3e7ee490
HJ
167}
168
169
170/*++
171
172Name:
173 GetRingBufferSize()
174
175Description:
176 Get the size of the ring buffer
177
178--*/
4d643114 179static inline u32
fc8c72eb 180GetRingBufferSize(struct hv_ring_buffer_info *ring_info)
3e7ee490 181{
fc8c72eb 182 return ring_info->ring_datasize;
3e7ee490
HJ
183}
184
185/*++
186
187Name:
188 GetRingBufferIndices()
189
190Description:
59471438 191 Get the read and write indices as u64 of the specified ring buffer
3e7ee490
HJ
192
193--*/
59471438 194static inline u64
fc8c72eb 195GetRingBufferIndices(struct hv_ring_buffer_info *ring_info)
3e7ee490 196{
fc8c72eb 197 return (u64)ring_info->ring_buffer->write_index << 32;
3e7ee490
HJ
198}
199
200
201/*++
202
203Name:
fc8c72eb 204 Dumpring_info()
3e7ee490
HJ
205
206Description:
207 Dump out to console the ring buffer info
208
209--*/
fc8c72eb 210void Dumpring_info(struct hv_ring_buffer_info *ring_info, char *prefix)
3e7ee490 211{
fc8c72eb
HZ
212 u32 bytes_avail_towrite;
213 u32 bytes_avail_toread;
3e7ee490 214
fc8c72eb
HZ
215 GetRingBufferAvailBytes(ring_info,
216 &bytes_avail_toread,
217 &bytes_avail_towrite);
3e7ee490 218
4408f531
B
219 DPRINT(VMBUS,
220 DEBUG_RING_LVL,
221 "%s <<ringinfo %p buffer %p avail write %u "
222 "avail read %u read idx %u write idx %u>>",
fc8c72eb
HZ
223 prefix,
224 ring_info,
225 ring_info->ring_buffer->buffer,
226 bytes_avail_towrite,
227 bytes_avail_toread,
228 ring_info->ring_buffer->read_index,
229 ring_info->ring_buffer->write_index);
3e7ee490
HJ
230}
231
454f18a9
BP
232
233/* Internal routines */
234
4d643114 235static u32
3e7ee490 236CopyToRingBuffer(
fc8c72eb
HZ
237 struct hv_ring_buffer_info *ring_info,
238 u32 start_write_offset,
239 void *src,
240 u32 srclen);
3e7ee490 241
4d643114 242static u32
3e7ee490 243CopyFromRingBuffer(
fc8c72eb
HZ
244 struct hv_ring_buffer_info *ring_info,
245 void *dest,
246 u32 destlen,
247 u32 start_read_offset);
3e7ee490
HJ
248
249
250
251/*++
252
253Name:
254 RingBufferGetDebugInfo()
255
256Description:
257 Get various debug metrics for the specified ring buffer
258
259--*/
fc8c72eb 260void RingBufferGetDebugInfo(struct hv_ring_buffer_info *ring_info,
80682b7a 261 struct hv_ring_buffer_debug_info *debug_info)
3e7ee490 262{
fc8c72eb
HZ
263 u32 bytes_avail_towrite;
264 u32 bytes_avail_toread;
3e7ee490 265
fc8c72eb
HZ
266 if (ring_info->ring_buffer) {
267 GetRingBufferAvailBytes(ring_info,
268 &bytes_avail_toread,
269 &bytes_avail_towrite);
3e7ee490 270
fc8c72eb
HZ
271 debug_info->bytes_avail_toread = bytes_avail_toread;
272 debug_info->bytes_avail_towrite = bytes_avail_towrite;
82f8bd40 273 debug_info->current_read_index =
fc8c72eb 274 ring_info->ring_buffer->read_index;
82f8bd40 275 debug_info->current_write_index =
fc8c72eb 276 ring_info->ring_buffer->write_index;
82f8bd40 277 debug_info->current_interrupt_mask =
fc8c72eb 278 ring_info->ring_buffer->interrupt_mask;
3e7ee490
HJ
279 }
280}
281
282
283/*++
284
285Name:
286 GetRingBufferInterruptMask()
287
288Description:
289 Get the interrupt mask for the specified ring buffer
290
291--*/
8a0e1c55 292u32 GetRingBufferInterruptMask(struct hv_ring_buffer_info *rbi)
3e7ee490 293{
82f8bd40 294 return rbi->ring_buffer->interrupt_mask;
3e7ee490
HJ
295}
296
297/*++
298
299Name:
300 RingBufferInit()
301
302Description:
303 Initialize the ring buffer
304
305--*/
fc8c72eb
HZ
306int RingBufferInit(struct hv_ring_buffer_info *ring_info,
307 void *buffer, u32 buflen)
3e7ee490 308{
4a1b3acc 309 if (sizeof(struct hv_ring_buffer) != PAGE_SIZE)
3324fb40 310 return -EINVAL;
3e7ee490 311
fc8c72eb 312 memset(ring_info, 0, sizeof(struct hv_ring_buffer_info));
3e7ee490 313
fc8c72eb
HZ
314 ring_info->ring_buffer = (struct hv_ring_buffer *)buffer;
315 ring_info->ring_buffer->read_index =
316 ring_info->ring_buffer->write_index = 0;
3e7ee490 317
fc8c72eb
HZ
318 ring_info->ring_size = buflen;
319 ring_info->ring_datasize = buflen - sizeof(struct hv_ring_buffer);
3e7ee490 320
fc8c72eb 321 spin_lock_init(&ring_info->ring_lock);
3e7ee490
HJ
322
323 return 0;
324}
325
326/*++
327
328Name:
329 RingBufferCleanup()
330
331Description:
332 Cleanup the ring buffer
333
334--*/
fc8c72eb 335void RingBufferCleanup(struct hv_ring_buffer_info *ring_info)
3e7ee490 336{
3e7ee490
HJ
337}
338
339/*++
340
341Name:
342 RingBufferWrite()
343
344Description:
345 Write to the ring buffer
346
347--*/
fc8c72eb 348int RingBufferWrite(struct hv_ring_buffer_info *outring_info,
3523a805 349 struct scatterlist *sglist, u32 sgcount)
3e7ee490 350{
4408f531 351 int i = 0;
fc8c72eb
HZ
352 u32 bytes_avail_towrite;
353 u32 bytes_avail_toread;
354 u32 totalbytes_towrite = 0;
3e7ee490 355
b219b3f7 356 struct scatterlist *sg;
fc8c72eb
HZ
357 volatile u32 next_write_location;
358 u64 prev_indices = 0;
a98f96ee 359 unsigned long flags;
3e7ee490 360
b219b3f7 361 for_each_sg(sglist, sg, sgcount, i)
3e7ee490 362 {
fc8c72eb 363 totalbytes_towrite += sg->length;
3e7ee490
HJ
364 }
365
fc8c72eb 366 totalbytes_towrite += sizeof(u64);
3e7ee490 367
fc8c72eb 368 spin_lock_irqsave(&outring_info->ring_lock, flags);
3e7ee490 369
fc8c72eb
HZ
370 GetRingBufferAvailBytes(outring_info,
371 &bytes_avail_toread,
372 &bytes_avail_towrite);
3e7ee490 373
fc8c72eb 374 DPRINT_DBG(VMBUS, "Writing %u bytes...", totalbytes_towrite);
3e7ee490 375
fc8c72eb 376 /* Dumpring_info(Outring_info, "BEFORE "); */
3e7ee490 377
4408f531
B
378 /* If there is only room for the packet, assume it is full. */
379 /* Otherwise, the next time around, we think the ring buffer */
454f18a9 380 /* is empty since the read index == write index */
fc8c72eb 381 if (bytes_avail_towrite <= totalbytes_towrite) {
4408f531
B
382 DPRINT_DBG(VMBUS,
383 "No more space left on outbound ring buffer "
384 "(needed %u, avail %u)",
fc8c72eb
HZ
385 totalbytes_towrite,
386 bytes_avail_towrite);
3e7ee490 387
fc8c72eb 388 spin_unlock_irqrestore(&outring_info->ring_lock, flags);
3e7ee490
HJ
389 return -1;
390 }
391
454f18a9 392 /* Write to the ring buffer */
fc8c72eb 393 next_write_location = GetNextWriteLocation(outring_info);
3e7ee490 394
b219b3f7 395 for_each_sg(sglist, sg, sgcount, i)
3e7ee490 396 {
fc8c72eb
HZ
397 next_write_location = CopyToRingBuffer(outring_info,
398 next_write_location,
b219b3f7
NP
399 sg_virt(sg),
400 sg->length);
3e7ee490
HJ
401 }
402
454f18a9 403 /* Set previous packet start */
fc8c72eb 404 prev_indices = GetRingBufferIndices(outring_info);
3e7ee490 405
fc8c72eb
HZ
406 next_write_location = CopyToRingBuffer(outring_info,
407 next_write_location,
408 &prev_indices,
b219b3f7 409 sizeof(u64));
3e7ee490 410
454f18a9 411 /* Make sure we flush all writes before updating the writeIndex */
28b6ca9c 412 mb();
3e7ee490 413
454f18a9 414 /* Now, update the write location */
fc8c72eb 415 SetNextWriteLocation(outring_info, next_write_location);
3e7ee490 416
fc8c72eb 417 /* Dumpring_info(Outring_info, "AFTER "); */
3e7ee490 418
fc8c72eb 419 spin_unlock_irqrestore(&outring_info->ring_lock, flags);
3e7ee490
HJ
420 return 0;
421}
422
423
424/*++
425
426Name:
427 RingBufferPeek()
428
429Description:
430 Read without advancing the read index
431
432--*/
fc8c72eb
HZ
433int RingBufferPeek(struct hv_ring_buffer_info *Inring_info,
434 void *Buffer, u32 buflen)
3e7ee490 435{
fc8c72eb
HZ
436 u32 bytes_avail_towrite;
437 u32 bytes_avail_toread;
438 u32 next_read_location = 0;
a98f96ee 439 unsigned long flags;
3e7ee490 440
fc8c72eb 441 spin_lock_irqsave(&Inring_info->ring_lock, flags);
3e7ee490 442
fc8c72eb
HZ
443 GetRingBufferAvailBytes(Inring_info,
444 &bytes_avail_toread,
445 &bytes_avail_towrite);
3e7ee490 446
454f18a9 447 /* Make sure there is something to read */
fc8c72eb 448 if (bytes_avail_toread < buflen) {
4408f531
B
449 /* DPRINT_DBG(VMBUS,
450 "got callback but not enough to read "
451 "<avail to read %d read size %d>!!",
fc8c72eb 452 bytes_avail_toread,
4408f531 453 BufferLen); */
3e7ee490 454
fc8c72eb 455 spin_unlock_irqrestore(&Inring_info->ring_lock, flags);
3e7ee490
HJ
456
457 return -1;
458 }
459
454f18a9 460 /* Convert to byte offset */
fc8c72eb 461 next_read_location = GetNextReadLocation(Inring_info);
3e7ee490 462
fc8c72eb 463 next_read_location = CopyFromRingBuffer(Inring_info,
4408f531 464 Buffer,
fc8c72eb
HZ
465 buflen,
466 next_read_location);
3e7ee490 467
fc8c72eb 468 spin_unlock_irqrestore(&Inring_info->ring_lock, flags);
3e7ee490
HJ
469
470 return 0;
471}
472
473
474/*++
475
476Name:
477 RingBufferRead()
478
479Description:
480 Read and advance the read index
481
482--*/
fc8c72eb
HZ
483int RingBufferRead(struct hv_ring_buffer_info *inring_info, void *buffer,
484 u32 buflen, u32 offset)
3e7ee490 485{
fc8c72eb
HZ
486 u32 bytes_avail_towrite;
487 u32 bytes_avail_toread;
488 u32 next_read_location = 0;
489 u64 prev_indices = 0;
a98f96ee 490 unsigned long flags;
3e7ee490 491
fc8c72eb 492 if (buflen <= 0)
a16e1485 493 return -EINVAL;
3e7ee490 494
fc8c72eb 495 spin_lock_irqsave(&inring_info->ring_lock, flags);
3e7ee490 496
fc8c72eb
HZ
497 GetRingBufferAvailBytes(inring_info,
498 &bytes_avail_toread,
499 &bytes_avail_towrite);
3e7ee490 500
fc8c72eb 501 DPRINT_DBG(VMBUS, "Reading %u bytes...", buflen);
3e7ee490 502
fc8c72eb 503 /* Dumpring_info(Inring_info, "BEFORE "); */
3e7ee490 504
454f18a9 505 /* Make sure there is something to read */
fc8c72eb 506 if (bytes_avail_toread < buflen) {
4408f531
B
507 DPRINT_DBG(VMBUS,
508 "got callback but not enough to read "
509 "<avail to read %d read size %d>!!",
fc8c72eb
HZ
510 bytes_avail_toread,
511 buflen);
3e7ee490 512
fc8c72eb 513 spin_unlock_irqrestore(&inring_info->ring_lock, flags);
3e7ee490
HJ
514
515 return -1;
516 }
517
fc8c72eb 518 next_read_location = GetNextReadLocationWithOffset(inring_info, offset);
3e7ee490 519
fc8c72eb
HZ
520 next_read_location = CopyFromRingBuffer(inring_info,
521 buffer,
522 buflen,
523 next_read_location);
3e7ee490 524
fc8c72eb
HZ
525 next_read_location = CopyFromRingBuffer(inring_info,
526 &prev_indices,
4408f531 527 sizeof(u64),
fc8c72eb 528 next_read_location);
3e7ee490 529
454f18a9 530 /* Make sure all reads are done before we update the read index since */
4408f531
B
531 /* the writer may start writing to the read area once the read index */
532 /*is updated */
28b6ca9c 533 mb();
3e7ee490 534
454f18a9 535 /* Update the read index */
fc8c72eb 536 SetNextReadLocation(inring_info, next_read_location);
3e7ee490 537
fc8c72eb 538 /* Dumpring_info(Inring_info, "AFTER "); */
3e7ee490 539
fc8c72eb 540 spin_unlock_irqrestore(&inring_info->ring_lock, flags);
3e7ee490
HJ
541
542 return 0;
543}
544
545
546/*++
547
548Name:
549 CopyToRingBuffer()
550
551Description:
552 Helper routine to copy from source to ring buffer.
553 Assume there is enough room. Handles wrap-around in dest case only!!
554
555--*/
bd1de709 556static u32
3e7ee490 557CopyToRingBuffer(
fc8c72eb
HZ
558 struct hv_ring_buffer_info *ring_info,
559 u32 start_write_offset,
560 void *src,
561 u32 srclen)
3e7ee490 562{
fc8c72eb
HZ
563 void *ring_buffer = GetRingBuffer(ring_info);
564 u32 ring_buffer_size = GetRingBufferSize(ring_info);
565 u32 frag_len;
3e7ee490 566
4408f531 567 /* wrap-around detected! */
fc8c72eb 568 if (srclen > ring_buffer_size - start_write_offset) {
3e7ee490
HJ
569 DPRINT_DBG(VMBUS, "wrap-around detected!");
570
fc8c72eb
HZ
571 frag_len = ring_buffer_size - start_write_offset;
572 memcpy(ring_buffer + start_write_offset, src, frag_len);
573 memcpy(ring_buffer, src + frag_len, srclen - frag_len);
4408f531 574 } else
fc8c72eb 575 memcpy(ring_buffer + start_write_offset, src, srclen);
3e7ee490 576
fc8c72eb
HZ
577 start_write_offset += srclen;
578 start_write_offset %= ring_buffer_size;
3e7ee490 579
fc8c72eb 580 return start_write_offset;
3e7ee490
HJ
581}
582
583
584/*++
585
586Name:
587 CopyFromRingBuffer()
588
589Description:
590 Helper routine to copy to source from ring buffer.
591 Assume there is enough room. Handles wrap-around in src case only!!
592
593--*/
bd1de709 594static u32
3e7ee490 595CopyFromRingBuffer(
fc8c72eb
HZ
596 struct hv_ring_buffer_info *ring_info,
597 void *dest,
598 u32 destlen,
599 u32 start_read_offset)
3e7ee490 600{
fc8c72eb
HZ
601 void *ring_buffer = GetRingBuffer(ring_info);
602 u32 ring_buffer_size = GetRingBufferSize(ring_info);
3e7ee490 603
fc8c72eb 604 u32 frag_len;
3e7ee490 605
4408f531 606 /* wrap-around detected at the src */
fc8c72eb 607 if (destlen > ring_buffer_size - start_read_offset) {
3e7ee490
HJ
608 DPRINT_DBG(VMBUS, "src wrap-around detected!");
609
fc8c72eb 610 frag_len = ring_buffer_size - start_read_offset;
3e7ee490 611
fc8c72eb
HZ
612 memcpy(dest, ring_buffer + start_read_offset, frag_len);
613 memcpy(dest + frag_len, ring_buffer, destlen - frag_len);
4408f531
B
614 } else
615
fc8c72eb 616 memcpy(dest, ring_buffer + start_read_offset, destlen);
4408f531 617
3e7ee490 618
fc8c72eb
HZ
619 start_read_offset += destlen;
620 start_read_offset %= ring_buffer_size;
3e7ee490 621
fc8c72eb 622 return start_read_offset;
3e7ee490
HJ
623}
624
625
454f18a9 626/* eof */
This page took 0.205668 seconds and 5 git commands to generate.