From patchwork Thu Mar 17 00:12:55 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shirley Ma X-Patchwork-Id: 640781 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p2H0DE3t004966 for ; Thu, 17 Mar 2011 00:13:15 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751853Ab1CQANG (ORCPT ); Wed, 16 Mar 2011 20:13:06 -0400 Received: from e39.co.us.ibm.com ([32.97.110.160]:46976 "EHLO e39.co.us.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751048Ab1CQANE (ORCPT ); Wed, 16 Mar 2011 20:13:04 -0400 Received: from d03relay02.boulder.ibm.com (d03relay02.boulder.ibm.com [9.17.195.227]) by e39.co.us.ibm.com (8.14.4/8.13.1) with ESMTP id p2H006FO004336; Wed, 16 Mar 2011 18:00:06 -0600 Received: from d03av06.boulder.ibm.com (d03av06.boulder.ibm.com [9.17.195.245]) by d03relay02.boulder.ibm.com (8.13.8/8.13.8/NCO v9.1) with ESMTP id p2H0D3ZC103050; Wed, 16 Mar 2011 18:13:03 -0600 Received: from d03av06.boulder.ibm.com (loopback [127.0.0.1]) by d03av06.boulder.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id p2H0Holo013183; Wed, 16 Mar 2011 18:17:50 -0600 Received: from [9.65.99.92] (sig-9-65-99-92.mts.ibm.com [9.65.99.92]) by d03av06.boulder.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id p2H0Hhaf012647; Wed, 16 Mar 2011 18:17:44 -0600 Subject: [PATCH 2/2] virtio_net: remove send completion interrupts and avoid TX queue overrun through packet drop From: Shirley Ma To: "Michael S. Tsirkin" , Rusty Russell Cc: David Miller , kvm@vger.kernel.org, netdev@vger.kernel.org Date: Wed, 16 Mar 2011 17:12:55 -0700 Message-ID: <1300320775.3255.34.camel@localhost.localdomain> Mime-Version: 1.0 X-Mailer: Evolution 2.28.3 (2.28.3-1.fc12) Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Thu, 17 Mar 2011 00:13:15 +0000 (UTC) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 82dba5a..c603daa 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -509,19 +510,18 @@ again: return received; } -static unsigned int free_old_xmit_skbs(struct virtnet_info *vi) +static void free_old_xmit_skbs(struct virtnet_info *vi) { struct sk_buff *skb; - unsigned int len, tot_sgs = 0; + unsigned int len; while ((skb = virtqueue_get_buf(vi->svq, &len)) != NULL) { pr_debug("Sent skb %p\n", skb); vi->dev->stats.tx_bytes += skb->len; vi->dev->stats.tx_packets++; - tot_sgs += skb_vnet_hdr(skb)->num_sg; dev_kfree_skb_any(skb); } - return tot_sgs; + return; } static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb) @@ -574,11 +574,26 @@ static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb) static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) { struct virtnet_info *vi = netdev_priv(dev); + bool drop; + bool indirect = virtio_has_feature(vi->vdev, + VIRTIO_RING_F_INDIRECT_DESC); int capacity; /* Free up any pending old buffers before queueing new ones. */ free_old_xmit_skbs(vi); - + capacity = virtqueue_get_capacity(vi->svq); + + /* Drop packet instead of stop queue for better performance */ + drop = (capacity == 0 && indirect) || + ((capacity < MAX_SKB_FRAGS + 2) && !indirect); + if (unlikely(drop)) { + dev->stats.tx_fifo_errors++; + dev_warn(&dev->dev, "Unexpected TX queue failure: %d\n", + capacity); + dev->stats.tx_dropped++; + kfree_skb(skb); + return NETDEV_TX_OK; + } /* Try to transmit */ capacity = xmit_skb(vi, skb); @@ -605,20 +620,6 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) skb_orphan(skb); nf_reset(skb); - /* Apparently nice girls don't return TX_BUSY; stop the queue - * before it gets out of hand. Naturally, this wastes entries. */ - if (capacity < 2+MAX_SKB_FRAGS) { - netif_stop_queue(dev); - if (unlikely(!virtqueue_enable_cb(vi->svq))) { - /* More just got used, free them then recheck. */ - capacity += free_old_xmit_skbs(vi); - if (capacity >= 2+MAX_SKB_FRAGS) { - netif_start_queue(dev); - virtqueue_disable_cb(vi->svq); - } - } - } - return NETDEV_TX_OK; }