dev_hold(dev);
        ipgre_tunnel_link(nt);
-       /* Do not decrement MOD_USE_COUNT here. */
        return nt;
 
 failed:
        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);
 
 
        dev_hold(dev);
        ipip_tunnel_link(nt);
-       /* Do not decrement MOD_USE_COUNT here. */
        return nt;
 
 failed:
        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);
 
        dev_hold(dev);
 
        ipip6_tunnel_link(nt);
-       /* Do not decrement MOD_USE_COUNT here. */
        return nt;
 
 failed:
        .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)