diff options
Diffstat (limited to 'net/bridge/br_device.c')
-rw-r--r-- | net/bridge/br_device.c | 30 |
1 files changed, 13 insertions, 17 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 |