From patchwork Wed Oct 29 12:51:51 2008 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "J. K. Cliburn" X-Patchwork-Id: 6247 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.176.167]) by ozlabs.org (Postfix) with ESMTP id B2918DDDE7 for ; Wed, 29 Oct 2008 23:52:01 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753501AbYJ2Mv4 (ORCPT ); Wed, 29 Oct 2008 08:51:56 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1753419AbYJ2Mv4 (ORCPT ); Wed, 29 Oct 2008 08:51:56 -0400 Received: from nf-out-0910.google.com ([64.233.182.185]:18215 "EHLO nf-out-0910.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752756AbYJ2Mvz (ORCPT ); Wed, 29 Oct 2008 08:51:55 -0400 Received: by nf-out-0910.google.com with SMTP id d3so1255533nfc.21 for ; Wed, 29 Oct 2008 05:51:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from:to :subject:cc:in-reply-to:mime-version:content-type:references; bh=D399pSPo5P9Vm3V02hHCprfUYhHHQlKPyx4xJCkjhew=; b=mgalIdHmApxqSNQCSpocSCdT5VCtzkKvS+WffcFhAbpg9m21PhBCiR2rSsZBcsKBLV 9gNZuveoQiNHTs7PZKm3aA7pLmZ/Nn+SFbHi4jfEMYKrLTomsdKSwiITANlW4C1P9ZjG X3iR7FsUnN82KkcXwspG/7sxXNHUixKNQ4few= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:to:subject:cc:in-reply-to:mime-version :content-type:references; b=FleJkkzgzOL0daIHxSqeSIP/UB8vW07mAIVJOUFHdVF75DO/gKyOdyYJtYL5CF9iFa 8kymQIOUk4wvNEp5DmLOSTmLPj/w47q1zbsSZW8329m5QRf6dgaUVhhQYmGbBFkpsGKQ /ZKwhZxlA8+SRXKdLvujBOutoNGp0Iop+lwwE= Received: by 10.210.128.5 with SMTP id a5mr9989865ebd.26.1225284711916; Wed, 29 Oct 2008 05:51:51 -0700 (PDT) Received: by 10.210.78.14 with HTTP; Wed, 29 Oct 2008 05:51:51 -0700 (PDT) Message-ID: <3400f2f60810290551y39c61e0aj90ca1222b339798c@mail.gmail.com> Date: Wed, 29 Oct 2008 07:51:51 -0500 From: "J. K. Cliburn" To: "Patrick McHardy" Subject: Re: atl1 warn_on_slowpath help Cc: "Jarek Poplawski" , netdev@vger.kernel.org, "Ramon Casellas" In-Reply-To: <49083825.3000601@trash.net> MIME-Version: 1.0 References: <20081029071549.GA4861@ff.dom.local> <49081AE4.9040301@trash.net> <49083825.3000601@trash.net> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org [adding bug reporter to cc list] On Wed, Oct 29, 2008 at 5:17 AM, Patrick McHardy wrote: > Patrick McHardy wrote: >> >> Jarek Poplawski wrote: >>> >>> On 29-10-2008 01:08, Jay Cliburn wrote: >>>> >>>> [ 27.779463] ------------[ cut here ]------------ >>>> [ 27.779509] WARNING: at kernel/softirq.c:136 >>>> local_bh_enable+0x37/0x81() >>> >>> ... >>>> >>>> [ 27.782520] [] netif_nit_deliver+0x5b/0x75 >>>> [ 27.782590] [] __vlan_hwaccel_rx+0x79/0x162 >>>> [ 27.782664] [] atl1_intr+0x9a9/0xa7c [atl1] >>>>> >>>> warn_on_slowpath stuff well enough to know what to look for. Can someone >>>> please take a quick look at drivers/net/atlx/atl1.c around line 2017 >>>> and see if there's an obvious error? I'd really appreciate it. >>> >>> It looks to me like vlan_hwaccel_rx() is to blame: I doubt we can do >>> netif_nit_deliver() in hard irq context. (Patrick Cc-ed.) >> >> Crap, I didn't think of that, all drivers I tested with support >> NAPI. I can't think of a clean way to fix it right now, but I'll >> look into it. > > This is the best I could come up with, short of simply restoring > the old behaviour for non-polling drivers. > > The __vlan_hwaccel_rx function only does the device lookup and > stores it in the cb. The remaining processing is done in a new > function that is invoked by netif_receive_skb(), in the proper > context. Unfortunatly this needs vlan-specific handling in > netif_receive_skb(). > > Thanks Jarek and Patrick. Ramon, Can you please try the attached patch from Patrick and see if it fixes your kernel warning? Thanks, Jay diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index 9e7b49b..a5cb0c3 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -114,6 +114,8 @@ extern u16 vlan_dev_vlan_id(const struct net_device *dev); extern int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, u16 vlan_tci, int polling); +extern int vlan_hwaccel_do_receive(struct sk_buff *skb); + #else static inline struct net_device *vlan_dev_real_dev(const struct net_device *dev) { @@ -133,6 +135,11 @@ static inline int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, BUG(); return NET_XMIT_SUCCESS; } + +static inline int vlan_hwaccel_do_receive(struct sk_buff *skb) +{ + return 0; +} #endif /** diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index 916061f..68ced4b 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -3,11 +3,20 @@ #include #include "vlan.h" +struct vlan_hwaccel_cb { + struct net_device *dev; +}; + +static inline struct vlan_hwaccel_cb *vlan_hwaccel_cb(struct sk_buff *skb) +{ + return (struct vlan_hwaccel_cb *)skb->cb; +} + /* VLAN rx hw acceleration helper. This acts like netif_{rx,receive_skb}(). */ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, u16 vlan_tci, int polling) { - struct net_device_stats *stats; + struct vlan_hwaccel_cb *cb = vlan_hwaccel_cb(skb); if (skb_bond_should_drop(skb)) { dev_kfree_skb_any(skb); @@ -15,23 +24,35 @@ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, } skb->vlan_tci = vlan_tci; + cb->dev = vlan_group_get_device(grp, vlan_tci & VLAN_VID_MASK); + + return (polling ? netif_receive_skb(skb) : netif_rx(skb)); +} +EXPORT_SYMBOL(__vlan_hwaccel_rx); + +int vlan_hwaccel_do_receive(struct sk_buff *skb) +{ + struct vlan_hwaccel_cb *cb = vlan_hwaccel_cb(skb); + struct net_device *dev = cb->dev; + struct net_device_stats *stats; + netif_nit_deliver(skb); - skb->dev = vlan_group_get_device(grp, vlan_tci & VLAN_VID_MASK); - if (skb->dev == NULL) { - dev_kfree_skb_any(skb); - /* Not NET_RX_DROP, this is not being dropped - * due to congestion. */ - return NET_RX_SUCCESS; + if (dev == NULL) { + kfree_skb(skb); + return -1; } - skb->dev->last_rx = jiffies; + + skb->dev = dev; + skb->priority = vlan_get_ingress_priority(dev, skb->vlan_tci); skb->vlan_tci = 0; - stats = &skb->dev->stats; + dev->last_rx = jiffies; + + stats = &dev->stats; stats->rx_packets++; stats->rx_bytes += skb->len; - skb->priority = vlan_get_ingress_priority(skb->dev, vlan_tci); switch (skb->pkt_type) { case PACKET_BROADCAST: break; @@ -43,13 +64,12 @@ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, * This allows the VLAN to have a different MAC than the * underlying device, and still route correctly. */ if (!compare_ether_addr(eth_hdr(skb)->h_dest, - skb->dev->dev_addr)) + dev->dev_addr)) skb->pkt_type = PACKET_HOST; break; }; - return (polling ? netif_receive_skb(skb) : netif_rx(skb)); + return 0; } -EXPORT_SYMBOL(__vlan_hwaccel_rx); struct net_device *vlan_dev_real_dev(const struct net_device *dev) { diff --git a/net/core/dev.c b/net/core/dev.c index d9038e3..9174c77 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2218,6 +2218,9 @@ int netif_receive_skb(struct sk_buff *skb) int ret = NET_RX_DROP; __be16 type; + if (skb->vlan_tci && vlan_hwaccel_do_receive(skb)) + return NET_RX_SUCCESS; + /* if we've gotten here through NAPI, check netpoll */ if (netpoll_receive_skb(skb)) return NET_RX_DROP;