diff options
Diffstat (limited to 'drivers/net/virtio_net.c')
| -rw-r--r-- | drivers/net/virtio_net.c | 36 | 
1 files changed, 20 insertions, 16 deletions
| diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 78eb3190b9b..bb6b67f6b0c 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -340,7 +340,7 @@ static int add_recvbuf_small(struct virtnet_info *vi, gfp_t gfp)  	skb_to_sgvec(skb, vi->rx_sg + 1, 0, skb->len); -	err = virtqueue_add_buf(vi->rvq, vi->rx_sg, 0, 2, skb); +	err = virtqueue_add_buf_gfp(vi->rvq, vi->rx_sg, 0, 2, skb, gfp);  	if (err < 0)  		dev_kfree_skb(skb); @@ -385,8 +385,8 @@ static int add_recvbuf_big(struct virtnet_info *vi, gfp_t gfp)  	/* chain first in list head */  	first->private = (unsigned long)list; -	err = virtqueue_add_buf(vi->rvq, vi->rx_sg, 0, MAX_SKB_FRAGS + 2, -				       first); +	err = virtqueue_add_buf_gfp(vi->rvq, vi->rx_sg, 0, MAX_SKB_FRAGS + 2, +				    first, gfp);  	if (err < 0)  		give_pages(vi, first); @@ -404,7 +404,7 @@ static int add_recvbuf_mergeable(struct virtnet_info *vi, gfp_t gfp)  	sg_init_one(vi->rx_sg, page_address(page), PAGE_SIZE); -	err = virtqueue_add_buf(vi->rvq, vi->rx_sg, 0, 1, page); +	err = virtqueue_add_buf_gfp(vi->rvq, vi->rx_sg, 0, 1, page, gfp);  	if (err < 0)  		give_pages(vi, page); @@ -415,7 +415,7 @@ static int add_recvbuf_mergeable(struct virtnet_info *vi, gfp_t gfp)  static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp)  {  	int err; -	bool oom = false; +	bool oom;  	do {  		if (vi->mergeable_rx_bufs) @@ -425,10 +425,9 @@ static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp)  		else  			err = add_recvbuf_small(vi, gfp); -		if (err < 0) { -			oom = true; +		oom = err == -ENOMEM; +		if (err < 0)  			break; -		}  		++vi->num;  	} while (err > 0);  	if (unlikely(vi->num > vi->max)) @@ -563,7 +562,6 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)  	struct virtnet_info *vi = netdev_priv(dev);  	int capacity; -again:  	/* Free up any pending old buffers before queueing new ones. */  	free_old_xmit_skbs(vi); @@ -572,14 +570,20 @@ again:  	/* This can happen with OOM and indirect buffers. */  	if (unlikely(capacity < 0)) { -		netif_stop_queue(dev); -		dev_warn(&dev->dev, "Unexpected full queue\n"); -		if (unlikely(!virtqueue_enable_cb(vi->svq))) { -			virtqueue_disable_cb(vi->svq); -			netif_start_queue(dev); -			goto again; +		if (net_ratelimit()) { +			if (likely(capacity == -ENOMEM)) { +				dev_warn(&dev->dev, +					 "TX queue failure: out of memory\n"); +			} else { +				dev->stats.tx_fifo_errors++; +				dev_warn(&dev->dev, +					 "Unexpected TX queue failure: %d\n", +					 capacity); +			}  		} -		return NETDEV_TX_BUSY; +		dev->stats.tx_dropped++; +		kfree_skb(skb); +		return NETDEV_TX_OK;  	}  	virtqueue_kick(vi->svq); | 
