Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>




+28 -20
+20 -13
drivers/net/virtio_net.c
··· 347 347 } 348 348 349 349 static struct sk_buff *receive_mergeable(struct net_device *dev, 350 + struct virtnet_info *vi, 350 351 struct receive_queue *rq, 351 352 unsigned long ctx, 352 353 unsigned int len) 353 354 { 354 355 void *buf = mergeable_ctx_to_buf_address(ctx); 355 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 358 struct page *page = virt_to_head_page(buf); 358 359 int offset = buf - page_address(page); 359 360 unsigned int truesize = max(len, mergeable_ctx_to_buf_truesize(ctx)); ··· 370 369 ctx = (unsigned long)virtqueue_get_buf(rq->vq, &len); 371 370 if (unlikely(!ctx)) { 372 371 pr_debug("%s: rx error: %d buffers out of %d missing\n", 373 - dev->name, num_buf, hdr->mhdr.num_buffers); 372 + dev->name, num_buf, 373 + virtio16_to_cpu(rq->vq->vdev, 374 + hdr->mhdr.num_buffers)); 374 375 dev->stats.rx_length_errors++; 375 376 goto err_buf; 376 377 } ··· 457 454 } 458 455 459 456 if (vi->mergeable_rx_bufs) 460 - skb = receive_mergeable(dev, rq, (unsigned long)buf, len); 457 + skb = receive_mergeable(dev, vi, rq, (unsigned long)buf, len); 461 458 else if (vi->big_packets) 462 459 skb = receive_big(dev, rq, buf, len); 463 460 else ··· 476 473 if (hdr->hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { 477 474 pr_debug("Needs csum!\n"); 478 475 if (!skb_partial_csum_set(skb, 479 - hdr->hdr.csum_start, 480 - hdr->hdr.csum_offset)) 476 + virtio16_to_cpu(vi->vdev, hdr->hdr.csum_start), 477 + virtio16_to_cpu(vi->vdev, hdr->hdr.csum_offset))) 481 478 goto frame_err; 482 479 } else if (hdr->hdr.flags & VIRTIO_NET_HDR_F_DATA_VALID) { 483 480 skb->ip_summed = CHECKSUM_UNNECESSARY; ··· 517 514 if (hdr->hdr.gso_type & VIRTIO_NET_HDR_GSO_ECN) 518 515 skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN; 519 516 520 - skb_shinfo(skb)->gso_size = hdr->hdr.gso_size; 517 + skb_shinfo(skb)->gso_size = virtio16_to_cpu(vi->vdev, 518 + hdr->hdr.gso_size); 521 519 if (skb_shinfo(skb)->gso_size == 0) { 522 520 net_warn_ratelimited("%s: zero gso size.\n", dev->name); 523 521 goto frame_err; ··· 880 876 881 877 if (skb->ip_summed == CHECKSUM_PARTIAL) { 882 878 hdr->hdr.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; 883 - hdr->hdr.csum_start = skb_checksum_start_offset(skb); 884 - hdr->hdr.csum_offset = skb->csum_offset; 879 + hdr->hdr.csum_start = cpu_to_virtio16(vi->vdev, 880 + skb_checksum_start_offset(skb)); 881 + hdr->hdr.csum_offset = cpu_to_virtio16(vi->vdev, 882 + skb->csum_offset); 885 883 } else { 886 884 hdr->hdr.flags = 0; 887 885 hdr->hdr.csum_offset = hdr->hdr.csum_start = 0; 888 886 } 889 887 890 888 if (skb_is_gso(skb)) { 891 - hdr->hdr.hdr_len = skb_headlen(skb); 892 - hdr->hdr.gso_size = skb_shinfo(skb)->gso_size; 889 + hdr->hdr.hdr_len = cpu_to_virtio16(vi->vdev, skb_headlen(skb)); 890 + hdr->hdr.gso_size = cpu_to_virtio16(vi->vdev, 891 + skb_shinfo(skb)->gso_size); 893 892 if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) 894 893 hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV4; 895 894 else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) ··· 1119 1112 if (!vi->has_cvq || !virtio_has_feature(vi->vdev, VIRTIO_NET_F_MQ)) 1120 1113 return 0; 1121 1114 1122 - s.virtqueue_pairs = queue_pairs; 1115 + s.virtqueue_pairs = cpu_to_virtio16(vi->vdev, queue_pairs); 1123 1116 sg_init_one(&sg, &s, sizeof(s)); 1124 1117 1125 1118 if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MQ, ··· 1196 1189 sg_init_table(sg, 2); 1197 1190 1198 1191 /* Store the unicast list and count in the front of the buffer */ 1199 - mac_data->entries = uc_count; 1192 + mac_data->entries = cpu_to_virtio32(vi->vdev, uc_count); 1200 1193 i = 0; 1201 1194 netdev_for_each_uc_addr(ha, dev) 1202 1195 memcpy(&mac_data->macs[i++][0], ha->addr, ETH_ALEN); ··· 1207 1200 /* multicast list and count fill the end */ 1208 1201 mac_data = (void *)&mac_data->macs[uc_count][0]; 1209 1202 1210 - mac_data->entries = mc_count; 1203 + mac_data->entries = cpu_to_virtio32(vi->vdev, mc_count); 1211 1204 i = 0; 1212 1205 netdev_for_each_mc_addr(ha, dev) 1213 1206 memcpy(&mac_data->macs[i++][0], ha->addr, ETH_ALEN);
+8 -7
include/uapi/linux/virtio_net.h
··· 28 28 #include <linux/types.h> 29 29 #include <linux/virtio_ids.h> 30 30 #include <linux/virtio_config.h> 31 + #include <linux/virtio_types.h> 31 32 #include <linux/if_ether.h> 32 33 33 34 /* The feature bitmap for virtio net */ ··· 85 84 #define VIRTIO_NET_HDR_GSO_TCPV6 4 // GSO frame, IPv6 TCP 86 85 #define VIRTIO_NET_HDR_GSO_ECN 0x80 // TCP has ECN set 87 86 __u8 gso_type; 88 - __u16 hdr_len; /* Ethernet + IP + tcp/udp hdrs */ 89 - __u16 gso_size; /* Bytes to append to hdr_len per frame */ 90 - __u16 csum_start; /* Position to start checksumming from */ 91 - __u16 csum_offset; /* Offset after that to place checksum */ 87 + __virtio16 hdr_len; /* Ethernet + IP + tcp/udp hdrs */ 88 + __virtio16 gso_size; /* Bytes to append to hdr_len per frame */ 89 + __virtio16 csum_start; /* Position to start checksumming from */ 90 + __virtio16 csum_offset; /* Offset after that to place checksum */ 92 91 }; 93 92 94 93 /* This is the version of the header to use when the MRG_RXBUF 95 94 * feature has been negotiated. */ 96 95 struct virtio_net_hdr_mrg_rxbuf { 97 96 struct virtio_net_hdr hdr; 98 - __u16 num_buffers; /* Number of merged rx buffers */ 97 + __virtio16 num_buffers; /* Number of merged rx buffers */ 99 98 }; 100 99 101 100 /* ··· 150 149 * VIRTIO_NET_F_CTRL_MAC_ADDR feature is available. 151 150 */ 152 151 struct virtio_net_ctrl_mac { 153 - __u32 entries; 152 + __virtio32 entries; 154 153 __u8 macs[][ETH_ALEN]; 155 154 } __attribute__((packed)); 156 155 ··· 194 193 * specified. 195 194 */ 196 195 struct virtio_net_ctrl_mq { 197 - __u16 virtqueue_pairs; 196 + __virtio16 virtqueue_pairs; 198 197 }; 199 198 200 199 #define VIRTIO_NET_CTRL_MQ 4