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 0d142ed0bbe3..c03d2c3ff03e 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
@@ -147,8 +147,9 @@ static void del_nbp(struct net_bridge_port *p) | |||
147 | 147 | ||
148 | list_del_rcu(&p->list); | 148 | list_del_rcu(&p->list); |
149 | 149 | ||
150 | dev->priv_flags &= ~IFF_BRIDGE_PORT; | ||
151 | |||
150 | netdev_rx_handler_unregister(dev); | 152 | netdev_rx_handler_unregister(dev); |
151 | rcu_assign_pointer(dev->br_port, NULL); | ||
152 | 153 | ||
153 | br_multicast_del_port(p); | 154 | br_multicast_del_port(p); |
154 | 155 | ||
@@ -400,7 +401,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
400 | return -ELOOP; | 401 | return -ELOOP; |
401 | 402 | ||
402 | /* Device is already being bridged */ | 403 | /* Device is already being bridged */ |
403 | if (dev->br_port != NULL) | 404 | if (br_port_exists(dev)) |
404 | return -EBUSY; | 405 | return -EBUSY; |
405 | 406 | ||
406 | /* No bridging devices that dislike that (e.g. wireless) */ | 407 | /* No bridging devices that dislike that (e.g. wireless) */ |
@@ -431,11 +432,11 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
431 | if (br_netpoll_info(br) && ((err = br_netpoll_enable(p)))) | 432 | if (br_netpoll_info(br) && ((err = br_netpoll_enable(p)))) |
432 | goto err3; | 433 | goto err3; |
433 | 434 | ||
434 | rcu_assign_pointer(dev->br_port, p); | 435 | err = netdev_rx_handler_register(dev, br_handle_frame, p); |
435 | |||
436 | err = netdev_rx_handler_register(dev, br_handle_frame, NULL); | ||
437 | if (err) | 436 | if (err) |
438 | goto err4; | 437 | goto err3; |
438 | |||
439 | dev->priv_flags |= IFF_BRIDGE_PORT; | ||
439 | 440 | ||
440 | dev_disable_lro(dev); | 441 | dev_disable_lro(dev); |
441 | 442 | ||
@@ -457,8 +458,6 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
457 | kobject_uevent(&p->kobj, KOBJ_ADD); | 458 | kobject_uevent(&p->kobj, KOBJ_ADD); |
458 | 459 | ||
459 | return 0; | 460 | return 0; |
460 | err4: | ||
461 | rcu_assign_pointer(dev->br_port, NULL); | ||
462 | err3: | 461 | err3: |
463 | sysfs_remove_link(br->ifobj, p->dev->name); | 462 | sysfs_remove_link(br->ifobj, p->dev->name); |
464 | err2: | 463 | err2: |
@@ -477,9 +476,13 @@ put_back: | |||
477 | /* called with RTNL */ | 476 | /* called with RTNL */ |
478 | int br_del_if(struct net_bridge *br, struct net_device *dev) | 477 | int br_del_if(struct net_bridge *br, struct net_device *dev) |
479 | { | 478 | { |
480 | struct net_bridge_port *p = dev->br_port; | 479 | struct net_bridge_port *p; |
480 | |||
481 | if (!br_port_exists(dev)) | ||
482 | return -EINVAL; | ||
481 | 483 | ||
482 | if (!p || p->br != br) | 484 | p = br_port_get(dev); |
485 | if (p->br != br) | ||
483 | return -EINVAL; | 486 | return -EINVAL; |
484 | 487 | ||
485 | del_nbp(p); | 488 | del_nbp(p); |