~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to drivers/staging/hv/ring_buffer.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

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