diff options
author | Michael S. Tsirkin <mst@redhat.com> | 2014-10-24 09:55:57 -0400 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2014-12-09 05:05:28 -0500 |
commit | 012873d057a449c4480e7679e733a7daa9aa540f (patch) | |
tree | ae7c8bd666d623f1964b588d71ea4f2b8d1346b5 | |
parent | 946fa5647b529402161814ca8ed1302254b6affb (diff) |
virtio_net: get rid of virtio_net_hdr/skb_vnet_hdr
virtio 1.0 doesn't use virtio_net_hdr anymore, and in fact, it's not
really useful since virtio_net_hdr_mrg_rxbuf includes that as the first
field anyway.
Let's drop it, precalculate header len and store within vi instead.
This way we can also remove struct skb_vnet_hdr.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Reviewed-by: Jason Wang <jasowang@redhat.com>
-rw-r--r-- | drivers/net/virtio_net.c | 90 |
1 files changed, 41 insertions, 49 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 1630c217d9f7..516f2cb034b5 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
@@ -123,6 +123,9 @@ struct virtnet_info { | |||
123 | /* Host can handle any s/g split between our header and packet data */ | 123 | /* Host can handle any s/g split between our header and packet data */ |
124 | bool any_header_sg; | 124 | bool any_header_sg; |
125 | 125 | ||
126 | /* Packet virtio header size */ | ||
127 | u8 hdr_len; | ||
128 | |||
126 | /* Active statistics */ | 129 | /* Active statistics */ |
127 | struct virtnet_stats __percpu *stats; | 130 | struct virtnet_stats __percpu *stats; |
128 | 131 | ||
@@ -139,21 +142,14 @@ struct virtnet_info { | |||
139 | struct notifier_block nb; | 142 | struct notifier_block nb; |
140 | }; | 143 | }; |
141 | 144 | ||
142 | struct skb_vnet_hdr { | ||
143 | union { | ||
144 | struct virtio_net_hdr hdr; | ||
145 | struct virtio_net_hdr_mrg_rxbuf mhdr; | ||
146 | }; | ||
147 | }; | ||
148 | |||
149 | struct padded_vnet_hdr { | 145 | struct padded_vnet_hdr { |
150 | struct virtio_net_hdr hdr; | 146 | struct virtio_net_hdr_mrg_rxbuf hdr; |
151 | /* | 147 | /* |
152 | * virtio_net_hdr should be in a separated sg buffer because of a | 148 | * hdr is in a separate sg buffer, and data sg buffer shares same page |
153 | * QEMU bug, and data sg buffer shares same page with this header sg. | 149 | * with this header sg. This padding makes next sg 16 byte aligned |
154 | * This padding makes next sg 16 byte aligned after virtio_net_hdr. | 150 | * after the header. |
155 | */ | 151 | */ |
156 | char padding[6]; | 152 | char padding[4]; |
157 | }; | 153 | }; |
158 | 154 | ||
159 | /* Converting between virtqueue no. and kernel tx/rx queue no. | 155 | /* Converting between virtqueue no. and kernel tx/rx queue no. |
@@ -179,9 +175,9 @@ static int rxq2vq(int rxq) | |||
179 | return rxq * 2; | 175 | return rxq * 2; |
180 | } | 176 | } |
181 | 177 | ||
182 | static inline struct skb_vnet_hdr *skb_vnet_hdr(struct sk_buff *skb) | 178 | static inline struct virtio_net_hdr_mrg_rxbuf *skb_vnet_hdr(struct sk_buff *skb) |
183 | { | 179 | { |
184 | return (struct skb_vnet_hdr *)skb->cb; | 180 | return (struct virtio_net_hdr_mrg_rxbuf *)skb->cb; |
185 | } | 181 | } |
186 | 182 | ||
187 | /* | 183 | /* |
@@ -247,7 +243,7 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi, | |||
247 | unsigned int len, unsigned int truesize) | 243 | unsigned int len, unsigned int truesize) |
248 | { | 244 | { |
249 | struct sk_buff *skb; | 245 | struct sk_buff *skb; |
250 | struct skb_vnet_hdr *hdr; | 246 | struct virtio_net_hdr_mrg_rxbuf *hdr; |
251 | unsigned int copy, hdr_len, hdr_padded_len; | 247 | unsigned int copy, hdr_len, hdr_padded_len; |
252 | char *p; | 248 | char *p; |
253 | 249 | ||
@@ -260,13 +256,11 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi, | |||
260 | 256 | ||
261 | hdr = skb_vnet_hdr(skb); | 257 | hdr = skb_vnet_hdr(skb); |
262 | 258 | ||
263 | if (vi->mergeable_rx_bufs) { | 259 | hdr_len = vi->hdr_len; |
264 | hdr_len = sizeof hdr->mhdr; | 260 | if (vi->mergeable_rx_bufs) |
265 | hdr_padded_len = sizeof hdr->mhdr; | 261 | hdr_padded_len = sizeof *hdr; |
266 | } else { | 262 | else |
267 | hdr_len = sizeof hdr->hdr; | ||
268 | hdr_padded_len = sizeof(struct padded_vnet_hdr); | 263 | hdr_padded_len = sizeof(struct padded_vnet_hdr); |
269 | } | ||
270 | 264 | ||
271 | memcpy(hdr, p, hdr_len); | 265 | memcpy(hdr, p, hdr_len); |
272 | 266 | ||
@@ -317,11 +311,11 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi, | |||
317 | return skb; | 311 | return skb; |
318 | } | 312 | } |
319 | 313 | ||
320 | static struct sk_buff *receive_small(void *buf, unsigned int len) | 314 | static struct sk_buff *receive_small(struct virtnet_info *vi, void *buf, unsigned int len) |
321 | { | 315 | { |
322 | struct sk_buff * skb = buf; | 316 | struct sk_buff * skb = buf; |
323 | 317 | ||
324 | len -= sizeof(struct virtio_net_hdr); | 318 | len -= vi->hdr_len; |
325 | skb_trim(skb, len); | 319 | skb_trim(skb, len); |
326 | 320 | ||
327 | return skb; | 321 | return skb; |
@@ -354,8 +348,8 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, | |||
354 | unsigned int len) | 348 | unsigned int len) |
355 | { | 349 | { |
356 | void *buf = mergeable_ctx_to_buf_address(ctx); | 350 | void *buf = mergeable_ctx_to_buf_address(ctx); |
357 | struct skb_vnet_hdr *hdr = buf; | 351 | struct virtio_net_hdr_mrg_rxbuf *hdr = buf; |
358 | u16 num_buf = virtio16_to_cpu(rq->vq->vdev, hdr->mhdr.num_buffers); | 352 | u16 num_buf = virtio16_to_cpu(vi->vdev, hdr->num_buffers); |
359 | struct page *page = virt_to_head_page(buf); | 353 | struct page *page = virt_to_head_page(buf); |
360 | int offset = buf - page_address(page); | 354 | int offset = buf - page_address(page); |
361 | unsigned int truesize = max(len, mergeable_ctx_to_buf_truesize(ctx)); | 355 | unsigned int truesize = max(len, mergeable_ctx_to_buf_truesize(ctx)); |
@@ -373,8 +367,8 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, | |||
373 | if (unlikely(!ctx)) { | 367 | if (unlikely(!ctx)) { |
374 | pr_debug("%s: rx error: %d buffers out of %d missing\n", | 368 | pr_debug("%s: rx error: %d buffers out of %d missing\n", |
375 | dev->name, num_buf, | 369 | dev->name, num_buf, |
376 | virtio16_to_cpu(rq->vq->vdev, | 370 | virtio16_to_cpu(vi->vdev, |
377 | hdr->mhdr.num_buffers)); | 371 | hdr->num_buffers)); |
378 | dev->stats.rx_length_errors++; | 372 | dev->stats.rx_length_errors++; |
379 | goto err_buf; | 373 | goto err_buf; |
380 | } | 374 | } |
@@ -441,7 +435,7 @@ static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq, | |||
441 | struct net_device *dev = vi->dev; | 435 | struct net_device *dev = vi->dev; |
442 | struct virtnet_stats *stats = this_cpu_ptr(vi->stats); | 436 | struct virtnet_stats *stats = this_cpu_ptr(vi->stats); |
443 | struct sk_buff *skb; | 437 | struct sk_buff *skb; |
444 | struct skb_vnet_hdr *hdr; | 438 | struct virtio_net_hdr_mrg_rxbuf *hdr; |
445 | 439 | ||
446 | if (unlikely(len < sizeof(struct virtio_net_hdr) + ETH_HLEN)) { | 440 | if (unlikely(len < sizeof(struct virtio_net_hdr) + ETH_HLEN)) { |
447 | pr_debug("%s: short packet %i\n", dev->name, len); | 441 | pr_debug("%s: short packet %i\n", dev->name, len); |
@@ -463,7 +457,7 @@ static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq, | |||
463 | else if (vi->big_packets) | 457 | else if (vi->big_packets) |
464 | skb = receive_big(dev, vi, rq, buf, len); | 458 | skb = receive_big(dev, vi, rq, buf, len); |
465 | else | 459 | else |
466 | skb = receive_small(buf, len); | 460 | skb = receive_small(vi, buf, len); |
467 | 461 | ||
468 | if (unlikely(!skb)) | 462 | if (unlikely(!skb)) |
469 | return; | 463 | return; |
@@ -545,7 +539,7 @@ static int add_recvbuf_small(struct virtnet_info *vi, struct receive_queue *rq, | |||
545 | gfp_t gfp) | 539 | gfp_t gfp) |
546 | { | 540 | { |
547 | struct sk_buff *skb; | 541 | struct sk_buff *skb; |
548 | struct skb_vnet_hdr *hdr; | 542 | struct virtio_net_hdr_mrg_rxbuf *hdr; |
549 | int err; | 543 | int err; |
550 | 544 | ||
551 | skb = __netdev_alloc_skb_ip_align(vi->dev, GOOD_PACKET_LEN, gfp); | 545 | skb = __netdev_alloc_skb_ip_align(vi->dev, GOOD_PACKET_LEN, gfp); |
@@ -556,7 +550,7 @@ static int add_recvbuf_small(struct virtnet_info *vi, struct receive_queue *rq, | |||
556 | 550 | ||
557 | hdr = skb_vnet_hdr(skb); | 551 | hdr = skb_vnet_hdr(skb); |
558 | sg_init_table(rq->sg, MAX_SKB_FRAGS + 2); | 552 | sg_init_table(rq->sg, MAX_SKB_FRAGS + 2); |
559 | sg_set_buf(rq->sg, &hdr->hdr, sizeof hdr->hdr); | 553 | sg_set_buf(rq->sg, hdr, vi->hdr_len); |
560 | skb_to_sgvec(skb, rq->sg + 1, 0, skb->len); | 554 | skb_to_sgvec(skb, rq->sg + 1, 0, skb->len); |
561 | 555 | ||
562 | err = virtqueue_add_inbuf(rq->vq, rq->sg, 2, skb, gfp); | 556 | err = virtqueue_add_inbuf(rq->vq, rq->sg, 2, skb, gfp); |
@@ -566,7 +560,8 @@ static int add_recvbuf_small(struct virtnet_info *vi, struct receive_queue *rq, | |||
566 | return err; | 560 | return err; |
567 | } | 561 | } |
568 | 562 | ||
569 | static int add_recvbuf_big(struct receive_queue *rq, gfp_t gfp) | 563 | static int add_recvbuf_big(struct virtnet_info *vi, struct receive_queue *rq, |
564 | gfp_t gfp) | ||
570 | { | 565 | { |
571 | struct page *first, *list = NULL; | 566 | struct page *first, *list = NULL; |
572 | char *p; | 567 | char *p; |
@@ -597,8 +592,8 @@ static int add_recvbuf_big(struct receive_queue *rq, gfp_t gfp) | |||
597 | p = page_address(first); | 592 | p = page_address(first); |
598 | 593 | ||
599 | /* rq->sg[0], rq->sg[1] share the same page */ | 594 | /* rq->sg[0], rq->sg[1] share the same page */ |
600 | /* a separated rq->sg[0] for virtio_net_hdr only due to QEMU bug */ | 595 | /* a separated rq->sg[0] for header - required in case !any_header_sg */ |
601 | sg_set_buf(&rq->sg[0], p, sizeof(struct virtio_net_hdr)); | 596 | sg_set_buf(&rq->sg[0], p, vi->hdr_len); |
602 | 597 | ||
603 | /* rq->sg[1] for data packet, from offset */ | 598 | /* rq->sg[1] for data packet, from offset */ |
604 | offset = sizeof(struct padded_vnet_hdr); | 599 | offset = sizeof(struct padded_vnet_hdr); |
@@ -677,7 +672,7 @@ static bool try_fill_recv(struct virtnet_info *vi, struct receive_queue *rq, | |||
677 | if (vi->mergeable_rx_bufs) | 672 | if (vi->mergeable_rx_bufs) |
678 | err = add_recvbuf_mergeable(rq, gfp); | 673 | err = add_recvbuf_mergeable(rq, gfp); |
679 | else if (vi->big_packets) | 674 | else if (vi->big_packets) |
680 | err = add_recvbuf_big(rq, gfp); | 675 | err = add_recvbuf_big(vi, rq, gfp); |
681 | else | 676 | else |
682 | err = add_recvbuf_small(vi, rq, gfp); | 677 | err = add_recvbuf_small(vi, rq, gfp); |
683 | 678 | ||
@@ -857,18 +852,14 @@ static void free_old_xmit_skbs(struct send_queue *sq) | |||
857 | 852 | ||
858 | static int xmit_skb(struct send_queue *sq, struct sk_buff *skb) | 853 | static int xmit_skb(struct send_queue *sq, struct sk_buff *skb) |
859 | { | 854 | { |
860 | struct skb_vnet_hdr *hdr; | 855 | struct virtio_net_hdr_mrg_rxbuf *hdr; |
861 | const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest; | 856 | const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest; |
862 | struct virtnet_info *vi = sq->vq->vdev->priv; | 857 | struct virtnet_info *vi = sq->vq->vdev->priv; |
863 | unsigned num_sg; | 858 | unsigned num_sg; |
864 | unsigned hdr_len; | 859 | unsigned hdr_len = vi->hdr_len; |
865 | bool can_push; | 860 | bool can_push; |
866 | 861 | ||
867 | pr_debug("%s: xmit %p %pM\n", vi->dev->name, skb, dest); | 862 | pr_debug("%s: xmit %p %pM\n", vi->dev->name, skb, dest); |
868 | if (vi->mergeable_rx_bufs) | ||
869 | hdr_len = sizeof hdr->mhdr; | ||
870 | else | ||
871 | hdr_len = sizeof hdr->hdr; | ||
872 | 863 | ||
873 | can_push = vi->any_header_sg && | 864 | can_push = vi->any_header_sg && |
874 | !((unsigned long)skb->data & (__alignof__(*hdr) - 1)) && | 865 | !((unsigned long)skb->data & (__alignof__(*hdr) - 1)) && |
@@ -876,7 +867,7 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb) | |||
876 | /* Even if we can, don't push here yet as this would skew | 867 | /* Even if we can, don't push here yet as this would skew |
877 | * csum_start offset below. */ | 868 | * csum_start offset below. */ |
878 | if (can_push) | 869 | if (can_push) |
879 | hdr = (struct skb_vnet_hdr *)(skb->data - hdr_len); | 870 | hdr = (struct virtio_net_hdr_mrg_rxbuf *)(skb->data - hdr_len); |
880 | else | 871 | else |
881 | hdr = skb_vnet_hdr(skb); | 872 | hdr = skb_vnet_hdr(skb); |
882 | 873 | ||
@@ -909,7 +900,7 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb) | |||
909 | } | 900 | } |
910 | 901 | ||
911 | if (vi->mergeable_rx_bufs) | 902 | if (vi->mergeable_rx_bufs) |
912 | hdr->mhdr.num_buffers = 0; | 903 | hdr->num_buffers = 0; |
913 | 904 | ||
914 | sg_init_table(sq->sg, MAX_SKB_FRAGS + 2); | 905 | sg_init_table(sq->sg, MAX_SKB_FRAGS + 2); |
915 | if (can_push) { | 906 | if (can_push) { |
@@ -1814,18 +1805,19 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
1814 | if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF)) | 1805 | if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF)) |
1815 | vi->mergeable_rx_bufs = true; | 1806 | vi->mergeable_rx_bufs = true; |
1816 | 1807 | ||
1808 | if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF)) | ||
1809 | vi->hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf); | ||
1810 | else | ||
1811 | vi->hdr_len = sizeof(struct virtio_net_hdr); | ||
1812 | |||
1817 | if (virtio_has_feature(vdev, VIRTIO_F_ANY_LAYOUT)) | 1813 | if (virtio_has_feature(vdev, VIRTIO_F_ANY_LAYOUT)) |
1818 | vi->any_header_sg = true; | 1814 | vi->any_header_sg = true; |
1819 | 1815 | ||
1820 | if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) | 1816 | if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) |
1821 | vi->has_cvq = true; | 1817 | vi->has_cvq = true; |
1822 | 1818 | ||
1823 | if (vi->any_header_sg) { | 1819 | if (vi->any_header_sg) |
1824 | if (vi->mergeable_rx_bufs) | 1820 | dev->needed_headroom = vi->hdr_len; |
1825 | dev->needed_headroom = sizeof(struct virtio_net_hdr_mrg_rxbuf); | ||
1826 | else | ||
1827 | dev->needed_headroom = sizeof(struct virtio_net_hdr); | ||
1828 | } | ||
1829 | 1821 | ||
1830 | /* Use single tx/rx queue pair as default */ | 1822 | /* Use single tx/rx queue pair as default */ |
1831 | vi->curr_queue_pairs = 1; | 1823 | vi->curr_queue_pairs = 1; |