From patchwork Thu Apr 11 18:02:59 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Willy Tarreau X-Patchwork-Id: 2429831 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) by patchwork2.kernel.org (Postfix) with ESMTP id 1A18CDF230 for ; Thu, 11 Apr 2013 18:03:27 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UQLqD-0007d5-P7; Thu, 11 Apr 2013 18:03:21 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UQLqA-0000sD-Qt; Thu, 11 Apr 2013 18:03:18 +0000 Received: from 1wt.eu ([62.212.114.60]) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UQLq7-0000rr-Aj for linux-arm-kernel@lists.infradead.org; Thu, 11 Apr 2013 18:03:16 +0000 Received: (from willy@localhost) by mail.home.local (8.14.4/8.14.4/Submit) id r3BI2xkF005904; Thu, 11 Apr 2013 20:02:59 +0200 Date: Thu, 11 Apr 2013 20:02:59 +0200 From: Willy Tarreau To: Eric Dumazet Subject: Re: [PATCH] net: mv643xx_eth: Add GRO support Message-ID: <20130411180259.GO1910@1wt.eu> References: <20130411150326.GA19978@1wt.eu> <20130411.133119.913809939413807690.davem@davemloft.net> <20130411175147.GN1910@1wt.eu> <1365703155.3887.184.camel@edumazet-glaptop> Mime-Version: 1.0 Content-Disposition: inline In-Reply-To: <1365703155.3887.184.camel@edumazet-glaptop> User-Agent: Mutt/1.4.2.3i X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130411_140316_174301_B2A02A87 X-CRM114-Status: GOOD ( 22.59 ) X-Spam-Score: -2.5 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.5 points) pts rule name description ---- ---------------------- -------------------------------------------------- 1.7 KHOP_BIG_TO_CC Sent to 10+ recipients instaed of Bcc or a list -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.0 SPF_PASS SPF: sender matches SPF record -2.4 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: andrew@lunn.ch, jason@lakedaemon.net, benh@kernel.crashing.org, linux-kernel@vger.kernel.org, florian@openwrt.org, smoch@web.de, paulus@samba.org, linux-arm-kernel@lists.infradead.org, dale@farnsworth.org, netdev@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, David Miller , buytenh@wantstofly.org, sebastian.hesselbarth@gmail.com X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org On Thu, Apr 11, 2013 at 10:59:15AM -0700, Eric Dumazet wrote: > On Thu, 2013-04-11 at 19:51 +0200, Willy Tarreau wrote: > > > Eric provided me with one such experimental patch in the past for this > > driver. It worked for me but we never tried to clean it up to propose > > it for inclusion. > > > > If anyone is interested, I might still have it in experimental shape. > > We are interested a lot ;) Just found it in one of my local branches :-) Here it is. It was experimental. At first glance, I'm seeing it does not remove NETIF_F_LRO as we used it for experimentation only, but that's a trivial thing to fix. Original work by you Eric, tested by me on 3.6. Regards, Willy diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index ea2cedc..81a6cb0 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -55,9 +55,9 @@ #include #include #include -#include #include #include +#include static char mv643xx_eth_driver_name[] = "mv643xx_eth"; static char mv643xx_eth_driver_version[] = "1.4"; @@ -343,12 +343,6 @@ struct mib_counters { u32 rx_overrun; }; -struct lro_counters { - u32 lro_aggregated; - u32 lro_flushed; - u32 lro_no_desc; -}; - struct rx_queue { int index; @@ -363,8 +357,6 @@ struct rx_queue { int rx_desc_area_size; void **rx_data; unsigned int frag_size; - struct net_lro_mgr lro_mgr; - struct net_lro_desc lro_arr[8]; }; struct tx_queue { @@ -400,8 +392,6 @@ struct mv643xx_eth_private { spinlock_t mib_counters_lock; struct mib_counters mib_counters; - struct lro_counters lro_counters; - struct work_struct tx_timeout_task; struct napi_struct napi; @@ -533,33 +523,6 @@ static void txq_maybe_wake(struct tx_queue *txq) } -/* rx napi ******************************************************************/ -static int -mv643xx_get_skb_header(struct sk_buff *skb, void **iphdr, void **tcph, - u64 *hdr_flags, void *priv) -{ - unsigned long cmd_sts = (unsigned long)priv; - - /* - * Make sure that this packet is Ethernet II, is not VLAN - * tagged, is IPv4, has a valid IP header, and is TCP. - */ - if ((cmd_sts & (RX_IP_HDR_OK | RX_PKT_IS_IPV4 | - RX_PKT_IS_ETHERNETV2 | RX_PKT_LAYER4_TYPE_MASK | - RX_PKT_IS_VLAN_TAGGED)) != - (RX_IP_HDR_OK | RX_PKT_IS_IPV4 | - RX_PKT_IS_ETHERNETV2 | RX_PKT_LAYER4_TYPE_TCP_IPV4)) - return -1; - - skb_reset_network_header(skb); - skb_set_transport_header(skb, ip_hdrlen(skb)); - *iphdr = ip_hdr(skb); - *tcph = tcp_hdr(skb); - *hdr_flags = LRO_IPV4 | LRO_TCP; - - return 0; -} - static void mv_frag_free(const struct rx_queue *rxq, void *data) { if (rxq->frag_size) @@ -568,14 +531,12 @@ static void mv_frag_free(const struct rx_queue *rxq, void *data) kfree(data); } -static int rxq_process(struct rx_queue *rxq, int budget) +static int rxq_process(struct napi_struct *napi, struct rx_queue *rxq, int budget) { struct mv643xx_eth_private *mp = rxq_to_mp(rxq); struct net_device_stats *stats = &mp->dev->stats; - int lro_flush_needed; int rx; - lro_flush_needed = 0; rx = 0; while (rx < budget && rxq->rx_desc_count) { struct rx_desc *rx_desc; @@ -646,12 +607,7 @@ static int rxq_process(struct rx_queue *rxq, int budget) skb->ip_summed = CHECKSUM_UNNECESSARY; skb->protocol = eth_type_trans(skb, mp->dev); - if (skb->dev->features & NETIF_F_LRO && - skb->ip_summed == CHECKSUM_UNNECESSARY) { - lro_receive_skb(&rxq->lro_mgr, skb, (void *)cmd_sts); - lro_flush_needed = 1; - } else - netif_receive_skb(skb); + napi_gro_receive(napi, skb); continue; @@ -671,9 +627,6 @@ err: dev_kfree_skb(skb); } - if (lro_flush_needed) - lro_flush_all(&rxq->lro_mgr); - if (rx < budget) mp->work_rx &= ~(1 << rxq->index); @@ -723,7 +676,6 @@ static int rxq_refill(struct rx_queue *rxq, int budget) rxq->rx_data[rx] = data; wmb(); rx_desc->cmd_sts = BUFFER_OWNED_BY_DMA | RX_ENABLE_INTERRUPT; - } if (refilled < budget) @@ -1214,26 +1166,6 @@ static struct net_device_stats *mv643xx_eth_get_stats(struct net_device *dev) return stats; } -static void mv643xx_eth_grab_lro_stats(struct mv643xx_eth_private *mp) -{ - u32 lro_aggregated = 0; - u32 lro_flushed = 0; - u32 lro_no_desc = 0; - int i; - - for (i = 0; i < mp->rxq_count; i++) { - struct rx_queue *rxq = mp->rxq + i; - - lro_aggregated += rxq->lro_mgr.stats.aggregated; - lro_flushed += rxq->lro_mgr.stats.flushed; - lro_no_desc += rxq->lro_mgr.stats.no_desc; - } - - mp->lro_counters.lro_aggregated = lro_aggregated; - mp->lro_counters.lro_flushed = lro_flushed; - mp->lro_counters.lro_no_desc = lro_no_desc; -} - static inline u32 mib_read(struct mv643xx_eth_private *mp, int offset) { return rdl(mp, MIB_COUNTERS(mp->port_num) + offset); @@ -1397,10 +1329,6 @@ struct mv643xx_eth_stats { { #m, FIELD_SIZEOF(struct mib_counters, m), \ -1, offsetof(struct mv643xx_eth_private, mib_counters.m) } -#define LROSTAT(m) \ - { #m, FIELD_SIZEOF(struct lro_counters, m), \ - -1, offsetof(struct mv643xx_eth_private, lro_counters.m) } - static const struct mv643xx_eth_stats mv643xx_eth_stats[] = { SSTAT(rx_packets), SSTAT(tx_packets), @@ -1442,9 +1370,6 @@ static const struct mv643xx_eth_stats mv643xx_eth_stats[] = { MIBSTAT(late_collision), MIBSTAT(rx_discard), MIBSTAT(rx_overrun), - LROSTAT(lro_aggregated), - LROSTAT(lro_flushed), - LROSTAT(lro_no_desc), }; static int @@ -1642,7 +1567,6 @@ static void mv643xx_eth_get_ethtool_stats(struct net_device *dev, mv643xx_eth_get_stats(dev); mib_counters_update(mp); - mv643xx_eth_grab_lro_stats(mp); for (i = 0; i < ARRAY_SIZE(mv643xx_eth_stats); i++) { const struct mv643xx_eth_stats *stat; @@ -1915,19 +1839,6 @@ static int rxq_init(struct mv643xx_eth_private *mp, int index) nexti * sizeof(struct rx_desc); } - rxq->lro_mgr.dev = mp->dev; - memset(&rxq->lro_mgr.stats, 0, sizeof(rxq->lro_mgr.stats)); - rxq->lro_mgr.features = LRO_F_NAPI; - rxq->lro_mgr.ip_summed = CHECKSUM_UNNECESSARY; - rxq->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY; - rxq->lro_mgr.max_desc = ARRAY_SIZE(rxq->lro_arr); - rxq->lro_mgr.max_aggr = 32; - rxq->lro_mgr.frag_align_pad = 0; - rxq->lro_mgr.lro_arr = rxq->lro_arr; - rxq->lro_mgr.get_skb_header = mv643xx_get_skb_header; - - memset(&rxq->lro_arr, 0, sizeof(rxq->lro_arr)); - return 0; @@ -2192,7 +2103,7 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget) work_done += txq_reclaim(mp->txq + queue, work_tbd, 0); txq_maybe_wake(mp->txq + queue); } else if (mp->work_rx & queue_mask) { - work_done += rxq_process(mp->rxq + queue, work_tbd); + work_done += rxq_process(napi, mp->rxq + queue, work_tbd); } else if (!mp->oom && (mp->work_rx_refill & queue_mask)) { work_done += rxq_refill(mp->rxq + queue, work_tbd); } else {