diff options
Diffstat (limited to 'drivers/net/virtio_net.c')
-rw-r--r-- | drivers/net/virtio_net.c | 42 |
1 files changed, 30 insertions, 12 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 1edb7a61983c..4598e9d2608f 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -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); @@ -701,6 +705,19 @@ static int virtnet_close(struct net_device *dev) return 0; } +static void virtnet_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *drvinfo) +{ + struct virtnet_info *vi = netdev_priv(dev); + struct virtio_device *vdev = vi->vdev; + + strncpy(drvinfo->driver, KBUILD_MODNAME, ARRAY_SIZE(drvinfo->driver)); + strncpy(drvinfo->version, "N/A", ARRAY_SIZE(drvinfo->version)); + strncpy(drvinfo->fw_version, "N/A", ARRAY_SIZE(drvinfo->fw_version)); + strncpy(drvinfo->bus_info, dev_name(&vdev->dev), + ARRAY_SIZE(drvinfo->bus_info)); +} + static int virtnet_set_tx_csum(struct net_device *dev, u32 data) { struct virtnet_info *vi = netdev_priv(dev); @@ -813,6 +830,7 @@ static void virtnet_vlan_rx_kill_vid(struct net_device *dev, u16 vid) } static const struct ethtool_ops virtnet_ethtool_ops = { + .get_drvinfo = virtnet_get_drvinfo, .set_tx_csum = virtnet_set_tx_csum, .set_sg = ethtool_op_set_sg, .set_tso = ethtool_op_set_tso, |