diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/virtio_net.c | 30 |
1 files changed, 16 insertions, 14 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 01f4eb5c8b78..69fb225e59a6 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
@@ -36,7 +36,10 @@ module_param(csum, bool, 0444); | |||
36 | module_param(gso, bool, 0444); | 36 | module_param(gso, bool, 0444); |
37 | 37 | ||
38 | /* FIXME: MTU in config. */ | 38 | /* FIXME: MTU in config. */ |
39 | #define MAX_PACKET_LEN (ETH_HLEN + VLAN_HLEN + ETH_DATA_LEN) | 39 | #define GOOD_PACKET_LEN (ETH_HLEN + VLAN_HLEN + ETH_DATA_LEN) |
40 | #define MERGE_BUFFER_LEN (ALIGN(GOOD_PACKET_LEN + \ | ||
41 | sizeof(struct virtio_net_hdr_mrg_rxbuf), \ | ||
42 | L1_CACHE_BYTES)) | ||
40 | #define GOOD_COPY_LEN 128 | 43 | #define GOOD_COPY_LEN 128 |
41 | 44 | ||
42 | #define VIRTNET_DRIVER_VERSION "1.0.0" | 45 | #define VIRTNET_DRIVER_VERSION "1.0.0" |
@@ -314,10 +317,10 @@ static int receive_mergeable(struct receive_queue *rq, struct sk_buff *head_skb) | |||
314 | head_skb->dev->stats.rx_length_errors++; | 317 | head_skb->dev->stats.rx_length_errors++; |
315 | return -EINVAL; | 318 | return -EINVAL; |
316 | } | 319 | } |
317 | if (unlikely(len > MAX_PACKET_LEN)) { | 320 | if (unlikely(len > MERGE_BUFFER_LEN)) { |
318 | pr_debug("%s: rx error: merge buffer too long\n", | 321 | pr_debug("%s: rx error: merge buffer too long\n", |
319 | head_skb->dev->name); | 322 | head_skb->dev->name); |
320 | len = MAX_PACKET_LEN; | 323 | len = MERGE_BUFFER_LEN; |
321 | } | 324 | } |
322 | if (unlikely(num_skb_frags == MAX_SKB_FRAGS)) { | 325 | if (unlikely(num_skb_frags == MAX_SKB_FRAGS)) { |
323 | struct sk_buff *nskb = alloc_skb(0, GFP_ATOMIC); | 326 | struct sk_buff *nskb = alloc_skb(0, GFP_ATOMIC); |
@@ -336,18 +339,17 @@ static int receive_mergeable(struct receive_queue *rq, struct sk_buff *head_skb) | |||
336 | if (curr_skb != head_skb) { | 339 | if (curr_skb != head_skb) { |
337 | head_skb->data_len += len; | 340 | head_skb->data_len += len; |
338 | head_skb->len += len; | 341 | head_skb->len += len; |
339 | head_skb->truesize += MAX_PACKET_LEN; | 342 | head_skb->truesize += MERGE_BUFFER_LEN; |
340 | } | 343 | } |
341 | page = virt_to_head_page(buf); | 344 | page = virt_to_head_page(buf); |
342 | offset = buf - (char *)page_address(page); | 345 | offset = buf - (char *)page_address(page); |
343 | if (skb_can_coalesce(curr_skb, num_skb_frags, page, offset)) { | 346 | if (skb_can_coalesce(curr_skb, num_skb_frags, page, offset)) { |
344 | put_page(page); | 347 | put_page(page); |
345 | skb_coalesce_rx_frag(curr_skb, num_skb_frags - 1, | 348 | skb_coalesce_rx_frag(curr_skb, num_skb_frags - 1, |
346 | len, MAX_PACKET_LEN); | 349 | len, MERGE_BUFFER_LEN); |
347 | } else { | 350 | } else { |
348 | skb_add_rx_frag(curr_skb, num_skb_frags, page, | 351 | skb_add_rx_frag(curr_skb, num_skb_frags, page, |
349 | offset, len, | 352 | offset, len, MERGE_BUFFER_LEN); |
350 | MAX_PACKET_LEN); | ||
351 | } | 353 | } |
352 | --rq->num; | 354 | --rq->num; |
353 | } | 355 | } |
@@ -383,7 +385,7 @@ static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len) | |||
383 | struct page *page = virt_to_head_page(buf); | 385 | struct page *page = virt_to_head_page(buf); |
384 | skb = page_to_skb(rq, page, | 386 | skb = page_to_skb(rq, page, |
385 | (char *)buf - (char *)page_address(page), | 387 | (char *)buf - (char *)page_address(page), |
386 | len, MAX_PACKET_LEN); | 388 | len, MERGE_BUFFER_LEN); |
387 | if (unlikely(!skb)) { | 389 | if (unlikely(!skb)) { |
388 | dev->stats.rx_dropped++; | 390 | dev->stats.rx_dropped++; |
389 | put_page(page); | 391 | put_page(page); |
@@ -471,11 +473,11 @@ static int add_recvbuf_small(struct receive_queue *rq, gfp_t gfp) | |||
471 | struct skb_vnet_hdr *hdr; | 473 | struct skb_vnet_hdr *hdr; |
472 | int err; | 474 | int err; |
473 | 475 | ||
474 | skb = __netdev_alloc_skb_ip_align(vi->dev, MAX_PACKET_LEN, gfp); | 476 | skb = __netdev_alloc_skb_ip_align(vi->dev, GOOD_PACKET_LEN, gfp); |
475 | if (unlikely(!skb)) | 477 | if (unlikely(!skb)) |
476 | return -ENOMEM; | 478 | return -ENOMEM; |
477 | 479 | ||
478 | skb_put(skb, MAX_PACKET_LEN); | 480 | skb_put(skb, GOOD_PACKET_LEN); |
479 | 481 | ||
480 | hdr = skb_vnet_hdr(skb); | 482 | hdr = skb_vnet_hdr(skb); |
481 | sg_set_buf(rq->sg, &hdr->hdr, sizeof hdr->hdr); | 483 | sg_set_buf(rq->sg, &hdr->hdr, sizeof hdr->hdr); |
@@ -542,20 +544,20 @@ static int add_recvbuf_mergeable(struct receive_queue *rq, gfp_t gfp) | |||
542 | int err; | 544 | int err; |
543 | 545 | ||
544 | if (gfp & __GFP_WAIT) { | 546 | if (gfp & __GFP_WAIT) { |
545 | if (skb_page_frag_refill(MAX_PACKET_LEN, &vi->alloc_frag, | 547 | if (skb_page_frag_refill(MERGE_BUFFER_LEN, &vi->alloc_frag, |
546 | gfp)) { | 548 | gfp)) { |
547 | buf = (char *)page_address(vi->alloc_frag.page) + | 549 | buf = (char *)page_address(vi->alloc_frag.page) + |
548 | vi->alloc_frag.offset; | 550 | vi->alloc_frag.offset; |
549 | get_page(vi->alloc_frag.page); | 551 | get_page(vi->alloc_frag.page); |
550 | vi->alloc_frag.offset += MAX_PACKET_LEN; | 552 | vi->alloc_frag.offset += MERGE_BUFFER_LEN; |
551 | } | 553 | } |
552 | } else { | 554 | } else { |
553 | buf = netdev_alloc_frag(MAX_PACKET_LEN); | 555 | buf = netdev_alloc_frag(MERGE_BUFFER_LEN); |
554 | } | 556 | } |
555 | if (!buf) | 557 | if (!buf) |
556 | return -ENOMEM; | 558 | return -ENOMEM; |
557 | 559 | ||
558 | sg_init_one(rq->sg, buf, MAX_PACKET_LEN); | 560 | sg_init_one(rq->sg, buf, MERGE_BUFFER_LEN); |
559 | err = virtqueue_add_inbuf(rq->vq, rq->sg, 1, buf, gfp); | 561 | err = virtqueue_add_inbuf(rq->vq, rq->sg, 1, buf, gfp); |
560 | if (err < 0) | 562 | if (err < 0) |
561 | put_page(virt_to_head_page(buf)); | 563 | put_page(virt_to_head_page(buf)); |