diff options
-rw-r--r-- | drivers/net/hyperv/hyperv_net.h | 5 | ||||
-rw-r--r-- | drivers/net/hyperv/netvsc.c | 50 | ||||
-rw-r--r-- | drivers/net/hyperv/netvsc_drv.c | 10 |
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 | ||
279 | static u32 init_page_array(void *hdr, u32 len, struct sk_buff *skb, | 279 | static 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 | ||