diff options
author | WANG Cong <amwang@redhat.com> | 2010-05-06 03:48:24 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-05-06 03:48:24 -0400 |
commit | c06ee961d3c0e51009cbd0e123b61fbb97f37d0b (patch) | |
tree | 5d5899374a6f32f5ab77a78e6baeeb4a122a4721 /net/bridge/br_device.c | |
parent | 0e34e93177fb1f642cab080e0bde664c06c7183a (diff) |
bridge: make bridge support netpoll
Based on the previous patch, make bridge support netpoll by:
1) implement the 2 methods to support netpoll for bridge;
2) modify netpoll during forwarding packets via bridge;
3) disable netpoll support of bridge when a netpoll-unabled device
is added to bridge;
4) enable netpoll support when all underlying devices support netpoll.
Cc: David Miller <davem@davemloft.net>
Cc: Neil Horman <nhorman@tuxdriver.com>
Cc: Stephen Hemminger <shemminger@linux-foundation.org>
Cc: Matt Mackall <mpm@selenic.com>
Signed-off-by: WANG Cong <amwang@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge/br_device.c')
-rw-r--r-- | net/bridge/br_device.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 82599405dc15..074c59690fc5 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c | |||
@@ -13,8 +13,10 @@ | |||
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 | 20 | ||
19 | #include <asm/uaccess.h> | 21 | #include <asm/uaccess.h> |
20 | #include "br_private.h" | 22 | #include "br_private.h" |
@@ -188,6 +190,59 @@ static int br_set_tx_csum(struct net_device *dev, u32 data) | |||
188 | return 0; | 190 | return 0; |
189 | } | 191 | } |
190 | 192 | ||
193 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
194 | bool br_devices_support_netpoll(struct net_bridge *br) | ||
195 | { | ||
196 | struct net_bridge_port *p; | ||
197 | bool ret = true; | ||
198 | int count = 0; | ||
199 | unsigned long flags; | ||
200 | |||
201 | spin_lock_irqsave(&br->lock, flags); | ||
202 | list_for_each_entry(p, &br->port_list, list) { | ||
203 | count++; | ||
204 | if ((p->dev->priv_flags & IFF_DISABLE_NETPOLL) || | ||
205 | !p->dev->netdev_ops->ndo_poll_controller) | ||
206 | ret = false; | ||
207 | } | ||
208 | spin_unlock_irqrestore(&br->lock, flags); | ||
209 | return count != 0 && ret; | ||
210 | } | ||
211 | |||
212 | static void br_poll_controller(struct net_device *br_dev) | ||
213 | { | ||
214 | struct netpoll *np = br_dev->npinfo->netpoll; | ||
215 | |||
216 | if (np->real_dev != br_dev) | ||
217 | netpoll_poll_dev(np->real_dev); | ||
218 | } | ||
219 | |||
220 | void br_netpoll_cleanup(struct net_device *br_dev) | ||
221 | { | ||
222 | struct net_bridge *br = netdev_priv(br_dev); | ||
223 | struct net_bridge_port *p, *n; | ||
224 | const struct net_device_ops *ops; | ||
225 | |||
226 | br->dev->npinfo = NULL; | ||
227 | list_for_each_entry_safe(p, n, &br->port_list, list) { | ||
228 | if (p->dev) { | ||
229 | ops = p->dev->netdev_ops; | ||
230 | if (ops->ndo_netpoll_cleanup) | ||
231 | ops->ndo_netpoll_cleanup(p->dev); | ||
232 | else | ||
233 | p->dev->npinfo = NULL; | ||
234 | } | ||
235 | } | ||
236 | } | ||
237 | |||
238 | #else | ||
239 | |||
240 | void br_netpoll_cleanup(struct net_device *br_dev) | ||
241 | { | ||
242 | } | ||
243 | |||
244 | #endif | ||
245 | |||
191 | static const struct ethtool_ops br_ethtool_ops = { | 246 | static const struct ethtool_ops br_ethtool_ops = { |
192 | .get_drvinfo = br_getinfo, | 247 | .get_drvinfo = br_getinfo, |
193 | .get_link = ethtool_op_get_link, | 248 | .get_link = ethtool_op_get_link, |
@@ -211,6 +266,10 @@ static const struct net_device_ops br_netdev_ops = { | |||
211 | .ndo_set_multicast_list = br_dev_set_multicast_list, | 266 | .ndo_set_multicast_list = br_dev_set_multicast_list, |
212 | .ndo_change_mtu = br_change_mtu, | 267 | .ndo_change_mtu = br_change_mtu, |
213 | .ndo_do_ioctl = br_dev_ioctl, | 268 | .ndo_do_ioctl = br_dev_ioctl, |
269 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
270 | .ndo_netpoll_cleanup = br_netpoll_cleanup, | ||
271 | .ndo_poll_controller = br_poll_controller, | ||
272 | #endif | ||
214 | }; | 273 | }; |
215 | 274 | ||
216 | static void br_dev_free(struct net_device *dev) | 275 | static void br_dev_free(struct net_device *dev) |