aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge/br_if.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/bridge/br_if.c')
-rw-r--r--net/bridge/br_if.c23
1 files changed, 16 insertions, 7 deletions
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 1bacca4cb67..1d420f64ff2 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -161,9 +161,10 @@ static void del_nbp(struct net_bridge_port *p)
161 call_rcu(&p->rcu, destroy_nbp_rcu); 161 call_rcu(&p->rcu, destroy_nbp_rcu);
162} 162}
163 163
164/* called with RTNL */ 164/* Delete bridge device */
165static void del_br(struct net_bridge *br, struct list_head *head) 165void br_dev_delete(struct net_device *dev, struct list_head *head)
166{ 166{
167 struct net_bridge *br = netdev_priv(dev);
167 struct net_bridge_port *p, *n; 168 struct net_bridge_port *p, *n;
168 169
169 list_for_each_entry_safe(p, n, &br->port_list, list) { 170 list_for_each_entry_safe(p, n, &br->port_list, list) {
@@ -231,6 +232,7 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br,
231int br_add_bridge(struct net *net, const char *name) 232int br_add_bridge(struct net *net, const char *name)
232{ 233{
233 struct net_device *dev; 234 struct net_device *dev;
235 int res;
234 236
235 dev = alloc_netdev(sizeof(struct net_bridge), name, 237 dev = alloc_netdev(sizeof(struct net_bridge), name,
236 br_dev_setup); 238 br_dev_setup);
@@ -240,7 +242,10 @@ int br_add_bridge(struct net *net, const char *name)
240 242
241 dev_net_set(dev, net); 243 dev_net_set(dev, net);
242 244
243 return register_netdev(dev); 245 res = register_netdev(dev);
246 if (res)
247 free_netdev(dev);
248 return res;
244} 249}
245 250
246int br_del_bridge(struct net *net, const char *name) 251int br_del_bridge(struct net *net, const char *name)
@@ -264,7 +269,7 @@ int br_del_bridge(struct net *net, const char *name)
264 } 269 }
265 270
266 else 271 else
267 del_br(netdev_priv(dev), NULL); 272 br_dev_delete(dev, NULL);
268 273
269 rtnl_unlock(); 274 rtnl_unlock();
270 return ret; 275 return ret;
@@ -388,7 +393,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
388 br_ifinfo_notify(RTM_NEWLINK, p); 393 br_ifinfo_notify(RTM_NEWLINK, p);
389 394
390 if (changed_addr) 395 if (changed_addr)
391 call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); 396 call_netdevice_notifiers(NETDEV_CHANGEADDR, br->dev);
392 397
393 dev_set_mtu(br->dev, br_min_mtu(br)); 398 dev_set_mtu(br->dev, br_min_mtu(br));
394 399
@@ -417,6 +422,7 @@ put_back:
417int br_del_if(struct net_bridge *br, struct net_device *dev) 422int br_del_if(struct net_bridge *br, struct net_device *dev)
418{ 423{
419 struct net_bridge_port *p; 424 struct net_bridge_port *p;
425 bool changed_addr;
420 426
421 p = br_port_get_rtnl(dev); 427 p = br_port_get_rtnl(dev);
422 if (!p || p->br != br) 428 if (!p || p->br != br)
@@ -425,9 +431,12 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)
425 del_nbp(p); 431 del_nbp(p);
426 432
427 spin_lock_bh(&br->lock); 433 spin_lock_bh(&br->lock);
428 br_stp_recalculate_bridge_id(br); 434 changed_addr = br_stp_recalculate_bridge_id(br);
429 spin_unlock_bh(&br->lock); 435 spin_unlock_bh(&br->lock);
430 436
437 if (changed_addr)
438 call_netdevice_notifiers(NETDEV_CHANGEADDR, br->dev);
439
431 netdev_update_features(br->dev); 440 netdev_update_features(br->dev);
432 441
433 return 0; 442 return 0;
@@ -441,7 +450,7 @@ void __net_exit br_net_exit(struct net *net)
441 rtnl_lock(); 450 rtnl_lock();
442 for_each_netdev(net, dev) 451 for_each_netdev(net, dev)
443 if (dev->priv_flags & IFF_EBRIDGE) 452 if (dev->priv_flags & IFF_EBRIDGE)
444 del_br(netdev_priv(dev), &list); 453 br_dev_delete(dev, &list);
445 454
446 unregister_netdevice_many(&list); 455 unregister_netdevice_many(&list);
447 rtnl_unlock(); 456 rtnl_unlock();