diff options
Diffstat (limited to 'net/bridge')
-rw-r--r-- | net/bridge/br_device.c | 30 | ||||
-rw-r--r-- | net/bridge/br_forward.c | 2 | ||||
-rw-r--r-- | net/bridge/br_if.c | 6 | ||||
-rw-r--r-- | net/bridge/br_private.h | 4 |
4 files changed, 21 insertions, 21 deletions
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 333484537600..070e8a68cfc6 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c | |||
@@ -31,9 +31,11 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) | |||
31 | struct net_bridge_mdb_entry *mdst; | 31 | struct net_bridge_mdb_entry *mdst; |
32 | struct br_cpu_netstats *brstats = this_cpu_ptr(br->stats); | 32 | struct br_cpu_netstats *brstats = this_cpu_ptr(br->stats); |
33 | 33 | ||
34 | rcu_read_lock(); | ||
34 | #ifdef CONFIG_BRIDGE_NETFILTER | 35 | #ifdef CONFIG_BRIDGE_NETFILTER |
35 | if (skb->nf_bridge && (skb->nf_bridge->mask & BRNF_BRIDGED_DNAT)) { | 36 | if (skb->nf_bridge && (skb->nf_bridge->mask & BRNF_BRIDGED_DNAT)) { |
36 | br_nf_pre_routing_finish_bridge_slow(skb); | 37 | br_nf_pre_routing_finish_bridge_slow(skb); |
38 | rcu_read_unlock(); | ||
37 | return NETDEV_TX_OK; | 39 | return NETDEV_TX_OK; |
38 | } | 40 | } |
39 | #endif | 41 | #endif |
@@ -48,7 +50,6 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) | |||
48 | skb_reset_mac_header(skb); | 50 | skb_reset_mac_header(skb); |
49 | skb_pull(skb, ETH_HLEN); | 51 | skb_pull(skb, ETH_HLEN); |
50 | 52 | ||
51 | rcu_read_lock(); | ||
52 | if (is_broadcast_ether_addr(dest)) | 53 | if (is_broadcast_ether_addr(dest)) |
53 | br_flood_deliver(br, skb); | 54 | br_flood_deliver(br, skb); |
54 | else if (is_multicast_ether_addr(dest)) { | 55 | else if (is_multicast_ether_addr(dest)) { |
@@ -206,24 +207,23 @@ static void br_poll_controller(struct net_device *br_dev) | |||
206 | static void br_netpoll_cleanup(struct net_device *dev) | 207 | static void br_netpoll_cleanup(struct net_device *dev) |
207 | { | 208 | { |
208 | struct net_bridge *br = netdev_priv(dev); | 209 | struct net_bridge *br = netdev_priv(dev); |
209 | struct net_bridge_port *p, *n; | 210 | struct net_bridge_port *p; |
210 | 211 | ||
211 | list_for_each_entry_safe(p, n, &br->port_list, list) { | 212 | list_for_each_entry(p, &br->port_list, list) |
212 | br_netpoll_disable(p); | 213 | br_netpoll_disable(p); |
213 | } | ||
214 | } | 214 | } |
215 | 215 | ||
216 | static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni) | 216 | static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, |
217 | gfp_t gfp) | ||
217 | { | 218 | { |
218 | struct net_bridge *br = netdev_priv(dev); | 219 | struct net_bridge *br = netdev_priv(dev); |
219 | struct net_bridge_port *p, *n; | 220 | struct net_bridge_port *p; |
220 | int err = 0; | 221 | int err = 0; |
221 | 222 | ||
222 | list_for_each_entry_safe(p, n, &br->port_list, list) { | 223 | list_for_each_entry(p, &br->port_list, list) { |
223 | if (!p->dev) | 224 | if (!p->dev) |
224 | continue; | 225 | continue; |
225 | 226 | err = br_netpoll_enable(p, gfp); | |
226 | err = br_netpoll_enable(p); | ||
227 | if (err) | 227 | if (err) |
228 | goto fail; | 228 | goto fail; |
229 | } | 229 | } |
@@ -236,17 +236,17 @@ fail: | |||
236 | goto out; | 236 | goto out; |
237 | } | 237 | } |
238 | 238 | ||
239 | int br_netpoll_enable(struct net_bridge_port *p) | 239 | int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp) |
240 | { | 240 | { |
241 | struct netpoll *np; | 241 | struct netpoll *np; |
242 | int err = 0; | 242 | int err = 0; |
243 | 243 | ||
244 | np = kzalloc(sizeof(*p->np), GFP_KERNEL); | 244 | np = kzalloc(sizeof(*p->np), gfp); |
245 | err = -ENOMEM; | 245 | err = -ENOMEM; |
246 | if (!np) | 246 | if (!np) |
247 | goto out; | 247 | goto out; |
248 | 248 | ||
249 | err = __netpoll_setup(np, p->dev); | 249 | err = __netpoll_setup(np, p->dev, gfp); |
250 | if (err) { | 250 | if (err) { |
251 | kfree(np); | 251 | kfree(np); |
252 | goto out; | 252 | goto out; |
@@ -267,11 +267,7 @@ void br_netpoll_disable(struct net_bridge_port *p) | |||
267 | 267 | ||
268 | p->np = NULL; | 268 | p->np = NULL; |
269 | 269 | ||
270 | /* Wait for transmitting packets to finish before freeing. */ | 270 | __netpoll_free_rcu(np); |
271 | synchronize_rcu_bh(); | ||
272 | |||
273 | __netpoll_cleanup(np); | ||
274 | kfree(np); | ||
275 | } | 271 | } |
276 | 272 | ||
277 | #endif | 273 | #endif |
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index e9466d412707..02015a505d2a 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c | |||
@@ -65,7 +65,7 @@ static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb) | |||
65 | { | 65 | { |
66 | skb->dev = to->dev; | 66 | skb->dev = to->dev; |
67 | 67 | ||
68 | if (unlikely(netpoll_tx_running(to->dev))) { | 68 | if (unlikely(netpoll_tx_running(to->br->dev))) { |
69 | if (packet_length(skb) > skb->dev->mtu && !skb_is_gso(skb)) | 69 | if (packet_length(skb) > skb->dev->mtu && !skb_is_gso(skb)) |
70 | kfree_skb(skb); | 70 | kfree_skb(skb); |
71 | else { | 71 | else { |
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index e1144e1617be..1c8fdc3558cd 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
@@ -361,7 +361,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
361 | if (err) | 361 | if (err) |
362 | goto err2; | 362 | goto err2; |
363 | 363 | ||
364 | if (br_netpoll_info(br) && ((err = br_netpoll_enable(p)))) | 364 | if (br_netpoll_info(br) && ((err = br_netpoll_enable(p, GFP_KERNEL)))) |
365 | goto err3; | 365 | goto err3; |
366 | 366 | ||
367 | err = netdev_set_master(dev, br->dev); | 367 | err = netdev_set_master(dev, br->dev); |
@@ -427,6 +427,10 @@ int br_del_if(struct net_bridge *br, struct net_device *dev) | |||
427 | if (!p || p->br != br) | 427 | if (!p || p->br != br) |
428 | return -EINVAL; | 428 | return -EINVAL; |
429 | 429 | ||
430 | /* Since more than one interface can be attached to a bridge, | ||
431 | * there still maybe an alternate path for netconsole to use; | ||
432 | * therefore there is no reason for a NETDEV_RELEASE event. | ||
433 | */ | ||
430 | del_nbp(p); | 434 | del_nbp(p); |
431 | 435 | ||
432 | spin_lock_bh(&br->lock); | 436 | spin_lock_bh(&br->lock); |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index a768b2408edf..f507d2af9646 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
@@ -316,7 +316,7 @@ static inline void br_netpoll_send_skb(const struct net_bridge_port *p, | |||
316 | netpoll_send_skb(np, skb); | 316 | netpoll_send_skb(np, skb); |
317 | } | 317 | } |
318 | 318 | ||
319 | extern int br_netpoll_enable(struct net_bridge_port *p); | 319 | extern int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp); |
320 | extern void br_netpoll_disable(struct net_bridge_port *p); | 320 | extern void br_netpoll_disable(struct net_bridge_port *p); |
321 | #else | 321 | #else |
322 | static inline struct netpoll_info *br_netpoll_info(struct net_bridge *br) | 322 | static inline struct netpoll_info *br_netpoll_info(struct net_bridge *br) |
@@ -329,7 +329,7 @@ static inline void br_netpoll_send_skb(const struct net_bridge_port *p, | |||
329 | { | 329 | { |
330 | } | 330 | } |
331 | 331 | ||
332 | static inline int br_netpoll_enable(struct net_bridge_port *p) | 332 | static inline int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp) |
333 | { | 333 | { |
334 | return 0; | 334 | return 0; |
335 | } | 335 | } |