aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hv/ring_buffer.c
diff options
context:
space:
mode:
authorK. Y. Srinivasan <kys@microsoft.com>2012-12-01 09:46:36 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-01-17 13:46:39 -0500
commit98fa8cf4bcc79cb14de8fd815bbcd00dcbd7b20e (patch)
tree0d48abd179e49709cdac7e28eb853a653df7fbe2 /drivers/hv/ring_buffer.c
parentf878f3d59ed26f489add852ed6d5c8e5f3bbb1aa (diff)
Drivers: hv: Optimize the signaling on the write path
The host has already implemented the "read" side optimizations. Leverage that to optimize "write" side signaling. Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/hv/ring_buffer.c')
-rw-r--r--drivers/hv/ring_buffer.c42
1 files changed, 39 insertions, 3 deletions
diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c
index 001079287709..9bc55f0dcf47 100644
--- a/drivers/hv/ring_buffer.c
+++ b/drivers/hv/ring_buffer.c
@@ -53,6 +53,37 @@ u32 hv_end_read(struct hv_ring_buffer_info *rbi)
53 return read; 53 return read;
54} 54}
55 55
56/*
57 * When we write to the ring buffer, check if the host needs to
58 * be signaled. Here is the details of this protocol:
59 *
60 * 1. The host guarantees that while it is draining the
61 * ring buffer, it will set the interrupt_mask to
62 * indicate it does not need to be interrupted when
63 * new data is placed.
64 *
65 * 2. The host guarantees that it will completely drain
66 * the ring buffer before exiting the read loop. Further,
67 * once the ring buffer is empty, it will clear the
68 * interrupt_mask and re-check to see if new data has
69 * arrived.
70 */
71
72static bool hv_need_to_signal(u32 old_write, struct hv_ring_buffer_info *rbi)
73{
74 if (rbi->ring_buffer->interrupt_mask)
75 return false;
76
77 /*
78 * This is the only case we need to signal when the
79 * ring transitions from being empty to non-empty.
80 */
81 if (old_write == rbi->ring_buffer->read_index)
82 return true;
83
84 return false;
85}
86
56 87
57/* 88/*
58 * hv_get_next_write_location() 89 * hv_get_next_write_location()
@@ -322,7 +353,7 @@ void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info)
322 * 353 *
323 */ 354 */
324int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info, 355int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info,
325 struct scatterlist *sglist, u32 sgcount) 356 struct scatterlist *sglist, u32 sgcount, bool *signal)
326{ 357{
327 int i = 0; 358 int i = 0;
328 u32 bytes_avail_towrite; 359 u32 bytes_avail_towrite;
@@ -331,6 +362,7 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info,
331 362
332 struct scatterlist *sg; 363 struct scatterlist *sg;
333 u32 next_write_location; 364 u32 next_write_location;
365 u32 old_write;
334 u64 prev_indices = 0; 366 u64 prev_indices = 0;
335 unsigned long flags; 367 unsigned long flags;
336 368
@@ -359,6 +391,8 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info,
359 /* Write to the ring buffer */ 391 /* Write to the ring buffer */
360 next_write_location = hv_get_next_write_location(outring_info); 392 next_write_location = hv_get_next_write_location(outring_info);
361 393
394 old_write = next_write_location;
395
362 for_each_sg(sglist, sg, sgcount, i) 396 for_each_sg(sglist, sg, sgcount, i)
363 { 397 {
364 next_write_location = hv_copyto_ringbuffer(outring_info, 398 next_write_location = hv_copyto_ringbuffer(outring_info,
@@ -375,14 +409,16 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info,
375 &prev_indices, 409 &prev_indices,
376 sizeof(u64)); 410 sizeof(u64));
377 411
378 /* Make sure we flush all writes before updating the writeIndex */ 412 /* Issue a full memory barrier before updating the write index */
379 smp_wmb(); 413 smp_mb();
380 414
381 /* Now, update the write location */ 415 /* Now, update the write location */
382 hv_set_next_write_location(outring_info, next_write_location); 416 hv_set_next_write_location(outring_info, next_write_location);
383 417
384 418
385 spin_unlock_irqrestore(&outring_info->ring_lock, flags); 419 spin_unlock_irqrestore(&outring_info->ring_lock, flags);
420
421 *signal = hv_need_to_signal(old_write, outring_info);
386 return 0; 422 return 0;
387} 423}
388 424