diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2010-07-02 12:34:01 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-07-03 01:27:26 -0400 |
commit | 58eba97d0774c69b1cf3e5a8ac74419409d1abbf (patch) | |
tree | 985ad7b05c0b4952ff76f83dfab87f18466ebe4f /drivers/net | |
parent | 1788f49548860fa1c861ee3454d47b466c877e43 (diff) |
virtio_net: fix oom handling on tx
virtio net will never try to overflow the TX ring, so the only reason
add_buf may fail is out of memory. Thus, we can not stop the
device until some request completes - there's no guarantee anything
at all is outstanding.
Make the error message clearer as well: error here does not
indicate queue full.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> (...and avoid TX_BUSY)
Cc: stable@kernel.org # .34.x (s/virtqueue_/vi->svq->vq_ops->/)
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/virtio_net.c | 21 |
1 files changed, 13 insertions, 8 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index ee7571195b10..bb6b67f6b0cc 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
@@ -562,7 +562,6 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
562 | struct virtnet_info *vi = netdev_priv(dev); | 562 | struct virtnet_info *vi = netdev_priv(dev); |
563 | int capacity; | 563 | int capacity; |
564 | 564 | ||
565 | again: | ||
566 | /* Free up any pending old buffers before queueing new ones. */ | 565 | /* Free up any pending old buffers before queueing new ones. */ |
567 | free_old_xmit_skbs(vi); | 566 | free_old_xmit_skbs(vi); |
568 | 567 | ||
@@ -571,14 +570,20 @@ again: | |||
571 | 570 | ||
572 | /* This can happen with OOM and indirect buffers. */ | 571 | /* This can happen with OOM and indirect buffers. */ |
573 | if (unlikely(capacity < 0)) { | 572 | if (unlikely(capacity < 0)) { |
574 | netif_stop_queue(dev); | 573 | if (net_ratelimit()) { |
575 | dev_warn(&dev->dev, "Unexpected full queue\n"); | 574 | if (likely(capacity == -ENOMEM)) { |
576 | if (unlikely(!virtqueue_enable_cb(vi->svq))) { | 575 | dev_warn(&dev->dev, |
577 | virtqueue_disable_cb(vi->svq); | 576 | "TX queue failure: out of memory\n"); |
578 | netif_start_queue(dev); | 577 | } else { |
579 | goto again; | 578 | dev->stats.tx_fifo_errors++; |
579 | dev_warn(&dev->dev, | ||
580 | "Unexpected TX queue failure: %d\n", | ||
581 | capacity); | ||
582 | } | ||
580 | } | 583 | } |
581 | return NETDEV_TX_BUSY; | 584 | dev->stats.tx_dropped++; |
585 | kfree_skb(skb); | ||
586 | return NETDEV_TX_OK; | ||
582 | } | 587 | } |
583 | virtqueue_kick(vi->svq); | 588 | virtqueue_kick(vi->svq); |
584 | 589 | ||