aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge/br_device.c
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2010-05-10 12:39:28 -0400
committerPatrick McHardy <kaber@trash.net>2010-05-10 12:39:28 -0400
commit1e4b1057121bc756b91758a434b504d2010f6088 (patch)
treeb016cf2c728289c7e36d9e4e488f30ab0bd0ae6e /net/bridge/br_device.c
parent3b254c54ec46eb022cb26ee6ab37fae23f5f7d6a (diff)
parent3ee943728fff536edaf8f59faa58aaa1aa7366e3 (diff)
Merge branch 'master' of /repos/git/net-next-2.6
Conflicts: net/bridge/br_device.c net/bridge/br_forward.c Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net/bridge/br_device.c')
-rw-r--r--net/bridge/br_device.c62
1 files changed, 61 insertions, 1 deletions
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 007bde87415d..f15f9c4a0dd2 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -13,9 +13,12 @@
13 13
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include <linux/netdevice.h> 15#include <linux/netdevice.h>
16#include <linux/netpoll.h>
16#include <linux/etherdevice.h> 17#include <linux/etherdevice.h>
17#include <linux/ethtool.h> 18#include <linux/ethtool.h>
19#include <linux/list.h>
18#include <linux/netfilter_bridge.h> 20#include <linux/netfilter_bridge.h>
21
19#include <asm/uaccess.h> 22#include <asm/uaccess.h>
20#include "br_private.h" 23#include "br_private.h"
21 24
@@ -43,7 +46,7 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
43 skb_reset_mac_header(skb); 46 skb_reset_mac_header(skb);
44 skb_pull(skb, ETH_HLEN); 47 skb_pull(skb, ETH_HLEN);
45 48
46 if (dest[0] & 1) { 49 if (is_multicast_ether_addr(dest)) {
47 if (br_multicast_rcv(br, NULL, skb)) 50 if (br_multicast_rcv(br, NULL, skb))
48 goto out; 51 goto out;
49 52
@@ -195,6 +198,59 @@ static int br_set_tx_csum(struct net_device *dev, u32 data)
195 return 0; 198 return 0;
196} 199}
197 200
201#ifdef CONFIG_NET_POLL_CONTROLLER
202bool br_devices_support_netpoll(struct net_bridge *br)
203{
204 struct net_bridge_port *p;
205 bool ret = true;
206 int count = 0;
207 unsigned long flags;
208
209 spin_lock_irqsave(&br->lock, flags);
210 list_for_each_entry(p, &br->port_list, list) {
211 count++;
212 if ((p->dev->priv_flags & IFF_DISABLE_NETPOLL) ||
213 !p->dev->netdev_ops->ndo_poll_controller)
214 ret = false;
215 }
216 spin_unlock_irqrestore(&br->lock, flags);
217 return count != 0 && ret;
218}
219
220static void br_poll_controller(struct net_device *br_dev)
221{
222 struct netpoll *np = br_dev->npinfo->netpoll;
223
224 if (np->real_dev != br_dev)
225 netpoll_poll_dev(np->real_dev);
226}
227
228void br_netpoll_cleanup(struct net_device *br_dev)
229{
230 struct net_bridge *br = netdev_priv(br_dev);
231 struct net_bridge_port *p, *n;
232 const struct net_device_ops *ops;
233
234 br->dev->npinfo = NULL;
235 list_for_each_entry_safe(p, n, &br->port_list, list) {
236 if (p->dev) {
237 ops = p->dev->netdev_ops;
238 if (ops->ndo_netpoll_cleanup)
239 ops->ndo_netpoll_cleanup(p->dev);
240 else
241 p->dev->npinfo = NULL;
242 }
243 }
244}
245
246#else
247
248void br_netpoll_cleanup(struct net_device *br_dev)
249{
250}
251
252#endif
253
198static const struct ethtool_ops br_ethtool_ops = { 254static const struct ethtool_ops br_ethtool_ops = {
199 .get_drvinfo = br_getinfo, 255 .get_drvinfo = br_getinfo,
200 .get_link = ethtool_op_get_link, 256 .get_link = ethtool_op_get_link,
@@ -218,6 +274,10 @@ static const struct net_device_ops br_netdev_ops = {
218 .ndo_set_multicast_list = br_dev_set_multicast_list, 274 .ndo_set_multicast_list = br_dev_set_multicast_list,
219 .ndo_change_mtu = br_change_mtu, 275 .ndo_change_mtu = br_change_mtu,
220 .ndo_do_ioctl = br_dev_ioctl, 276 .ndo_do_ioctl = br_dev_ioctl,
277#ifdef CONFIG_NET_POLL_CONTROLLER
278 .ndo_netpoll_cleanup = br_netpoll_cleanup,
279 .ndo_poll_controller = br_poll_controller,
280#endif
221}; 281};
222 282
223static void br_dev_free(struct net_device *dev) 283static void br_dev_free(struct net_device *dev)