aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorK. Y. Srinivasan <kys@microsoft.com>2014-02-01 22:02:20 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-02-07 18:22:40 -0500
commit011a7c3cc3aa60c7ea6bb49d847e80a299ba7b36 (patch)
tree97dc47f7d4d372b76ccefc50582e2abcf9489d21
parent90f3453585479d5beb75058da46eb573ced0e6ac (diff)
Drivers: hv: vmbus: Cleanup the packet send path
The current channel code is using scatterlist abstraction to pass data to the ringbuffer API on the send path. This causes unnecessary translations between virtual and physical addresses. Fix this. Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/hv/channel.c42
-rw-r--r--drivers/hv/hyperv_vmbus.h4
-rw-r--r--drivers/hv/ring_buffer.c17
-rw-r--r--include/linux/hyperv.h2
4 files changed, 33 insertions, 32 deletions
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index 69ea36f07b4d..602ca86a6488 100644
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -27,6 +27,7 @@
27#include <linux/slab.h> 27#include <linux/slab.h>
28#include <linux/module.h> 28#include <linux/module.h>
29#include <linux/hyperv.h> 29#include <linux/hyperv.h>
30#include <linux/uio.h>
30 31
31#include "hyperv_vmbus.h" 32#include "hyperv_vmbus.h"
32 33
@@ -554,14 +555,14 @@ EXPORT_SYMBOL_GPL(vmbus_close);
554 * 555 *
555 * Mainly used by Hyper-V drivers. 556 * Mainly used by Hyper-V drivers.
556 */ 557 */
557int vmbus_sendpacket(struct vmbus_channel *channel, const void *buffer, 558int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer,
558 u32 bufferlen, u64 requestid, 559 u32 bufferlen, u64 requestid,
559 enum vmbus_packet_type type, u32 flags) 560 enum vmbus_packet_type type, u32 flags)
560{ 561{
561 struct vmpacket_descriptor desc; 562 struct vmpacket_descriptor desc;
562 u32 packetlen = sizeof(struct vmpacket_descriptor) + bufferlen; 563 u32 packetlen = sizeof(struct vmpacket_descriptor) + bufferlen;
563 u32 packetlen_aligned = ALIGN(packetlen, sizeof(u64)); 564 u32 packetlen_aligned = ALIGN(packetlen, sizeof(u64));
564 struct scatterlist bufferlist[3]; 565 struct kvec bufferlist[3];
565 u64 aligned_data = 0; 566 u64 aligned_data = 0;
566 int ret; 567 int ret;
567 bool signal = false; 568 bool signal = false;
@@ -575,11 +576,12 @@ int vmbus_sendpacket(struct vmbus_channel *channel, const void *buffer,
575 desc.len8 = (u16)(packetlen_aligned >> 3); 576 desc.len8 = (u16)(packetlen_aligned >> 3);
576 desc.trans_id = requestid; 577 desc.trans_id = requestid;
577 578
578 sg_init_table(bufferlist, 3); 579 bufferlist[0].iov_base = &desc;
579 sg_set_buf(&bufferlist[0], &desc, sizeof(struct vmpacket_descriptor)); 580 bufferlist[0].iov_len = sizeof(struct vmpacket_descriptor);
580 sg_set_buf(&bufferlist[1], buffer, bufferlen); 581 bufferlist[1].iov_base = buffer;
581 sg_set_buf(&bufferlist[2], &aligned_data, 582 bufferlist[1].iov_len = bufferlen;
582 packetlen_aligned - packetlen); 583 bufferlist[2].iov_base = &aligned_data;
584 bufferlist[2].iov_len = (packetlen_aligned - packetlen);
583 585
584 ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal); 586 ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);
585 587
@@ -605,7 +607,7 @@ int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
605 u32 descsize; 607 u32 descsize;
606 u32 packetlen; 608 u32 packetlen;
607 u32 packetlen_aligned; 609 u32 packetlen_aligned;
608 struct scatterlist bufferlist[3]; 610 struct kvec bufferlist[3];
609 u64 aligned_data = 0; 611 u64 aligned_data = 0;
610 bool signal = false; 612 bool signal = false;
611 613
@@ -637,11 +639,12 @@ int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
637 desc.range[i].pfn = pagebuffers[i].pfn; 639 desc.range[i].pfn = pagebuffers[i].pfn;
638 } 640 }
639 641
640 sg_init_table(bufferlist, 3); 642 bufferlist[0].iov_base = &desc;
641 sg_set_buf(&bufferlist[0], &desc, descsize); 643 bufferlist[0].iov_len = descsize;
642 sg_set_buf(&bufferlist[1], buffer, bufferlen); 644 bufferlist[1].iov_base = buffer;
643 sg_set_buf(&bufferlist[2], &aligned_data, 645 bufferlist[1].iov_len = bufferlen;
644 packetlen_aligned - packetlen); 646 bufferlist[2].iov_base = &aligned_data;
647 bufferlist[2].iov_len = (packetlen_aligned - packetlen);
645 648
646 ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal); 649 ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);
647 650
@@ -665,7 +668,7 @@ int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
665 u32 descsize; 668 u32 descsize;
666 u32 packetlen; 669 u32 packetlen;
667 u32 packetlen_aligned; 670 u32 packetlen_aligned;
668 struct scatterlist bufferlist[3]; 671 struct kvec bufferlist[3];
669 u64 aligned_data = 0; 672 u64 aligned_data = 0;
670 bool signal = false; 673 bool signal = false;
671 u32 pfncount = NUM_PAGES_SPANNED(multi_pagebuffer->offset, 674 u32 pfncount = NUM_PAGES_SPANNED(multi_pagebuffer->offset,
@@ -700,11 +703,12 @@ int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
700 memcpy(desc.range.pfn_array, multi_pagebuffer->pfn_array, 703 memcpy(desc.range.pfn_array, multi_pagebuffer->pfn_array,
701 pfncount * sizeof(u64)); 704 pfncount * sizeof(u64));
702 705
703 sg_init_table(bufferlist, 3); 706 bufferlist[0].iov_base = &desc;
704 sg_set_buf(&bufferlist[0], &desc, descsize); 707 bufferlist[0].iov_len = descsize;
705 sg_set_buf(&bufferlist[1], buffer, bufferlen); 708 bufferlist[1].iov_base = buffer;
706 sg_set_buf(&bufferlist[2], &aligned_data, 709 bufferlist[1].iov_len = bufferlen;
707 packetlen_aligned - packetlen); 710 bufferlist[2].iov_base = &aligned_data;
711 bufferlist[2].iov_len = (packetlen_aligned - packetlen);
708 712
709 ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal); 713 ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);
710 714
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index e05517616a06..1544609881fe 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -559,8 +559,8 @@ int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info, void *buffer,
559void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info); 559void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info);
560 560
561int hv_ringbuffer_write(struct hv_ring_buffer_info *ring_info, 561int hv_ringbuffer_write(struct hv_ring_buffer_info *ring_info,
562 struct scatterlist *sglist, 562 struct kvec *kv_list,
563 u32 sgcount, bool *signal); 563 u32 kv_count, bool *signal);
564 564
565int hv_ringbuffer_peek(struct hv_ring_buffer_info *ring_info, void *buffer, 565int hv_ringbuffer_peek(struct hv_ring_buffer_info *ring_info, void *buffer,
566 u32 buflen); 566 u32 buflen);
diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c
index 26c93cf9f6be..15db66b74141 100644
--- a/drivers/hv/ring_buffer.c
+++ b/drivers/hv/ring_buffer.c
@@ -26,6 +26,7 @@
26#include <linux/kernel.h> 26#include <linux/kernel.h>
27#include <linux/mm.h> 27#include <linux/mm.h>
28#include <linux/hyperv.h> 28#include <linux/hyperv.h>
29#include <linux/uio.h>
29 30
30#include "hyperv_vmbus.h" 31#include "hyperv_vmbus.h"
31 32
@@ -387,23 +388,20 @@ void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info)
387 * 388 *
388 */ 389 */
389int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info, 390int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info,
390 struct scatterlist *sglist, u32 sgcount, bool *signal) 391 struct kvec *kv_list, u32 kv_count, bool *signal)
391{ 392{
392 int i = 0; 393 int i = 0;
393 u32 bytes_avail_towrite; 394 u32 bytes_avail_towrite;
394 u32 bytes_avail_toread; 395 u32 bytes_avail_toread;
395 u32 totalbytes_towrite = 0; 396 u32 totalbytes_towrite = 0;
396 397
397 struct scatterlist *sg;
398 u32 next_write_location; 398 u32 next_write_location;
399 u32 old_write; 399 u32 old_write;
400 u64 prev_indices = 0; 400 u64 prev_indices = 0;
401 unsigned long flags; 401 unsigned long flags;
402 402
403 for_each_sg(sglist, sg, sgcount, i) 403 for (i = 0; i < kv_count; i++)
404 { 404 totalbytes_towrite += kv_list[i].iov_len;
405 totalbytes_towrite += sg->length;
406 }
407 405
408 totalbytes_towrite += sizeof(u64); 406 totalbytes_towrite += sizeof(u64);
409 407
@@ -427,12 +425,11 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info,
427 425
428 old_write = next_write_location; 426 old_write = next_write_location;
429 427
430 for_each_sg(sglist, sg, sgcount, i) 428 for (i = 0; i < kv_count; i++) {
431 {
432 next_write_location = hv_copyto_ringbuffer(outring_info, 429 next_write_location = hv_copyto_ringbuffer(outring_info,
433 next_write_location, 430 next_write_location,
434 sg_virt(sg), 431 kv_list[i].iov_base,
435 sg->length); 432 kv_list[i].iov_len);
436 } 433 }
437 434
438 /* Set previous packet start */ 435 /* Set previous packet start */
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index 6b862dadbb7a..9b07e1f070ac 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -802,7 +802,7 @@ extern int vmbus_open(struct vmbus_channel *channel,
802extern void vmbus_close(struct vmbus_channel *channel); 802extern void vmbus_close(struct vmbus_channel *channel);
803 803
804extern int vmbus_sendpacket(struct vmbus_channel *channel, 804extern int vmbus_sendpacket(struct vmbus_channel *channel,
805 const void *buffer, 805 void *buffer,
806 u32 bufferLen, 806 u32 bufferLen,
807 u64 requestid, 807 u64 requestid,
808 enum vmbus_packet_type type, 808 enum vmbus_packet_type type,