aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@redhat.com>2014-10-07 10:39:48 -0400
committerMichael S. Tsirkin <mst@redhat.com>2014-12-09 05:05:26 -0500
commitfdd819b21576c361bf0dcdd9522df4ccabf7aaa8 (patch)
tree39c8178b2f4d6d399665dbd449ebfad8f46955ec
parentb3bb62d11950eb6ac87403cacd667f84fa9495bc (diff)
virtio_net: v1.0 endianness
Based on patches by Rusty Russell, Cornelia Huck. Note: more code changes are needed for 1.0 support (due to different header size). So we don't advertize support for 1.0 yet. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
-rw-r--r--drivers/net/virtio_net.c33
-rw-r--r--include/uapi/linux/virtio_net.h15
2 files changed, 28 insertions, 20 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index b0bc8ead47de..c07e0302438e 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -347,13 +347,14 @@ err:
347} 347}
348 348
349static struct sk_buff *receive_mergeable(struct net_device *dev, 349static struct sk_buff *receive_mergeable(struct net_device *dev,
350 struct virtnet_info *vi,
350 struct receive_queue *rq, 351 struct receive_queue *rq,
351 unsigned long ctx, 352 unsigned long ctx,
352 unsigned int len) 353 unsigned int len)
353{ 354{
354 void *buf = mergeable_ctx_to_buf_address(ctx); 355 void *buf = mergeable_ctx_to_buf_address(ctx);
355 struct skb_vnet_hdr *hdr = buf; 356 struct skb_vnet_hdr *hdr = buf;
356 int num_buf = hdr->mhdr.num_buffers; 357 u16 num_buf = virtio16_to_cpu(rq->vq->vdev, hdr->mhdr.num_buffers);
357 struct page *page = virt_to_head_page(buf); 358 struct page *page = virt_to_head_page(buf);
358 int offset = buf - page_address(page); 359 int offset = buf - page_address(page);
359 unsigned int truesize = max(len, mergeable_ctx_to_buf_truesize(ctx)); 360 unsigned int truesize = max(len, mergeable_ctx_to_buf_truesize(ctx));
@@ -369,7 +370,9 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
369 ctx = (unsigned long)virtqueue_get_buf(rq->vq, &len); 370 ctx = (unsigned long)virtqueue_get_buf(rq->vq, &len);
370 if (unlikely(!ctx)) { 371 if (unlikely(!ctx)) {
371 pr_debug("%s: rx error: %d buffers out of %d missing\n", 372 pr_debug("%s: rx error: %d buffers out of %d missing\n",
372 dev->name, num_buf, hdr->mhdr.num_buffers); 373 dev->name, num_buf,
374 virtio16_to_cpu(rq->vq->vdev,
375 hdr->mhdr.num_buffers));
373 dev->stats.rx_length_errors++; 376 dev->stats.rx_length_errors++;
374 goto err_buf; 377 goto err_buf;
375 } 378 }
@@ -454,7 +457,7 @@ static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len)
454 } 457 }
455 458
456 if (vi->mergeable_rx_bufs) 459 if (vi->mergeable_rx_bufs)
457 skb = receive_mergeable(dev, rq, (unsigned long)buf, len); 460 skb = receive_mergeable(dev, vi, rq, (unsigned long)buf, len);
458 else if (vi->big_packets) 461 else if (vi->big_packets)
459 skb = receive_big(dev, rq, buf, len); 462 skb = receive_big(dev, rq, buf, len);
460 else 463 else
@@ -473,8 +476,8 @@ static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len)
473 if (hdr->hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { 476 if (hdr->hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
474 pr_debug("Needs csum!\n"); 477 pr_debug("Needs csum!\n");
475 if (!skb_partial_csum_set(skb, 478 if (!skb_partial_csum_set(skb,
476 hdr->hdr.csum_start, 479 virtio16_to_cpu(vi->vdev, hdr->hdr.csum_start),
477 hdr->hdr.csum_offset)) 480 virtio16_to_cpu(vi->vdev, hdr->hdr.csum_offset)))
478 goto frame_err; 481 goto frame_err;
479 } else if (hdr->hdr.flags & VIRTIO_NET_HDR_F_DATA_VALID) { 482 } else if (hdr->hdr.flags & VIRTIO_NET_HDR_F_DATA_VALID) {
480 skb->ip_summed = CHECKSUM_UNNECESSARY; 483 skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -514,7 +517,8 @@ static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len)
514 if (hdr->hdr.gso_type & VIRTIO_NET_HDR_GSO_ECN) 517 if (hdr->hdr.gso_type & VIRTIO_NET_HDR_GSO_ECN)
515 skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN; 518 skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN;
516 519
517 skb_shinfo(skb)->gso_size = hdr->hdr.gso_size; 520 skb_shinfo(skb)->gso_size = virtio16_to_cpu(vi->vdev,
521 hdr->hdr.gso_size);
518 if (skb_shinfo(skb)->gso_size == 0) { 522 if (skb_shinfo(skb)->gso_size == 0) {
519 net_warn_ratelimited("%s: zero gso size.\n", dev->name); 523 net_warn_ratelimited("%s: zero gso size.\n", dev->name);
520 goto frame_err; 524 goto frame_err;
@@ -876,16 +880,19 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb)
876 880
877 if (skb->ip_summed == CHECKSUM_PARTIAL) { 881 if (skb->ip_summed == CHECKSUM_PARTIAL) {
878 hdr->hdr.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; 882 hdr->hdr.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
879 hdr->hdr.csum_start = skb_checksum_start_offset(skb); 883 hdr->hdr.csum_start = cpu_to_virtio16(vi->vdev,
880 hdr->hdr.csum_offset = skb->csum_offset; 884 skb_checksum_start_offset(skb));
885 hdr->hdr.csum_offset = cpu_to_virtio16(vi->vdev,
886 skb->csum_offset);
881 } else { 887 } else {
882 hdr->hdr.flags = 0; 888 hdr->hdr.flags = 0;
883 hdr->hdr.csum_offset = hdr->hdr.csum_start = 0; 889 hdr->hdr.csum_offset = hdr->hdr.csum_start = 0;
884 } 890 }
885 891
886 if (skb_is_gso(skb)) { 892 if (skb_is_gso(skb)) {
887 hdr->hdr.hdr_len = skb_headlen(skb); 893 hdr->hdr.hdr_len = cpu_to_virtio16(vi->vdev, skb_headlen(skb));
888 hdr->hdr.gso_size = skb_shinfo(skb)->gso_size; 894 hdr->hdr.gso_size = cpu_to_virtio16(vi->vdev,
895 skb_shinfo(skb)->gso_size);
889 if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) 896 if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4)
890 hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV4; 897 hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
891 else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) 898 else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
@@ -1112,7 +1119,7 @@ static int virtnet_set_queues(struct virtnet_info *vi, u16 queue_pairs)
1112 if (!vi->has_cvq || !virtio_has_feature(vi->vdev, VIRTIO_NET_F_MQ)) 1119 if (!vi->has_cvq || !virtio_has_feature(vi->vdev, VIRTIO_NET_F_MQ))
1113 return 0; 1120 return 0;
1114 1121
1115 s.virtqueue_pairs = queue_pairs; 1122 s.virtqueue_pairs = cpu_to_virtio16(vi->vdev, queue_pairs);
1116 sg_init_one(&sg, &s, sizeof(s)); 1123 sg_init_one(&sg, &s, sizeof(s));
1117 1124
1118 if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MQ, 1125 if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MQ,
@@ -1189,7 +1196,7 @@ static void virtnet_set_rx_mode(struct net_device *dev)
1189 sg_init_table(sg, 2); 1196 sg_init_table(sg, 2);
1190 1197
1191 /* Store the unicast list and count in the front of the buffer */ 1198 /* Store the unicast list and count in the front of the buffer */
1192 mac_data->entries = uc_count; 1199 mac_data->entries = cpu_to_virtio32(vi->vdev, uc_count);
1193 i = 0; 1200 i = 0;
1194 netdev_for_each_uc_addr(ha, dev) 1201 netdev_for_each_uc_addr(ha, dev)
1195 memcpy(&mac_data->macs[i++][0], ha->addr, ETH_ALEN); 1202 memcpy(&mac_data->macs[i++][0], ha->addr, ETH_ALEN);
@@ -1200,7 +1207,7 @@ static void virtnet_set_rx_mode(struct net_device *dev)
1200 /* multicast list and count fill the end */ 1207 /* multicast list and count fill the end */
1201 mac_data = (void *)&mac_data->macs[uc_count][0]; 1208 mac_data = (void *)&mac_data->macs[uc_count][0];
1202 1209
1203 mac_data->entries = mc_count; 1210 mac_data->entries = cpu_to_virtio32(vi->vdev, mc_count);
1204 i = 0; 1211 i = 0;
1205 netdev_for_each_mc_addr(ha, dev) 1212 netdev_for_each_mc_addr(ha, dev)
1206 memcpy(&mac_data->macs[i++][0], ha->addr, ETH_ALEN); 1213 memcpy(&mac_data->macs[i++][0], ha->addr, ETH_ALEN);
diff --git a/include/uapi/linux/virtio_net.h b/include/uapi/linux/virtio_net.h
index 172a7f00780c..b5f1677b291c 100644
--- a/include/uapi/linux/virtio_net.h
+++ b/include/uapi/linux/virtio_net.h
@@ -28,6 +28,7 @@
28#include <linux/types.h> 28#include <linux/types.h>
29#include <linux/virtio_ids.h> 29#include <linux/virtio_ids.h>
30#include <linux/virtio_config.h> 30#include <linux/virtio_config.h>
31#include <linux/virtio_types.h>
31#include <linux/if_ether.h> 32#include <linux/if_ether.h>
32 33
33/* The feature bitmap for virtio net */ 34/* The feature bitmap for virtio net */
@@ -84,17 +85,17 @@ struct virtio_net_hdr {
84#define VIRTIO_NET_HDR_GSO_TCPV6 4 // GSO frame, IPv6 TCP 85#define VIRTIO_NET_HDR_GSO_TCPV6 4 // GSO frame, IPv6 TCP
85#define VIRTIO_NET_HDR_GSO_ECN 0x80 // TCP has ECN set 86#define VIRTIO_NET_HDR_GSO_ECN 0x80 // TCP has ECN set
86 __u8 gso_type; 87 __u8 gso_type;
87 __u16 hdr_len; /* Ethernet + IP + tcp/udp hdrs */ 88 __virtio16 hdr_len; /* Ethernet + IP + tcp/udp hdrs */
88 __u16 gso_size; /* Bytes to append to hdr_len per frame */ 89 __virtio16 gso_size; /* Bytes to append to hdr_len per frame */
89 __u16 csum_start; /* Position to start checksumming from */ 90 __virtio16 csum_start; /* Position to start checksumming from */
90 __u16 csum_offset; /* Offset after that to place checksum */ 91 __virtio16 csum_offset; /* Offset after that to place checksum */
91}; 92};
92 93
93/* This is the version of the header to use when the MRG_RXBUF 94/* This is the version of the header to use when the MRG_RXBUF
94 * feature has been negotiated. */ 95 * feature has been negotiated. */
95struct virtio_net_hdr_mrg_rxbuf { 96struct virtio_net_hdr_mrg_rxbuf {
96 struct virtio_net_hdr hdr; 97 struct virtio_net_hdr hdr;
97 __u16 num_buffers; /* Number of merged rx buffers */ 98 __virtio16 num_buffers; /* Number of merged rx buffers */
98}; 99};
99 100
100/* 101/*
@@ -149,7 +150,7 @@ typedef __u8 virtio_net_ctrl_ack;
149 * VIRTIO_NET_F_CTRL_MAC_ADDR feature is available. 150 * VIRTIO_NET_F_CTRL_MAC_ADDR feature is available.
150 */ 151 */
151struct virtio_net_ctrl_mac { 152struct virtio_net_ctrl_mac {
152 __