aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/virtio_net.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/virtio_net.c')
-rw-r--r--drivers/net/virtio_net.c48
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
136struct padded_vnet_hdr { 135struct 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
643static unsigned int free_old_xmit_skbs(struct send_queue *sq) 642static 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
664static int xmit_skb(struct send_queue *sq, struct sk_buff *skb) 661static 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 }