aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-03-10 15:52:17 -0400
committerDavid S. Miller <davem@davemloft.net>2014-03-10 15:52:17 -0400
commite3ca64948b50d05304a33ad8c4332e2a748e9401 (patch)
tree5420a2dc396c09173940c73d761f0aea0fd6bed5
parent3ee2f8ce1ab8f235bda164295fa0cf39ec1c2400 (diff)
parent77bf5487946254798ed7f265877939c703189f1e (diff)
Merge branch 'hyperv-next'
K. Y. Srinivasan says: ==================== Drivers: net: hyperv: Enable various offloads This patch set enables both checksum as well as segmentation offload. As part of this effort I have enabled scatter gather I/O a well. In version 2 of these patches, I addressed comments from David Miller and Dan Carpenter. In this version I have addressed the latest comments from David Miller. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/hyperv/hyperv_net.h145
-rw-r--r--drivers/net/hyperv/netvsc_drv.c333
-rw-r--r--drivers/net/hyperv/rndis_filter.c150
3 files changed, 504 insertions, 124 deletions
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 39fc230f5c20..7d06b4959383 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -30,6 +30,7 @@
30 30
31/* Fwd declaration */ 31/* Fwd declaration */
32struct hv_netvsc_packet; 32struct hv_netvsc_packet;
33struct ndis_tcp_ip_checksum_info;
33 34
34/* Represent the xfer page packet which contains 1 or more netvsc packet */ 35/* Represent the xfer page packet which contains 1 or more netvsc packet */
35struct xferpage_packet { 36struct xferpage_packet {
@@ -73,7 +74,7 @@ struct hv_netvsc_packet {
73 } completion; 74 } completion;
74 75
75 /* This points to the memory after page_buf */ 76 /* This points to the memory after page_buf */
76 void *extension; 77 struct rndis_message *rndis_msg;
77 78
78 u32 total_data_buflen; 79 u32 total_data_buflen;
79 /* Points to the send/receive buffer where the ethernet frame is */ 80 /* Points to the send/receive buffer where the ethernet frame is */
@@ -117,7 +118,8 @@ int netvsc_send(struct hv_device *device,
117void netvsc_linkstatus_callback(struct hv_device *device_obj, 118void netvsc_linkstatus_callback(struct hv_device *device_obj,
118 unsigned int status); 119 unsigned int status);
119int netvsc_recv_callback(struct hv_device *device_obj, 120int netvsc_recv_callback(struct hv_device *device_obj,
120 struct hv_netvsc_packet *packet); 121 struct hv_netvsc_packet *packet,
122 struct ndis_tcp_ip_checksum_info *csum_info);
121int rndis_filter_open(struct hv_device *dev); 123int rndis_filter_open(struct hv_device *dev);
122int rndis_filter_close(struct hv_device *dev); 124int rndis_filter_close(struct hv_device *dev);
123int rndis_filter_device_add(struct hv_device *dev, 125int rndis_filter_device_add(struct hv_device *dev,
@@ -126,11 +128,6 @@ void rndis_filter_device_remove(struct hv_device *dev);
126int rndis_filter_receive(struct hv_device *dev, 128int rndis_filter_receive(struct hv_device *dev,
127 struct hv_netvsc_packet *pkt); 129 struct hv_netvsc_packet *pkt);
128 130
129
130
131int rndis_filter_send(struct hv_device *dev,
132 struct hv_netvsc_packet *pkt);
133
134int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter); 131int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter);
135int rndis_filter_set_device_mac(struct hv_device *hdev, char *mac); 132int rndis_filter_set_device_mac(struct hv_device *hdev, char *mac);
136 133
@@ -726,9 +723,133 @@ struct ndis_pkt_8021q_info {
726 }; 723 };
727}; 724};
728 725
726struct ndis_oject_header {
727 u8 type;
728 u8 revision;
729 u16 size;
730};
731
732#define NDIS_OBJECT_TYPE_DEFAULT 0x80
733#define NDIS_OFFLOAD_PARAMETERS_REVISION_3 3
734#define NDIS_OFFLOAD_PARAMETERS_NO_CHANGE 0
735#define NDIS_OFFLOAD_PARAMETERS_LSOV2_DISABLED 1
736#define NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED 2
737#define NDIS_OFFLOAD_PARAMETERS_LSOV1_ENABLED 2
738#define NDIS_OFFLOAD_PARAMETERS_RSC_DISABLED 1
739#define NDIS_OFFLOAD_PARAMETERS_RSC_ENABLED 2
740#define NDIS_OFFLOAD_PARAMETERS_TX_RX_DISABLED 1
741#define NDIS_OFFLOAD_PARAMETERS_TX_ENABLED_RX_DISABLED 2
742#define NDIS_OFFLOAD_PARAMETERS_RX_ENABLED_TX_DISABLED 3
743#define NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED 4
744
745#define NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE 1
746#define NDIS_TCP_LARGE_SEND_OFFLOAD_IPV4 0
747#define NDIS_TCP_LARGE_SEND_OFFLOAD_IPV6 1
748
749/*
750 * New offload OIDs for NDIS 6
751 */
752#define OID_TCP_OFFLOAD_CURRENT_CONFIG 0xFC01020B /* query only */
753#define OID_TCP_OFFLOAD_PARAMETERS 0xFC01020C /* set only */
754#define OID_TCP_OFFLOAD_HARDWARE_CAPABILITIES 0xFC01020D/* query only */
755#define OID_TCP_CONNECTION_OFFLOAD_CURRENT_CONFIG 0xFC01020E /* query only */
756#define OID_TCP_CONNECTION_OFFLOAD_HARDWARE_CAPABILITIES 0xFC01020F /* query */
757#define OID_OFFLOAD_ENCAPSULATION 0x0101010A /* set/query */
758
759struct ndis_offload_params {
760 struct ndis_oject_header header;
761 u8 ip_v4_csum;
762 u8 tcp_ip_v4_csum;
763 u8 udp_ip_v4_csum;
764 u8 tcp_ip_v6_csum;
765 u8 udp_ip_v6_csum;
766 u8 lso_v1;
767 u8 ip_sec_v1;
768 u8 lso_v2_ipv4;
769 u8 lso_v2_ipv6;
770 u8 tcp_connection_ip_v4;
771 u8 tcp_connection_ip_v6;
772 u32 flags;
773 u8 ip_sec_v2;
774 u8 ip_sec_v2_ip_v4;
775 struct {
776 u8 rsc_ip_v4;
777 u8 rsc_ip_v6;
778 };
779 struct {
780 u8 encapsulated_packet_task_offload;
781 u8 encapsulation_types;
782 };
783};
784
785struct ndis_tcp_ip_checksum_info {
786 union {
787 struct {
788 u32 is_ipv4:1;
789 u32 is_ipv6:1;
790 u32 tcp_checksum:1;
791 u32 udp_checksum:1;
792 u32 ip_header_checksum:1;
793 u32 reserved:11;
794 u32 tcp_header_offset:10;
795 } transmit;
796 struct {
797 u32 tcp_checksum_failed:1;
798 u32 udp_checksum_failed:1;
799 u32 ip_checksum_failed:1;
800 u32 tcp_checksum_succeeded:1;
801 u32 udp_checksum_succeeded:1;
802 u32 ip_checksum_succeeded:1;
803 u32 loopback:1;
804 u32 tcp_checksum_value_invalid:1;
805 u32 ip_checksum_value_invalid:1;
806 } receive;
807 u32 value;
808 };
809};
810
811struct ndis_tcp_lso_info {
812 union {
813 struct {
814 u32 unused:30;
815 u32 type:1;
816 u32 reserved2:1;
817 } transmit;
818 struct {
819 u32 mss:20;
820 u32 tcp_header_offset:10;
821 u32 type:1;
822 u32 reserved2:1;
823 } lso_v1_transmit;
824 struct {
825 u32 tcp_payload:30;
826 u32 type:1;
827 u32 reserved2:1;
828 } lso_v1_transmit_complete;
829 struct {
830 u32 mss:20;
831 u32 tcp_header_offset:10;
832 u32 type:1;
833 u32 ip_version:1;
834 } lso_v2_transmit;
835 struct {
836 u32 reserved:30;
837 u32 type:1;
838 u32 reserved2:1;
839 } lso_v2_transmit_complete;
840 u32 value;
841 };
842};
843
729#define NDIS_VLAN_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \ 844#define NDIS_VLAN_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \
730 sizeof(struct ndis_pkt_8021q_info)) 845 sizeof(struct ndis_pkt_8021q_info))
731 846
847#define NDIS_CSUM_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \
848 sizeof(struct ndis_tcp_ip_checksum_info))
849
850#define NDIS_LSO_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \
851 sizeof(struct ndis_tcp_lso_info))
852
732/* Format of Information buffer passed in a SetRequest for the OID */ 853/* Format of Information buffer passed in a SetRequest for the OID */
733/* OID_GEN_RNDIS_CONFIG_PARAMETER. */ 854/* OID_GEN_RNDIS_CONFIG_PARAMETER. */
734struct rndis_config_parameter_info { 855struct rndis_config_parameter_info {
@@ -954,6 +1075,16 @@ struct rndis_message {
954#define NDIS_PACKET_TYPE_FUNCTIONAL 0x00000400 1075#define NDIS_PACKET_TYPE_FUNCTIONAL 0x00000400
955#define NDIS_PACKET_TYPE_MAC_FRAME 0x00000800 1076#define NDIS_PACKET_TYPE_MAC_FRAME 0x00000800
956 1077
1078#define INFO_IPV4 2
1079#define INFO_IPV6 4
1080#define INFO_TCP 2
1081#define INFO_UDP 4
1082
1083#define TRANSPORT_INFO_NOT_IP 0
1084#define TRANSPORT_INFO_IPV4_TCP ((INFO_IPV4 << 16) | INFO_TCP)
1085#define TRANSPORT_INFO_IPV4_UDP ((INFO_IPV4 << 16) | INFO_UDP)
1086#define TRANSPORT_INFO_IPV6_TCP ((INFO_IPV6 << 16) | INFO_TCP)
1087#define TRANSPORT_INFO_IPV6_UDP ((INFO_IPV6 << 16) | INFO_UDP)
957 1088
958 1089
959#endif /* _HYPERV_NET_H */ 1090#endif /* _HYPERV_NET_H */
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 9ef6be90a81c..3d069901e6d9 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -128,6 +128,27 @@ static int netvsc_close(struct net_device *net)
128 return ret; 128 return ret;
129} 129}
130 130
131static void *init_ppi_data(struct rndis_message *msg, u32 ppi_size,
132 int pkt_type)
133{
134 struct rndis_packet *rndis_pkt;
135 struct rndis_per_packet_info *ppi;
136
137 rndis_pkt = &msg->msg.pkt;
138 rndis_pkt->data_offset += ppi_size;
139
140 ppi = (struct rndis_per_packet_info *)((void *)rndis_pkt +
141 rndis_pkt->per_pkt_info_offset + rndis_pkt->per_pkt_info_len);
142
143 ppi->size = ppi_size;
144 ppi->type = pkt_type;
145 ppi->ppi_offset = sizeof(struct rndis_per_packet_info);
146
147 rndis_pkt->per_pkt_info_len += ppi_size;
148
149 return ppi;
150}
151
131static void netvsc_xmit_completion(void *context) 152static void netvsc_xmit_completion(void *context)
132{ 153{
133 struct hv_netvsc_packet *packet = (struct hv_netvsc_packet *)context; 154 struct hv_netvsc_packet *packet = (struct hv_netvsc_packet *)context;
@@ -140,21 +161,163 @@ static void netvsc_xmit_completion(void *context)
140 dev_kfree_skb_any(skb); 161 dev_kfree_skb_any(skb);
141} 162}
142 163
164static u32 fill_pg_buf(struct page *page, u32 offset, u32 len,
165 struct hv_page_buffer *pb)
166{
167 int j = 0;
168
169 /* Deal with compund pages by ignoring unused part
170 * of the page.
171 */
172 page += (offset >> PAGE_SHIFT);
173 offset &= ~PAGE_MASK;
174
175 while (len > 0) {
176 unsigned long bytes;
177
178 bytes = PAGE_SIZE - offset;
179 if (bytes > len)
180 bytes = len;
181 pb[j].pfn = page_to_pfn(page);
182 pb[j].offset = offset;
183 pb[j].len = bytes;
184
185 offset += bytes;
186 len -= bytes;
187
188 if (offset == PAGE_SIZE && len) {
189 page++;
190 offset = 0;
191 j++;
192 }
193 }
194
195 return j + 1;
196}
197
198static u32 init_page_array(void *hdr, u32 len, struct sk_buff *skb,
199 struct hv_page_buffer *pb)
200{
201 u32 slots_used = 0;
202 char *data = skb->data;
203 int frags = skb_shinfo(skb)->nr_frags;
204 int i;
205
206 /* The packet is laid out thus:
207 * 1. hdr
208 * 2. skb linear data
209 * 3. skb fragment data
210 */
211 if (hdr != NULL)
212 slots_used += fill_pg_buf(virt_to_page(hdr),
213 offset_in_page(hdr),
214 len, &pb[slots_used]);
215
216 slots_used += fill_pg_buf(virt_to_page(data),
217 offset_in_page(data),
218 skb_headlen(skb), &pb[slots_used]);
219
220 for (i = 0; i < frags; i++) {
221 skb_frag_t *frag = skb_shinfo(skb)->frags + i;
222
223 slots_used += fill_pg_buf(skb_frag_page(frag),
224 frag->page_offset,
225 skb_frag_size(frag), &pb[slots_used]);
226 }
227 return slots_used;
228}
229
230static int count_skb_frag_slots(struct sk_buff *skb)
231{
232 int i, frags = skb_shinfo(skb)->nr_frags;
233 int pages = 0;
234
235 for (i = 0; i < frags; i++) {
236 skb_frag_t *frag = skb_shinfo(skb)->frags + i;
237 unsigned long size = skb_frag_size(frag);
238 unsigned long offset = frag->page_offset;
239
240 /* Skip unused frames from start of page */
241 offset &= ~PAGE_MASK;
242 pages += PFN_UP(offset + size);
243 }
244 return pages;
245}
246
247static int netvsc_get_slots(struct sk_buff *skb)
248{
249 char *data = skb->data;
250 unsigned int offset = offset_in_page(data);
251 unsigned int len = skb_headlen(skb);
252 int slots;
253 int frag_slots;
254
255 slots = DIV_ROUND_UP(offset + len, PAGE_SIZE);
256 frag_slots = count_skb_frag_slots(skb);
257 return slots + frag_slots;
258}
259
260static u32 get_net_transport_info(struct sk_buff *skb, u32 *trans_off)
261{
262 u32 ret_val = TRANSPORT_INFO_NOT_IP;
263
264 if ((eth_hdr(skb)->h_proto != htons(ETH_P_IP)) &&
265 (eth_hdr(skb)->h_proto != htons(ETH_P_IPV6))) {
266 goto not_ip;
267 }
268
269 *trans_off = skb_transport_offset(skb);
270
271 if ((eth_hdr(skb)->h_proto == htons(ETH_P_IP))) {
272 struct iphdr *iphdr = ip_hdr(skb);
273
274 if (iphdr->protocol == IPPROTO_TCP)
275 ret_val = TRANSPORT_INFO_IPV4_TCP;
276 else if (iphdr->protocol == IPPROTO_UDP)
277 ret_val = TRANSPORT_INFO_IPV4_UDP;
278 } else {
279 if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
280 ret_val = TRANSPORT_INFO_IPV6_TCP;
281 else if (ipv6_hdr(skb)->nexthdr == IPPROTO_UDP)
282 ret_val = TRANSPORT_INFO_IPV6_UDP;
283 }
284
285not_ip:
286 return ret_val;
287}
288
143static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) 289static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
144{ 290{
145 struct net_device_context *net_device_ctx = netdev_priv(net); 291 struct net_device_context *net_device_ctx = netdev_priv(net);
146 struct hv_netvsc_packet *packet; 292 struct hv_netvsc_packet *packet;
147 int ret; 293 int ret;
148 unsigned int i, num_pages, npg_data; 294 unsigned int num_data_pgs;
149 295 struct rndis_message *rndis_msg;
150 /* Add multipages for skb->data and additional 2 for RNDIS */ 296 struct rndis_packet *rndis_pkt;
151 npg_data = (((unsigned long)skb->data + skb_headlen(skb) - 1) 297 u32 rndis_msg_size;
152 >> PAGE_SHIFT) - ((unsigned long)skb->data >> PAGE_SHIFT) + 1; 298 bool isvlan;
153 num_pages = skb_shinfo(skb)->nr_frags + npg_data + 2; 299 struct rndis_per_packet_info *ppi;
300 struct ndis_tcp_ip_checksum_info *csum_info;
301 struct ndis_tcp_lso_info *lso_info;
302 int hdr_offset;
303 u32 net_trans_info;
304
305
306 /* We will atmost need two pages to describe the rndis
307 * header. We can only transmit MAX_PAGE_BUFFER_COUNT number
308 * of pages in a single packet.
309 */
310 num_data_pgs = netvsc_get_slots(skb) + 2;
311 if (num_data_pgs > MAX_PAGE_BUFFER_COUNT) {
312 netdev_err(net, "Packet too big: %u\n", skb->len);
313 dev_kfree_skb(skb);
314 net->stats.tx_dropped++;
315 return NETDEV_TX_OK;
316 }
154 317
155 /* Allocate a netvsc packet based on # of frags. */ 318 /* Allocate a netvsc packet based on # of frags. */
156 packet = kzalloc(sizeof(struct hv_netvsc_packet) + 319 packet = kzalloc(sizeof(struct hv_netvsc_packet) +
157 (num_pages * sizeof(struct hv_page_buffer)) + 320 (num_data_pgs * sizeof(struct hv_page_buffer)) +
158 sizeof(struct rndis_message) + 321 sizeof(struct rndis_message) +
159 NDIS_VLAN_PPI_SIZE, GFP_ATOMIC); 322 NDIS_VLAN_PPI_SIZE, GFP_ATOMIC);
160 if (!packet) { 323 if (!packet) {
@@ -168,53 +331,111 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
168 331
169 packet->vlan_tci = skb->vlan_tci; 332 packet->vlan_tci = skb->vlan_tci;
170 333
171 packet->extension = (void *)(unsigned long)packet + 334 packet->is_data_pkt = true;
335 packet->total_data_buflen = skb->len;
336
337 packet->rndis_msg = (struct rndis_message *)((unsigned long)packet +
172 sizeof(struct hv_netvsc_packet) + 338 sizeof(struct hv_netvsc_packet) +
173 (num_pages * sizeof(struct hv_page_buffer)); 339 (num_data_pgs * sizeof(struct hv_page_buffer)));
340
341 /* Set the completion routine */
342 packet->completion.send.send_completion = netvsc_xmit_completion;
343 packet->completion.send.send_completion_ctx = packet;
344 packet->completion.send.send_completion_tid = (unsigned long)skb;
174 345
175 /* If the rndis msg goes beyond 1 page, we will add 1 later */ 346 isvlan = packet->vlan_tci & VLAN_TAG_PRESENT;
176 packet->page_buf_cnt = num_pages - 1; 347
348 /* Add the rndis header */
349 rndis_msg = packet->rndis_msg;
350 rndis_msg->ndis_msg_type = RNDIS_MSG_PACKET;
351 rndis_msg->msg_len = packet->total_data_buflen;
352 rndis_pkt = &rndis_msg->msg.pkt;
353 rndis_pkt->data_offset = sizeof(struct rndis_packet);
354 rndis_pkt->data_len = packet->total_data_buflen;
355 rndis_pkt->per_pkt_info_offset = sizeof(struct rndis_packet);
356
357 rndis_msg_size = RNDIS_MESSAGE_SIZE(struct rndis_packet);
358
359 if (isvlan) {
360 struct ndis_pkt_8021q_info *vlan;
361
362 rndis_msg_size += NDIS_VLAN_PPI_SIZE;
363 ppi = init_ppi_data(rndis_msg, NDIS_VLAN_PPI_SIZE,
364 IEEE_8021Q_INFO);
365 vlan = (struct ndis_pkt_8021q_info *)((void *)ppi +
366 ppi->ppi_offset);
367 vlan->vlanid = packet->vlan_tci & VLAN_VID_MASK;
368 vlan->pri = (packet->vlan_tci & VLAN_PRIO_MASK) >>
369 VLAN_PRIO_SHIFT;
370 }
177 371
178 /* Initialize it from the skb */ 372 net_trans_info = get_net_transport_info(skb, &hdr_offset);
179 packet->total_data_buflen = skb->len; 373 if (net_trans_info == TRANSPORT_INFO_NOT_IP)
374 goto do_send;
375
376 /*
377 * Setup the sendside checksum offload only if this is not a
378 * GSO packet.
379 */
380 if (skb_is_gso(skb))
381 goto do_lso;
382
383 rndis_msg_size += NDIS_CSUM_PPI_SIZE;
384 ppi = init_ppi_data(rndis_msg, NDIS_CSUM_PPI_SIZE,
385 TCPIP_CHKSUM_PKTINFO);
386
387 csum_info = (struct ndis_tcp_ip_checksum_info *)((void *)ppi +
388 ppi->ppi_offset);
180 389
181 /* Start filling in the page buffers starting after RNDIS buffer. */ 390 if (net_trans_info & (INFO_IPV4 << 16))
182 packet->page_buf[1].pfn = virt_to_phys(skb->data) >> PAGE_SHIFT; 391 csum_info->transmit.is_ipv4 = 1;
183 packet->page_buf[1].offset
184 = (unsigned long)skb->data & (PAGE_SIZE - 1);
185 if (npg_data == 1)
186 packet->page_buf[1].len = skb_headlen(skb);
187 else 392 else
188 packet->page_buf[1].len = PAGE_SIZE 393 csum_info->transmit.is_ipv6 = 1;
189 - packet->page_buf[1].offset; 394
190 395 if (net_trans_info & INFO_TCP) {
191 for (i = 2; i <= npg_data; i++) { 396 csum_info->transmit.tcp_checksum = 1;
192 packet->page_buf[i].pfn = virt_to_phys(skb->data 397 csum_info->transmit.tcp_header_offset = hdr_offset;
193 + PAGE_SIZE * (i-1)) >> PAGE_SHIFT; 398 } else if (net_trans_info & INFO_UDP) {
194 packet->page_buf[i].offset = 0; 399 csum_info->transmit.udp_checksum = 1;
195 packet->page_buf[i].len = PAGE_SIZE;
196 } 400 }
197 if (npg_data > 1) 401 goto do_send;
198 packet->page_buf[npg_data].len = (((unsigned long)skb->data 402
199 + skb_headlen(skb) - 1) & (PAGE_SIZE - 1)) + 1; 403do_lso:
200 404 rndis_msg_size += NDIS_LSO_PPI_SIZE;
201 /* Additional fragments are after SKB data */ 405 ppi = init_ppi_data(rndis_msg, NDIS_LSO_PPI_SIZE,
202 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 406 TCP_LARGESEND_PKTINFO);
203 const skb_frag_t *f = &skb_shinfo(skb)->frags[i]; 407
204 408 lso_info = (struct ndis_tcp_lso_info *)((void *)ppi +
205 packet->page_buf[i+npg_data+1].pfn = 409 ppi->ppi_offset);
206 page_to_pfn(skb_frag_page(f)); 410
207 packet->page_buf[i+npg_data+1].offset = f->page_offset; 411 lso_info->lso_v2_transmit.type = NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE;
208 packet->page_buf[i+npg_data+1].len = skb_frag_size(f); 412 if (net_trans_info & (INFO_IPV4 << 16)) {
413 lso_info->lso_v2_transmit.ip_version =
414 NDIS_TCP_LARGE_SEND_OFFLOAD_IPV4;
415 ip_hdr(skb)->tot_len = 0;
416 ip_hdr(skb)->check = 0;
417 tcp_hdr(skb)->check =
418 ~csum_tcpudp_magic(ip_hdr(skb)->saddr,
419 ip_hdr(skb)->daddr, 0, IPPROTO_TCP, 0);
420 } else {
421 lso_info->lso_v2_transmit.ip_version =
422 NDIS_TCP_LARGE_SEND_OFFLOAD_IPV6;
423 ipv6_hdr(skb)->payload_len = 0;
424 tcp_hdr(skb)->check =
425 ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
426 &ipv6_hdr(skb)->daddr, 0, IPPROTO_TCP, 0);
209 } 427 }
428 lso_info->lso_v2_transmit.tcp_header_offset = hdr_offset;
429 lso_info->lso_v2_transmit.mss = skb_shinfo(skb)->gso_size;
210 430
211 /* Set the completion routine */ 431do_send:
212 packet->completion.send.send_completion = netvsc_xmit_completion; 432 /* Start filling in the page buffers with the rndis hdr */
213 packet->completion.send.send_completion_ctx = packet; 433 rndis_msg->msg_len += rndis_msg_size;
214 packet->completion.send.send_completion_tid = (unsigned long)skb; 434 packet->page_buf_cnt = init_page_array(rndis_msg, rndis_msg_size,
435 skb, &packet->page_buf[0]);
436
437 ret = netvsc_send(net_device_ctx->device_ctx, packet);
215 438
216 ret = rndis_filter_send(net_device_ctx->device_ctx,
217 packet);
218 if (ret == 0) { 439 if (ret == 0) {
219 net->stats.tx_bytes += skb->len; 440 net->stats.tx_bytes += skb->len;
220 net->stats.tx_packets++; 441 net->stats.tx_packets++;
@@ -264,7 +485,8 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj,
264 * "wire" on the specified device. 485 * "wire" on the specified device.
265 */ 486 */
266int netvsc_recv_callback(struct hv_device *device_obj, 487int netvsc_recv_callback(struct hv_device *device_obj,
267 struct hv_netvsc_packet *packet) 488 struct hv_netvsc_packet *packet,
489 struct ndis_tcp_ip_checksum_info *csum_info)
268{ 490{
269 struct net_device *net; 491 struct net_device *net;
270 struct sk_buff *skb; 492 struct sk_buff *skb;
@@ -291,7 +513,17 @@ int netvsc_recv_callback(struct hv_device *device_obj,
291 packet->total_data_buflen); 513 packet->total_data_buflen);
292 514
293 skb->protocol = eth_type_trans(skb, net); 515 skb->protocol = eth_type_trans(skb, net);
294 skb->ip_summed = CHECKSUM_NONE; 516 if (csum_info) {
517 /* We only look at the IP checksum here.
518 * Should we be dropping the packet if checksum
519 * failed? How do we deal with other checksums - TCP/UDP?
520 */
521 if (csum_info->receive.ip_checksum_succeeded)
522 skb->ip_summed = CHECKSUM_UNNECESSARY;
523 else
524 skb->ip_summed = CHECKSUM_NONE;
525 }
526
295 if (packet->vlan_tci & VLAN_TAG_PRESENT) 527 if (packet->vlan_tci & VLAN_TAG_PRESENT)
296 __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), 528 __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
297 packet->vlan_tci); 529 packet->vlan_tci);
@@ -450,9 +682,10 @@ static int netvsc_probe(struct hv_device *dev,
450 682
451 net->netdev_ops = &device_ops; 683 net->netdev_ops = &device_ops;
452 684
453 /* TODO: Add GSO and Checksum offload */ 685 net->hw_features = NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_IP_CSUM |
454 net->hw_features = 0; 686 NETIF_F_TSO;
455 net->features = NETIF_F_HW_VLAN_CTAG_TX; 687 net->features = NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_SG | NETIF_F_RXCSUM |
688 NETIF_F_IP_CSUM | NETIF_F_TSO;
456 689
457 SET_ETHTOOL_OPS(net, &ethtool_ops); 690 SET_ETHTOOL_OPS(net, &ethtool_ops);
458 SET_NETDEV_DEV(net, &dev->device); 691 SET_NETDEV_DEV(net, &dev->device);
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index f0cc8ef21e1c..54553df74cd2 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -350,6 +350,7 @@ static void rndis_filter_receive_data(struct rndis_device *dev,
350 struct rndis_packet *rndis_pkt; 350 struct rndis_packet *rndis_pkt;
351 u32 data_offset; 351 u32 data_offset;
352 struct ndis_pkt_8021q_info *vlan; 352 struct ndis_pkt_8021q_info *vlan;
353 struct ndis_tcp_ip_checksum_info *csum_info;
353 354
354 rndis_pkt = &msg->msg.pkt; 355 rndis_pkt = &msg->msg.pkt;
355 356
@@ -388,7 +389,8 @@ static void rndis_filter_receive_data(struct rndis_device *dev,
388 pkt->vlan_tci = 0; 389 pkt->vlan_tci = 0;
389 } 390 }
390 391
391 netvsc_recv_callback(dev->net_dev->dev, pkt); 392 csum_info = rndis_get_ppi(rndis_pkt, TCPIP_CHKSUM_PKTINFO);
393 netvsc_recv_callback(dev->net_dev->dev, pkt, csum_info);
392} 394}
393 395
394int rndis_filter_receive(struct hv_device *dev, 396int rndis_filter_receive(struct hv_device *dev,
@@ -607,6 +609,61 @@ cleanup:
607 return ret; 609 return ret;
608} 610}
609 611
612int rndis_filter_set_offload_params(struct hv_device *hdev,
613 struct ndis_offload_params *req_offloads)
614{
615 struct netvsc_device *nvdev = hv_get_drvdata(hdev);
616 struct rndis_device *rdev = nvdev->extension;
617 struct net_device *ndev = nvdev->ndev;
618 struct rndis_request *request;
619 struct rndis_set_request *set;
620 struct ndis_offload_params *offload_params;
621 struct rndis_set_complete *set_complete;
622 u32 extlen = sizeof(struct ndis_offload_params);
623 int ret, t;
624
625 request = get_rndis_request(rdev, RNDIS_MSG_SET,
626 RNDIS_MESSAGE_SIZE(struct rndis_set_request) + extlen);
627 if (!request)
628 return -ENOMEM;
629
630 set = &request->request_msg.msg.set_req;
631 set->oid = OID_TCP_OFFLOAD_PARAMETERS;
632 set->info_buflen = extlen;
633 set->info_buf_offset = sizeof(struct rndis_set_request);
634 set->dev_vc_handle = 0;
635
636 offload_params = (struct ndis_offload_params *)((ulong)set +
637 set->info_buf_offset);
638 *offload_params = *req_offloads;
639 offload_params->header.type = NDIS_OBJECT_TYPE_DEFAULT;
640 offload_params->header.revision = NDIS_OFFLOAD_PARAMETERS_REVISION_3;
641 offload_params->header.size = extlen;
642
643 ret = rndis_filter_send_request(rdev, request);
644 if (ret != 0)
645 goto cleanup;
646
647 t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
648 if (t == 0) {
649 netdev_err(ndev, "timeout before we got aOFFLOAD set response...\n");
650 /* can't put_rndis_request, since we may still receive a
651 * send-completion.
652 */
653 return -EBUSY;
654 } else {
655 set_complete = &request->response_msg.msg.set_complete;
656 if (set_complete->status != RNDIS_STATUS_SUCCESS) {
657 netdev_err(ndev, "Fail to set MAC on host side:0x%x\n",
658 set_complete->status);
659 ret = -EINVAL;
660 }
661 }
662
663cleanup:
664 put_rndis_request(rdev, request);
665 return ret;
666}
610 667
611static int rndis_filter_query_device_link_status(struct rndis_device *dev) 668static int rndis_filter_query_device_link_status(struct rndis_device *dev)
612{ 669{
@@ -807,6 +864,7 @@ int rndis_filter_device_add(struct hv_device *dev,
807 struct netvsc_device *net_device; 864 struct netvsc_device *net_device;
808 struct rndis_device *rndis_device; 865 struct rndis_device *rndis_device;
809 struct netvsc_device_info *device_info = additional_info; 866 struct netvsc_device_info *device_info = additional_info;
867 struct ndis_offload_params offloads;
810 868
811 rndis_device = get_rndis_device(); 869 rndis_device = get_rndis_device();
812 if (!rndis_device) 870 if (!rndis_device)
@@ -846,6 +904,26 @@ int rndis_filter_device_add(struct hv_device *dev,
846 904
847 memcpy(device_info->mac_adr, rndis_device->hw_mac_adr, ETH_ALEN); 905 memcpy(device_info->mac_adr, rndis_device->hw_mac_adr, ETH_ALEN);
848 906
907 /* Turn on the offloads; the host supports all of the relevant
908 * offloads.
909 */
910 memset(&offloads, 0, sizeof(struct ndis_offload_params));
911 /* A value of zero means "no change"; now turn on what we
912 * want.
913 */
914 offloads.ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
915 offloads.tcp_ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
916 offloads.udp_ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
917 offloads.tcp_ip_v6_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
918 offloads.udp_ip_v6_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
919 offloads.lso_v2_ipv4 = NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED;
920
921
922 ret = rndis_filter_set_offload_params(dev, &offloads);
923 if (ret)
924 goto err_dev_remv;
925
926
849 rndis_filter_query_device_link_status(rndis_device); 927 rndis_filter_query_device_link_status(rndis_device);
850 928
851 device_info->link_state = rndis_device->link_state; 929 device_info->link_state = rndis_device->link_state;
@@ -855,6 +933,10 @@ int rndis_filter_device_add(struct hv_device *dev,
855 device_info->link_state ? "down" : "up"); 933 device_info->link_state ? "down" : "up");
856 934
857 return ret; 935 return ret;
936
937err_dev_remv:
938 rndis_filter_device_remove(dev);
939 return ret;
858} 940}
859 941
860void rndis_filter_device_remove(struct hv_device *dev) 942void rndis_filter_device_remove(struct hv_device *dev)
@@ -891,69 +973,3 @@ int rndis_filter_close(struct hv_device *dev)
891 973
892 return rndis_filter_close_device(nvdev->extension); 974 return rndis_filter_close_device(nvdev->extension);
893} 975}
894
895int rndis_filter_send(struct hv_device *dev,
896 struct hv_netvsc_packet *pkt)
897{
898 struct rndis_message *rndis_msg;
899 struct rndis_packet *rndis_pkt;
900 u32 rndis_msg_size;
901 bool isvlan = pkt->vlan_tci & VLAN_TAG_PRESENT;
902
903 /* Add the rndis header */
904 rndis_msg = (struct rndis_message *)pkt->extension;
905
906 rndis_msg_size = RNDIS_MESSAGE_SIZE(struct rndis_packet);
907 if (isvlan)
908 rndis_msg_size += NDIS_VLAN_PPI_SIZE;
909
910 rndis_msg->ndis_msg_type = RNDIS_MSG_PACKET;
911 rndis_msg->msg_len = pkt->total_data_buflen +
912 rndis_msg_size;
913
914 rndis_pkt = &rndis_msg->msg.pkt;
915 rndis_pkt->data_offset = sizeof(struct rndis_packet);
916 if (isvlan)
917 rndis_pkt->data_offset += NDIS_VLAN_PPI_SIZE;
918 rndis_pkt->data_len = pkt->total_data_buflen;
919
920 if (isvlan) {
921 struct rndis_per_packet_info *ppi;
922 struct ndis_pkt_8021q_info *vlan;
923
924 rndis_pkt->per_pkt_info_offset = sizeof(struct rndis_packet);
925 rndis_pkt->per_pkt_info_len = NDIS_VLAN_PPI_SIZE;
926
927 ppi = (struct rndis_per_packet_info *)((ulong)rndis_pkt +
928 rndis_pkt->per_pkt_info_offset);
929 ppi->size = NDIS_VLAN_PPI_SIZE;
930 ppi->type = IEEE_8021Q_INFO;
931 ppi->ppi_offset = sizeof(struct rndis_per_packet_info);
932
933 vlan = (struct ndis_pkt_8021q_info *)((ulong)ppi +
934 ppi->ppi_offset);
935 vlan->vlanid = pkt->vlan_tci & VLAN_VID_MASK;
936 vlan->pri = (pkt->vlan_tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
937 }
938
939 pkt->is_data_pkt = true;
940 pkt->page_buf[0].pfn = virt_to_phys(rndis_msg) >> PAGE_SHIFT;
941 pkt->page_buf[0].offset =
942 (unsigned long)rndis_msg & (PAGE_SIZE-1);
943 pkt->page_buf[0].len = rndis_msg_size;
944
945 /* Add one page_buf if the rndis msg goes beyond page boundary */
946 if (pkt->page_buf[0].offset + rndis_msg_size > PAGE_SIZE) {
947 int i;
948 for (i = pkt->page_buf_cnt; i > 1; i--)
949 pkt->page_buf[i] = pkt->page_buf[i-1];
950 pkt->page_buf_cnt++;
951 pkt->page_buf[0].len = PAGE_SIZE - pkt->page_buf[0].offset;
952 pkt->page_buf[1].pfn = virt_to_phys((void *)((ulong)
953 rndis_msg + pkt->page_buf[0].len)) >> PAGE_SHIFT;
954 pkt->page_buf[1].offset = 0;
955 pkt->page_buf[1].len = rndis_msg_size - pkt->page_buf[0].len;
956 }
957
958 return netvsc_send(dev, pkt);
959}