diff options
Diffstat (limited to 'net/bridge/br_if.c')
-rw-r--r-- | net/bridge/br_if.c | 23 |
1 files changed, 13 insertions, 10 deletions
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 4a9f52732655..a2cbe61f6e65 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
@@ -154,7 +154,7 @@ static void del_nbp(struct net_bridge_port *p) | |||
154 | } | 154 | } |
155 | 155 | ||
156 | /* called with RTNL */ | 156 | /* called with RTNL */ |
157 | static void del_br(struct net_bridge *br) | 157 | static void del_br(struct net_bridge *br, struct list_head *head) |
158 | { | 158 | { |
159 | struct net_bridge_port *p, *n; | 159 | struct net_bridge_port *p, *n; |
160 | 160 | ||
@@ -165,7 +165,7 @@ static void del_br(struct net_bridge *br) | |||
165 | del_timer_sync(&br->gc_timer); | 165 | del_timer_sync(&br->gc_timer); |
166 | 166 | ||
167 | br_sysfs_delbr(br->dev); | 167 | br_sysfs_delbr(br->dev); |
168 | unregister_netdevice(br->dev); | 168 | unregister_netdevice_queue(br->dev, head); |
169 | } | 169 | } |
170 | 170 | ||
171 | static struct net_device *new_bridge_dev(struct net *net, const char *name) | 171 | static struct net_device *new_bridge_dev(struct net *net, const char *name) |
@@ -323,7 +323,7 @@ int br_del_bridge(struct net *net, const char *name) | |||
323 | } | 323 | } |
324 | 324 | ||
325 | else | 325 | else |
326 | del_br(netdev_priv(dev)); | 326 | del_br(netdev_priv(dev), NULL); |
327 | 327 | ||
328 | rtnl_unlock(); | 328 | rtnl_unlock(); |
329 | return ret; | 329 | return ret; |
@@ -390,6 +390,10 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
390 | if (dev->br_port != NULL) | 390 | if (dev->br_port != NULL) |
391 | return -EBUSY; | 391 | return -EBUSY; |
392 | 392 | ||
393 | /* No bridging devices that dislike that (e.g. wireless) */ | ||
394 | if (dev->priv_flags & IFF_DONT_BRIDGE) | ||
395 | return -EOPNOTSUPP; | ||
396 | |||
393 | p = new_nbp(br, dev); | 397 | p = new_nbp(br, dev); |
394 | if (IS_ERR(p)) | 398 | if (IS_ERR(p)) |
395 | return PTR_ERR(p); | 399 | return PTR_ERR(p); |
@@ -466,15 +470,14 @@ int br_del_if(struct net_bridge *br, struct net_device *dev) | |||
466 | void br_net_exit(struct net *net) | 470 | void br_net_exit(struct net *net) |
467 | { | 471 | { |
468 | struct net_device *dev; | 472 | struct net_device *dev; |
473 | LIST_HEAD(list); | ||
469 | 474 | ||
470 | rtnl_lock(); | 475 | rtnl_lock(); |
471 | restart: | 476 | for_each_netdev(net, dev) |
472 | for_each_netdev(net, dev) { | 477 | if (dev->priv_flags & IFF_EBRIDGE) |
473 | if (dev->priv_flags & IFF_EBRIDGE) { | 478 | del_br(netdev_priv(dev), &list); |
474 | del_br(netdev_priv(dev)); | 479 | |
475 | goto restart; | 480 | unregister_netdevice_many(&list); |
476 | } | ||
477 | } | ||
478 | rtnl_unlock(); | 481 | rtnl_unlock(); |
479 | 482 | ||
480 | } | 483 | } |