summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/hyperv/hyperv_net.h5
-rw-r--r--drivers/net/hyperv/netvsc.c50
-rw-r--r--drivers/net/hyperv/netvsc_drv.c10
3 files changed, 46 insertions, 19 deletions
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index f0b8b3e0ed7c..a10b31664709 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -132,6 +132,8 @@ struct hv_netvsc_packet {
132 132
133 bool is_data_pkt; 133 bool is_data_pkt;
134 bool xmit_more; /* from skb */ 134 bool xmit_more; /* from skb */
135 bool cp_partial; /* partial copy into send buffer */
136
135 u16 vlan_tci; 137 u16 vlan_tci;
136 138
137 u16 q_idx; 139 u16 q_idx;
@@ -146,6 +148,9 @@ struct hv_netvsc_packet {
146 /* This points to the memory after page_buf */ 148 /* This points to the memory after page_buf */
147 struct rndis_message *rndis_msg; 149 struct rndis_message *rndis_msg;
148 150
151 u32 rmsg_size; /* RNDIS header and PPI size */
152 u32 rmsg_pgcnt; /* page count of RNDIS header and PPI */
153
149 u32 total_data_buflen; 154 u32 total_data_buflen;
150 /* Points to the send/receive buffer where the ethernet frame is */ 155 /* Points to the send/receive buffer where the ethernet frame is */
151 void *data; 156 void *data;
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 4d4d497d5762..2e8ad0636b46 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -703,15 +703,18 @@ static u32 netvsc_copy_to_send_buf(struct netvsc_device *net_device,
703 u32 msg_size = 0; 703 u32 msg_size = 0;
704 u32 padding = 0; 704 u32 padding = 0;
705 u32 remain = packet->total_data_buflen % net_device->pkt_align; 705 u32 remain = packet->total_data_buflen % net_device->pkt_align;
706 u32 page_count = packet->cp_partial ? packet->rmsg_pgcnt :
707 packet->page_buf_cnt;
706 708
707 /* Add padding */ 709 /* Add padding */
708 if (packet->is_data_pkt && packet->xmit_more && remain) { 710 if (packet->is_data_pkt && packet->xmit_more && remain &&
711 !packet->cp_partial) {
709 padding = net_device->pkt_align - remain; 712 padding = net_device->pkt_align - remain;
710 packet->rndis_msg->msg_len += padding; 713 packet->rndis_msg->msg_len += padding;
711 packet->total_data_buflen += padding; 714 packet->total_data_buflen += padding;
712 } 715 }
713 716
714 for (i = 0; i < packet->page_buf_cnt; i++) { 717 for (i = 0; i < page_count; i++) {
715 char *src = phys_to_virt(packet->page_buf[i].pfn << PAGE_SHIFT); 718 char *src = phys_to_virt(packet->page_buf[i].pfn << PAGE_SHIFT);
716 u32 offset = packet->page_buf[i].offset; 719 u32 offset = packet->page_buf[i].offset;
717 u32 len = packet->page_buf[i].len; 720 u32 len = packet->page_buf[i].len;
@@ -739,6 +742,7 @@ static inline int netvsc_send_pkt(
739 struct net_device *ndev = net_device->ndev; 742 struct net_device *ndev = net_device->ndev;
740 u64 req_id; 743 u64 req_id;
741 int ret; 744 int ret;
745 struct hv_page_buffer *pgbuf;
742 746
743 nvmsg.hdr.msg_type = NVSP_MSG1_TYPE_SEND_RNDIS_PKT; 747 nvmsg.hdr.msg_type = NVSP_MSG1_TYPE_SEND_RNDIS_PKT;
744 if (packet->is_data_pkt) { 748 if (packet->is_data_pkt) {
@@ -766,8 +770,10 @@ static inline int netvsc_send_pkt(
766 return -ENODEV; 770 return -ENODEV;
767 771
768 if (packet->page_buf_cnt) { 772 if (packet->page_buf_cnt) {
773 pgbuf = packet->cp_partial ? packet->page_buf +
774 packet->rmsg_pgcnt : packet->page_buf;
769 ret = vmbus_sendpacket_pagebuffer(out_channel, 775 ret = vmbus_sendpacket_pagebuffer(out_channel,
770 packet->page_buf, 776 pgbuf,
771 packet->page_buf_cnt, 777 packet->page_buf_cnt,
772 &nvmsg, 778 &nvmsg,
773 sizeof(struct nvsp_message), 779 sizeof(struct nvsp_message),
@@ -824,6 +830,7 @@ int netvsc_send(struct hv_device *device,
824 unsigned long flag; 830 unsigned long flag;
825 struct multi_send_data *msdp; 831 struct multi_send_data *msdp;
826 struct hv_netvsc_packet *msd_send = NULL, *cur_send = NULL; 832 struct hv_netvsc_packet *msd_send = NULL, *cur_send = NULL;
833 bool try_batch;
827 834
828 net_device = get_outbound_net_device(device); 835 net_device = get_outbound_net_device(device);
829 if (!net_device) 836 if (!net_device)
@@ -837,6 +844,7 @@ int netvsc_send(struct hv_device *device,
837 } 844 }
838 packet->channel = out_channel; 845 packet->channel = out_channel;
839 packet->send_buf_index = NETVSC_INVALID_INDEX; 846 packet->send_buf_index = NETVSC_INVALID_INDEX;
847 packet->cp_partial = false;
840 848
841 msdp = &net_device->msd[q_idx]; 849 msdp = &net_device->msd[q_idx];
842 850
@@ -845,12 +853,18 @@ int netvsc_send(struct hv_device *device,
845 if (msdp->pkt) 853 if (msdp->pkt)
846 msd_len = msdp->pkt->total_data_buflen; 854 msd_len = msdp->pkt->total_data_buflen;
847 855
848 if (packet->is_data_pkt && msd_len > 0 && 856 try_batch = packet->is_data_pkt && msd_len > 0 && msdp->count <
849 msdp->count < net_device->max_pkt && 857 net_device->max_pkt;
850 msd_len + pktlen + net_device->pkt_align < 858
859 if (try_batch && msd_len + pktlen + net_device->pkt_align <
851 net_device->send_section_size) { 860 net_device->send_section_size) {
852 section_index = msdp->pkt->send_buf_index; 861 section_index = msdp->pkt->send_buf_index;
853 862
863 } else if (try_batch && msd_len + packet->rmsg_size <
864 net_device->send_section_size) {
865 section_index = msdp->pkt->send_buf_index;
866 packet->cp_partial = true;
867
854 } else if (packet->is_data_pkt && pktlen + net_device->pkt_align < 868 } else if (packet->is_data_pkt && pktlen + net_device->pkt_align <
855 net_device->send_section_size) { 869 net_device->send_section_size) {
856 section_index = netvsc_get_next_send_section(net_device); 870 section_index = netvsc_get_next_send_section(net_device);
@@ -866,22 +880,26 @@ int netvsc_send(struct hv_device *device,
866 netvsc_copy_to_send_buf(net_device, 880 netvsc_copy_to_send_buf(net_device,
867 section_index, msd_len, 881 section_index, msd_len,
868 packet); 882 packet);
869 if (!packet->part_of_skb) {
870 skb = (struct sk_buff *)
871 (unsigned long)
872 packet->send_completion_tid;
873
874 packet->send_completion_tid = 0;
875 }
876 883
877 packet->page_buf_cnt = 0;
878 packet->send_buf_index = section_index; 884 packet->send_buf_index = section_index;
879 packet->total_data_buflen += msd_len; 885
886 if (packet->cp_partial) {
887 packet->page_buf_cnt -= packet->rmsg_pgcnt;
888 packet->total_data_buflen = msd_len + packet->rmsg_size;
889 } else {
890 packet->page_buf_cnt = 0;
891 packet->total_data_buflen += msd_len;
892 if (!packet->part_of_skb) {
893 skb = (struct sk_buff *)(unsigned long)packet->
894 send_completion_tid;
895 packet->send_completion_tid = 0;
896 }
897 }
880 898
881 if (msdp->pkt) 899 if (msdp->pkt)
882 netvsc_xmit_completion(msdp->pkt); 900 netvsc_xmit_completion(msdp->pkt);
883 901
884 if (packet->xmit_more) { 902 if (packet->xmit_more && !packet->cp_partial) {
885 msdp->pkt = packet; 903 msdp->pkt = packet;
886 msdp->count++; 904 msdp->count++;
887 } else { 905 } else {
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 448716787e73..a3a9d3898a6e 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -277,15 +277,16 @@ static u32 fill_pg_buf(struct page *page, u32 offset, u32 len,
277} 277}
278 278
279static u32 init_page_array(void *hdr, u32 len, struct sk_buff *skb, 279static u32 init_page_array(void *hdr, u32 len, struct sk_buff *skb,
280 struct hv_page_buffer *pb) 280 struct hv_netvsc_packet *packet)
281{ 281{
282 struct hv_page_buffer *pb = packet->page_buf;
282 u32 slots_used = 0; 283 u32 slots_used = 0;
283 char *data = skb->data; 284 char *data = skb->data;
284 int frags = skb_shinfo(skb)->nr_frags; 285 int frags = skb_shinfo(skb)->nr_frags;
285 int i; 286 int i;
286 287
287 /* The packet is laid out thus: 288 /* The packet is laid out thus:
288 * 1. hdr 289 * 1. hdr: RNDIS header and PPI
289 * 2. skb linear data 290 * 2. skb linear data
290 * 3. skb fragment data 291 * 3. skb fragment data
291 */ 292 */
@@ -294,6 +295,9 @@ static u32 init_page_array(void *hdr, u32 len, struct sk_buff *skb,
294 offset_in_page(hdr), 295 offset_in_page(hdr),
295 len, &pb[slots_used]); 296 len, &pb[slots_used]);
296 297
298 packet->rmsg_size = len;
299 packet->rmsg_pgcnt = slots_used;
300
297 slots_used += fill_pg_buf(virt_to_page(data), 301 slots_used += fill_pg_buf(virt_to_page(data),
298 offset_in_page(data), 302 offset_in_page(data),
299 skb_headlen(skb), &pb[slots_used]); 303 skb_headlen(skb), &pb[slots_used]);
@@ -578,7 +582,7 @@ do_send:
578 rndis_msg->msg_len += rndis_msg_size; 582 rndis_msg->msg_len += rndis_msg_size;
579 packet->total_data_buflen = rndis_msg->msg_len; 583 packet->total_data_buflen = rndis_msg->msg_len;
580 packet->page_buf_cnt = init_page_array(rndis_msg, rndis_msg_size, 584 packet->page_buf_cnt = init_page_array(rndis_msg, rndis_msg_size,
581 skb, &page_buf[0]); 585 skb, packet);
582 586
583 ret = netvsc_send(net_device_ctx->device_ctx, packet); 587 ret = netvsc_send(net_device_ctx->device_ctx, packet);
584 588