Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
[platform/kernel/linux-rpi.git] / net / ipv6 / ip6_tunnel.c
index 3fa0eca..288bafd 100644 (file)
@@ -266,7 +266,6 @@ static int ip6_tnl_create2(struct net_device *dev)
 
        strcpy(t->parms.name, dev->name);
 
-       dev_hold(dev);
        ip6_tnl_link(ip6n, t);
        return 0;
 
@@ -388,7 +387,7 @@ ip6_tnl_dev_uninit(struct net_device *dev)
 }
 
 /**
- * parse_tvl_tnl_enc_lim - handle encapsulation limit option
+ * ip6_tnl_parse_tlv_enc_lim - handle encapsulation limit option
  *   @skb: received socket buffer
  *   @raw: the ICMPv6 error message data
  *
@@ -1882,6 +1881,7 @@ ip6_tnl_dev_init_gen(struct net_device *dev)
        dev->min_mtu = ETH_MIN_MTU;
        dev->max_mtu = IP6_MAX_MTU - dev->hard_header_len;
 
+       dev_hold(dev);
        return 0;
 
 destroy_dst:
@@ -1925,7 +1925,6 @@ static int __net_init ip6_fb_tnl_dev_init(struct net_device *dev)
        struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
 
        t->parms.proto = IPPROTO_IPV6;
-       dev_hold(dev);
 
        rcu_assign_pointer(ip6n->tnls_wc[0], t);
        return 0;
@@ -2244,6 +2243,16 @@ static void __net_exit ip6_tnl_destroy_tunnels(struct net *net, struct list_head
                        t = rtnl_dereference(t->next);
                }
        }
+
+       t = rtnl_dereference(ip6n->tnls_wc[0]);
+       while (t) {
+               /* If dev is in the same netns, it has already
+                * been added to the list by the previous loop.
+                */
+               if (!net_eq(dev_net(t->dev), net))
+                       unregister_netdevice_queue(t->dev, list);
+               t = rtnl_dereference(t->next);
+       }
 }
 
 static int __net_init ip6_tnl_init_net(struct net *net)