diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 884835522224..f0d5740d7e22 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -290,7 +290,6 @@ static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int
 
 	dev_hold(dev);
 	ipgre_tunnel_link(nt);
-	/* Do not decrement MOD_USE_COUNT here. */
 	return nt;
 
 failed:
@@ -1277,12 +1276,28 @@ static int __init ipgre_init(void)
 	goto out;
 }
 
-static void ipgre_fini(void)
+static void __exit ipgre_destroy_tunnels(void)
+{
+	int prio;
+
+	for (prio = 0; prio < 4; prio++) {
+		int h;
+		for (h = 0; h < HASH_SIZE; h++) {
+			struct ip_tunnel *t;
+			while ((t = tunnels[prio][h]) != NULL)
+				unregister_netdevice(t->dev);
+		}
+	}
+}
+
+static void __exit ipgre_fini(void)
 {
 	if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0)
 		printk(KERN_INFO "ipgre close: can't remove protocol\n");
 
-	unregister_netdev(ipgre_fb_tunnel_dev);
+	rtnl_lock();
+	ipgre_destroy_tunnels();
+	rtnl_unlock();
 }
 
 module_init(ipgre_init);
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index c3947cd566b7..c05c1df0bb04 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -255,7 +255,6 @@ static struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int c
 
 	dev_hold(dev);
 	ipip_tunnel_link(nt);
-	/* Do not decrement MOD_USE_COUNT here. */
 	return nt;
 
 failed:
@@ -920,12 +919,29 @@ static int __init ipip_init(void)
 	goto out;
 }
 
+static void __exit ipip_destroy_tunnels(void)
+{
+	int prio;
+
+	for (prio = 1; prio < 4; prio++) {
+		int h;
+		for (h = 0; h < HASH_SIZE; h++) {
+			struct ip_tunnel *t;
+			while ((t = tunnels[prio][h]) != NULL)
+				unregister_netdevice(t->dev);
+		}
+	}
+}
+
 static void __exit ipip_fini(void)
 {
 	if (ipip_unregister() < 0)
 		printk(KERN_INFO "ipip close: can't deregister tunnel\n");
 
-	unregister_netdev(ipip_fb_tunnel_dev);
+	rtnl_lock();
+	ipip_destroy_tunnels();
+	unregister_netdevice(ipip_fb_tunnel_dev);
+	rtnl_unlock();
 }
 
 module_init(ipip_init);
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index b788f55e139b..e553e5b80d6e 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -195,7 +195,6 @@ static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int
 	dev_hold(dev);
 
 	ipip6_tunnel_link(nt);
-	/* Do not decrement MOD_USE_COUNT here. */
 	return nt;
 
 failed:
@@ -794,10 +793,28 @@ static struct net_protocol sit_protocol = {
 	.err_handler	=	ipip6_err,
 };
 
+static void __exit sit_destroy_tunnels(void)
+{
+	int prio;
+
+	for (prio = 1; prio < 4; prio++) {
+		int h;
+		for (h = 0; h < HASH_SIZE; h++) {
+			struct ip_tunnel *t;
+			while ((t = tunnels[prio][h]) != NULL)
+				unregister_netdevice(t->dev);
+		}
+	}
+}
+
 void __exit sit_cleanup(void)
 {
 	inet_del_protocol(&sit_protocol, IPPROTO_IPV6);
-	unregister_netdev(ipip6_fb_tunnel_dev);
+
+	rtnl_lock();
+	sit_destroy_tunnels();
+	unregister_netdevice(ipip6_fb_tunnel_dev);
+	rtnl_unlock();
 }
 
 int __init sit_init(void)