diff options
Diffstat (limited to 'drivers/net/virtio_net.c')
-rw-r--r-- | drivers/net/virtio_net.c | 48 |
1 files changed, 19 insertions, 29 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 68d64f0313ea..a6fcf15adc4f 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
@@ -130,7 +130,6 @@ struct skb_vnet_hdr { | |||
130 | struct virtio_net_hdr hdr; | 130 | struct virtio_net_hdr hdr; |
131 | struct virtio_net_hdr_mrg_rxbuf mhdr; | 131 | struct virtio_net_hdr_mrg_rxbuf mhdr; |
132 | }; | 132 | }; |
133 | unsigned int num_sg; | ||
134 | }; | 133 | }; |
135 | 134 | ||
136 | struct padded_vnet_hdr { | 135 | struct padded_vnet_hdr { |
@@ -530,10 +529,10 @@ static bool try_fill_recv(struct receive_queue *rq, gfp_t gfp) | |||
530 | err = add_recvbuf_small(rq, gfp); | 529 | err = add_recvbuf_small(rq, gfp); |
531 | 530 | ||
532 | oom = err == -ENOMEM; | 531 | oom = err == -ENOMEM; |
533 | if (err < 0) | 532 | if (err) |
534 | break; | 533 | break; |
535 | ++rq->num; | 534 | ++rq->num; |
536 | } while (err > 0); | 535 | } while (rq->vq->num_free); |
537 | if (unlikely(rq->num > rq->max)) | 536 | if (unlikely(rq->num > rq->max)) |
538 | rq->max = rq->num; | 537 | rq->max = rq->num; |
539 | virtqueue_kick(rq->vq); | 538 | virtqueue_kick(rq->vq); |
@@ -640,10 +639,10 @@ static int virtnet_open(struct net_device *dev) | |||
640 | return 0; | 639 | return 0; |
641 | } | 640 | } |
642 | 641 | ||
643 | static unsigned int free_old_xmit_skbs(struct send_queue *sq) | 642 | static void free_old_xmit_skbs(struct send_queue *sq) |
644 | { | 643 | { |
645 | struct sk_buff *skb; | 644 | struct sk_buff *skb; |
646 | unsigned int len, tot_sgs = 0; | 645 | unsigned int len; |
647 | struct virtnet_info *vi = sq->vq->vdev->priv; | 646 | struct virtnet_info *vi = sq->vq->vdev->priv; |
648 | struct virtnet_stats *stats = this_cpu_ptr(vi->stats); | 647 | struct virtnet_stats *stats = this_cpu_ptr(vi->stats); |
649 | 648 | ||
@@ -655,10 +654,8 @@ static unsigned int free_old_xmit_skbs(struct send_queue *sq) | |||
655 | stats->tx_packets++; | 654 | stats->tx_packets++; |
656 | u64_stats_update_end(&stats->tx_syncp); | 655 | u64_stats_update_end(&stats->tx_syncp); |
657 | 656 | ||
658 | tot_sgs += skb_vnet_hdr(skb)->num_sg; | ||
659 | dev_kfree_skb_any(skb); | 657 | dev_kfree_skb_any(skb); |
660 | } | 658 | } |
661 | return tot_sgs; | ||
662 | } | 659 | } |
663 | 660 | ||
664 | static int xmit_skb(struct send_queue *sq, struct sk_buff *skb) | 661 | static int xmit_skb(struct send_queue *sq, struct sk_buff *skb) |
@@ -666,6 +663,7 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb) | |||
666 | struct skb_vnet_hdr *hdr = skb_vnet_hdr(skb); | 663 | struct skb_vnet_hdr *hdr = skb_vnet_hdr(skb); |
667 | const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest; | 664 | const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest; |
668 | struct virtnet_info *vi = sq->vq->vdev->priv; | 665 | struct virtnet_info *vi = sq->vq->vdev->priv; |
666 | unsigned num_sg; | ||
669 | 667 | ||
670 | pr_debug("%s: xmit %p %pM\n", vi->dev->name, skb, dest); | 668 | pr_debug("%s: xmit %p %pM\n", vi->dev->name, skb, dest); |
671 | 669 | ||
@@ -704,8 +702,8 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb) | |||
704 | else | 702 | else |
705 | sg_set_buf(sq->sg, &hdr->hdr, sizeof hdr->hdr); | 703 | sg_set_buf(sq->sg, &hdr->hdr, sizeof hdr->hdr); |
706 | 704 | ||
707 | hdr->num_sg = skb_to_sgvec(skb, sq->sg + 1, 0, skb->len) + 1; | 705 | num_sg = skb_to_sgvec(skb, sq->sg + 1, 0, skb->len) + 1; |
708 | return virtqueue_add_buf(sq->vq, sq->sg, hdr->num_sg, | 706 | return virtqueue_add_buf(sq->vq, sq->sg, num_sg, |
709 | 0, skb, GFP_ATOMIC); | 707 | 0, skb, GFP_ATOMIC); |
710 | } | 708 | } |
711 | 709 | ||
@@ -714,28 +712,20 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
714 | struct virtnet_info *vi = netdev_priv(dev); | 712 | struct virtnet_info *vi = netdev_priv(dev); |
715 | int qnum = skb_get_queue_mapping(skb); | 713 | int qnum = skb_get_queue_mapping(skb); |
716 | struct send_queue *sq = &vi->sq[qnum]; | 714 | struct send_queue *sq = &vi->sq[qnum]; |
717 | int capacity; | 715 | int err; |
718 | 716 | ||
719 | /* Free up any pending old buffers before queueing new ones. */ | 717 | /* Free up any pending old buffers before queueing new ones. */ |
720 | free_old_xmit_skbs(sq); | 718 | free_old_xmit_skbs(sq); |
721 | 719 | ||
722 | /* Try to transmit */ | 720 | /* Try to transmit */ |
723 | capacity = xmit_skb(sq, skb); | 721 | err = xmit_skb(sq, skb); |
724 | 722 | ||
725 | /* This can happen with OOM and indirect buffers. */ | 723 | /* This should not happen! */ |
726 | if (unlikely(capacity < 0)) { | 724 | if (unlikely(err)) { |
727 | if (likely(capacity == -ENOMEM)) { | 725 | dev->stats.tx_fifo_errors++; |
728 | if (net_ratelimit()) | 726 | if (net_ratelimit()) |
729 | dev_warn(&dev->dev, | 727 | dev_warn(&dev->dev, |
730 | "TXQ (%d) failure: out of memory\n", | 728 | "Unexpected TXQ (%d) queue failure: %d\n", qnum, err); |
731 | qnum); | ||
732 | } else { | ||
733 | dev->stats.tx_fifo_errors++; | ||
734 | if (net_ratelimit()) | ||
735 | dev_warn(&dev->dev, | ||
736 | "Unexpected TXQ (%d) failure: %d\n", | ||
737 | qnum, capacity); | ||
738 | } | ||
739 | dev->stats.tx_dropped++; | 729 | dev->stats.tx_dropped++; |
740 | kfree_skb(skb); | 730 | kfree_skb(skb); |
741 | return NETDEV_TX_OK; | 731 | return NETDEV_TX_OK; |
@@ -748,12 +738,12 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
748 | 738 | ||
749 | /* Apparently nice girls don't return TX_BUSY; stop the queue | 739 | /* Apparently nice girls don't return TX_BUSY; stop the queue |
750 | * before it gets out of hand. Naturally, this wastes entries. */ | 740 | * before it gets out of hand. Naturally, this wastes entries. */ |
751 | if (capacity < 2+MAX_SKB_FRAGS) { | 741 | if (sq->vq->num_free < 2+MAX_SKB_FRAGS) { |
752 | netif_stop_subqueue(dev, qnum); | 742 | netif_stop_subqueue(dev, qnum); |
753 | if (unlikely(!virtqueue_enable_cb_delayed(sq->vq))) { | 743 | if (unlikely(!virtqueue_enable_cb_delayed(sq->vq))) { |
754 | /* More just got used, free them then recheck. */ | 744 | /* More just got used, free them then recheck. */ |
755 | capacity += free_old_xmit_skbs(sq); | 745 | free_old_xmit_skbs(sq); |
756 | if (capacity >= 2+MAX_SKB_FRAGS) { | 746 | if (sq->vq->num_free >= 2+MAX_SKB_FRAGS) { |
757 | netif_start_subqueue(dev, qnum); | 747 | netif_start_subqueue(dev, qnum); |
758 | virtqueue_disable_cb(sq->vq); | 748 | virtqueue_disable_cb(sq->vq); |
759 | } | 749 | } |