diff options
Diffstat (limited to 'net/bridge/br_if.c')
-rw-r--r-- | net/bridge/br_if.c | 41 |
1 files changed, 17 insertions, 24 deletions
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 59eef42d4a4..fdec773f5b5 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -300,34 +300,22 @@ int br_add_bridge(const char *name) rtnl_lock(); if (strchr(dev->name, '%')) { ret = dev_alloc_name(dev, dev->name); - if (ret < 0) - goto err1; + if (ret < 0) { + free_netdev(dev); + goto out; + } } ret = register_netdevice(dev); if (ret) - goto err2; - - /* network device kobject is not setup until - * after rtnl_unlock does it's hotplug magic. - * so hold reference to avoid race. - */ - dev_hold(dev); - rtnl_unlock(); + goto out; ret = br_sysfs_addbr(dev); - dev_put(dev); - - if (ret) - unregister_netdev(dev); + if (ret) + unregister_netdevice(dev); out: - return ret; - - err2: - free_netdev(dev); - err1: rtnl_unlock(); - goto out; + return ret; } int br_del_bridge(const char *name) @@ -384,12 +372,17 @@ void br_features_recompute(struct net_bridge *br) struct net_bridge_port *p; unsigned long features, checksum; - features = br->feature_mask &~ NETIF_F_IP_CSUM; - checksum = br->feature_mask & NETIF_F_IP_CSUM; + checksum = br->feature_mask & NETIF_F_ALL_CSUM ? NETIF_F_NO_CSUM : 0; + features = br->feature_mask & ~NETIF_F_ALL_CSUM; list_for_each_entry(p, &br->port_list, list) { - if (!(p->dev->features - & (NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM))) + if (checksum & NETIF_F_NO_CSUM && + !(p->dev->features & NETIF_F_NO_CSUM)) + checksum ^= NETIF_F_NO_CSUM | NETIF_F_HW_CSUM; + if (checksum & NETIF_F_HW_CSUM && + !(p->dev->features & NETIF_F_HW_CSUM)) + checksum ^= NETIF_F_HW_CSUM | NETIF_F_IP_CSUM; + if (!(p->dev->features & NETIF_F_IP_CSUM)) checksum = 0; features &= p->dev->features; } |