diff options
author | Patrick McHardy <kaber@trash.net> | 2008-11-04 17:49:57 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-11-04 17:49:57 -0500 |
commit | 9b22ea560957de1484e6b3e8538f7eef202e3596 (patch) | |
tree | e922feeebfc8795e8ec2f02b58a99a23ae0ce74b /include | |
parent | 79654a7698195fa043063092f5c1ca5245276fba (diff) |
net: fix packet socket delivery in rx irq handler
The changes to deliver hardware accelerated VLAN packets to packet
sockets (commit bc1d0411) caused a warning for non-NAPI drivers.
The __vlan_hwaccel_rx() function is called directly from the drivers
RX function, for non-NAPI drivers that means its still in RX IRQ
context:
[ 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]
[ 27.782738] [<c0155b17>] handle_IRQ_event+0x23/0x51
[ 27.782808] [<c015692e>] handle_edge_irq+0xc2/0x102
[ 27.782878] [<c0105fd5>] do_IRQ+0x4d/0x64
Split hardware accelerated VLAN reception into two parts to fix this:
- __vlan_hwaccel_rx just stores the VLAN TCI and performs the VLAN
device lookup, then calls netif_receive_skb()/netif_rx()
- vlan_hwaccel_do_receive(), which is invoked by netif_receive_skb()
in softirq context, performs the real reception and delivery to
packet sockets.
Reported-and-tested-by: Ramon Casellas <ramon.casellas@cttc.es>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/if_vlan.h | 7 |
1 files changed, 7 insertions, 0 deletions
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index 9e7b49b8062d..a5cb0c3f6dcf 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); | |||
114 | 114 | ||
115 | extern int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, | 115 | extern int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, |
116 | u16 vlan_tci, int polling); | 116 | u16 vlan_tci, int polling); |
117 | extern int vlan_hwaccel_do_receive(struct sk_buff *skb); | ||
118 | |||
117 | #else | 119 | #else |
118 | static inline struct net_device *vlan_dev_real_dev(const struct net_device *dev) | 120 | static inline struct net_device *vlan_dev_real_dev(const struct net_device *dev) |
119 | { | 121 | { |
@@ -133,6 +135,11 @@ static inline int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, | |||
133 | BUG(); | 135 | BUG(); |
134 | return NET_XMIT_SUCCESS; | 136 | return NET_XMIT_SUCCESS; |
135 | } | 137 | } |
138 | |||
139 | static inline int vlan_hwaccel_do_receive(struct sk_buff *skb) | ||
140 | { | ||
141 | return 0; | ||
142 | } | ||
136 | #endif | 143 | #endif |
137 | 144 | ||
138 | /** | 145 | /** |