All of lore.kernel.org
 help / color / mirror / Atom feed
From: Patrick McHardy <kaber@trash.net>
To: Jarek Poplawski <jarkao2@gmail.com>
Cc: Jay Cliburn <jcliburn@gmail.com>, netdev@vger.kernel.org
Subject: Re: atl1 warn_on_slowpath help
Date: Wed, 29 Oct 2008 11:17:09 +0100	[thread overview]
Message-ID: <49083825.3000601@trash.net> (raw)
In-Reply-To: <49081AE4.9040301@trash.net>

[-- Attachment #1: Type: text/plain, Size: 1315 bytes --]

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]  [<c0264755>] netif_nit_deliver+0x5b/0x75
>>> [   27.782590]  [<c02bba83>] __vlan_hwaccel_rx+0x79/0x162
>>> [   27.782664]  [<f8851c1d>] 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().


[-- Attachment #2: 01.diff --]
[-- Type: text/x-patch, Size: 3602 bytes --]

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 <linux/if_vlan.h>
 #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;

  reply	other threads:[~2008-10-29 10:17 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-10-29  0:08 atl1 warn_on_slowpath help Jay Cliburn
2008-10-29  7:15 ` Jarek Poplawski
2008-10-29  8:12   ` Patrick McHardy
2008-10-29 10:17     ` Patrick McHardy [this message]
2008-10-29 12:51       ` J. K. Cliburn
2008-10-29 12:54         ` Patrick McHardy
2008-10-29 14:15         ` Ramon Casellas
2008-10-29 16:47           ` Patrick McHardy
2008-10-29 13:03       ` Jarek Poplawski
2008-10-29 13:09         ` Patrick McHardy
2008-10-29 13:22           ` Jarek Poplawski
2008-10-29 13:26             ` Patrick McHardy
2008-10-29 14:04               ` Jarek Poplawski
2008-10-29 16:40                 ` Patrick McHardy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=49083825.3000601@trash.net \
    --to=kaber@trash.net \
    --cc=jarkao2@gmail.com \
    --cc=jcliburn@gmail.com \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.