From patchwork Sat Dec 19 02:09:46 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Scott Feldman X-Patchwork-Id: 41458 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46AF7B6F10 for ; Sat, 19 Dec 2009 13:09:55 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932658AbZLSCJt (ORCPT ); Fri, 18 Dec 2009 21:09:49 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S932126AbZLSCJt (ORCPT ); Fri, 18 Dec 2009 21:09:49 -0500 Received: from sj-iport-6.cisco.com ([171.71.176.117]:17463 "EHLO sj-iport-6.cisco.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932331AbZLSCJq (ORCPT ); Fri, 18 Dec 2009 21:09:46 -0500 Authentication-Results: sj-iport-6.cisco.com; dkim=neutral (message not signed) header.i=none X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: ApsEAALFK0urRN+K/2dsb2JhbACECrp7hwCQD4Evgi1SBA X-IronPort-AV: E=Sophos;i="4.47,421,1257120000"; d="scan'208";a="452613110" Received: from sj-core-4.cisco.com ([171.68.223.138]) by sj-iport-6.cisco.com with ESMTP; 19 Dec 2009 02:09:46 +0000 Received: from savbu-pc100.cisco.com (savbu-pc100.cisco.com [10.193.164.29]) by sj-core-4.cisco.com (8.13.8/8.14.3) with ESMTP id nBJ29kZF023801; Sat, 19 Dec 2009 02:09:46 GMT From: Scott Feldman Subject: [net-next PATCH 2/6] enic: Bug fix: try harder to fill Rx ring on skb allocation failures To: davem@davemloft.net Cc: netdev@vger.kernel.org Date: Fri, 18 Dec 2009 18:09:46 -0800 Message-ID: <20091219020946.2745.7226.stgit@savbu-pc100.cisco.com> In-Reply-To: <20091219020758.2745.85264.stgit@savbu-pc100.cisco.com> References: <20091219020758.2745.85264.stgit@savbu-pc100.cisco.com> User-Agent: StGIT/0.12.1 MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org enic: Bug fix: try harder to fill Rx ring on skb allocation failures During probe(), make sure we get at least one skb on the Rx ring. Otherwise abort the interface load. Also, if we get skb allocation failures in NAPI poll while trying to replenish the ring, try again later so we don't end up starving out the Rx ring completely. Signed-off-by: Scott Feldman Signed-off-by: Vasanthy Kolluri --- drivers/net/enic/enic_main.c | 54 ++++++++++++++++++++++++++---------------- 1 files changed, 33 insertions(+), 21 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 496e8b6..0265b25 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -1092,6 +1092,7 @@ static int enic_poll(struct napi_struct *napi, int budget) unsigned int rq_work_to_do = budget; unsigned int wq_work_to_do = -1; /* no limit */ unsigned int work_done, rq_work_done, wq_work_done; + int err; /* Service RQ (first) and WQ */ @@ -1115,16 +1116,19 @@ static int enic_poll(struct napi_struct *napi, int budget) 0 /* don't unmask intr */, 0 /* don't reset intr timer */); - if (rq_work_done > 0) { + err = vnic_rq_fill(&enic->rq[0], enic->rq_alloc_buf); - /* Replenish RQ - */ + /* Buffer allocation failed. Stay in polling + * mode so we can try to fill the ring again. + */ - vnic_rq_fill(&enic->rq[0], enic->rq_alloc_buf); + if (err) + rq_work_done = rq_work_to_do; - } else { + if (rq_work_done < rq_work_to_do) { - /* If no work done, flush all LROs and exit polling + /* Some work done, but not enough to stay in polling, + * flush all LROs and exit polling */ if (netdev->features & NETIF_F_LRO) @@ -1143,6 +1147,7 @@ static int enic_poll_msix(struct napi_struct *napi, int budget) struct net_device *netdev = enic->netdev; unsigned int work_to_do = budget; unsigned int work_done; + int err; /* Service RQ */ @@ -1150,25 +1155,30 @@ static int enic_poll_msix(struct napi_struct *napi, int budget) work_done = vnic_cq_service(&enic->cq[ENIC_CQ_RQ], work_to_do, enic_rq_service, NULL); - if (work_done > 0) { - - /* Replenish RQ - */ - - vnic_rq_fill(&enic->rq[0], enic->rq_alloc_buf); - - /* Return intr event credits for this polling - * cycle. An intr event is the completion of a - * RQ packet. - */ + /* Return intr event credits for this polling + * cycle. An intr event is the completion of a + * RQ packet. + */ + if (work_done > 0) vnic_intr_return_credits(&enic->intr[ENIC_MSIX_RQ], work_done, 0 /* don't unmask intr */, 0 /* don't reset intr timer */); - } else { - /* If no work done, flush all LROs and exit polling + err = vnic_rq_fill(&enic->rq[0], enic->rq_alloc_buf); + + /* Buffer allocation failed. Stay in polling mode + * so we can try to fill the ring again. + */ + + if (err) + work_done = work_to_do; + + if (work_done < work_to_do) { + + /* Some work done, but not enough to stay in polling, + * flush all LROs and exit polling */ if (netdev->features & NETIF_F_LRO) @@ -1333,11 +1343,13 @@ static int enic_open(struct net_device *netdev) } for (i = 0; i < enic->rq_count; i++) { - err = vnic_rq_fill(&enic->rq[i], enic->rq_alloc_buf); - if (err) { + vnic_rq_fill(&enic->rq[i], enic->rq_alloc_buf); + /* Need at least one buffer on ring to get going */ + if (vnic_rq_desc_used(&enic->rq[i]) == 0) { printk(KERN_ERR PFX "%s: Unable to alloc receive buffers.\n", netdev->name); + err = -ENOMEM; goto err_out_notify_unset; } }