diff options
| author | Michael S. Tsirkin <mst@redhat.com> | 2014-10-07 10:39:48 -0400 |
|---|---|---|
| committer | Michael S. Tsirkin <mst@redhat.com> | 2014-12-09 05:05:26 -0500 |
| commit | fdd819b21576c361bf0dcdd9522df4ccabf7aaa8 (patch) | |
| tree | 39c8178b2f4d6d399665dbd449ebfad8f46955ec | |
| parent | b3bb62d11950eb6ac87403cacd667f84fa9495bc (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.c | 33 | ||||
| -rw-r--r-- | include/uapi/linux/virtio_net.h | 15 |
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 | ||
| 349 | static struct sk_buff *receive_mergeable(struct net_device *dev, | 349 | static 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. */ |
| 95 | struct virtio_net_hdr_mrg_rxbuf { | 96 | struct 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 | */ |
| 151 | struct virtio_net_ctrl_mac { | 152 | struct virtio_net_ctrl_mac { |
| 152 | __ | ||
