static void init_loopback(struct net_device *dev)
 {
        struct inet6_dev  *idev;
-       struct net_device *sp_dev;
-       struct inet6_ifaddr *sp_ifa;
-       struct rt6_info *sp_rt;
 
        /* ::1 */
 
        }
 
        add_addr(idev, &in6addr_loopback, 128, IFA_HOST);
-
-       /* Add routes to other interface's IPv6 addresses */
-       for_each_netdev(dev_net(dev), sp_dev) {
-               if (!strcmp(sp_dev->name, dev->name))
-                       continue;
-
-               idev = __in6_dev_get(sp_dev);
-               if (!idev)
-                       continue;
-
-               read_lock_bh(&idev->lock);
-               list_for_each_entry(sp_ifa, &idev->addr_list, if_list) {
-
-                       if (sp_ifa->flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE))
-                               continue;
-
-                       if (sp_ifa->rt) {
-                               /* This dst has been added to garbage list when
-                                * lo device down, release this obsolete dst and
-                                * reallocate a new router for ifa.
-                                */
-                               if (!sp_ifa->rt->rt6i_node) {
-                                       ip6_rt_put(sp_ifa->rt);
-                                       sp_ifa->rt = NULL;
-                               } else {
-                                       continue;
-                               }
-                       }
-
-                       sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, false);
-
-                       /* Failure cases are ignored */
-                       if (!IS_ERR(sp_rt)) {
-                               sp_ifa->rt = sp_rt;
-                               ip6_ins_rt(sp_rt);
-                       }
-               }
-               read_unlock_bh(&idev->lock);
-       }
 }
 
 void addrconf_add_linklocal(struct inet6_dev *idev,
 
        return __ip6_ins_rt(rt, &info, &mxc, NULL);
 }
 
+/* called with rcu_lock held */
+static struct net_device *ip6_rt_get_dev_rcu(struct rt6_info *rt)
+{
+       struct net_device *dev = rt->dst.dev;
+
+       if (rt->rt6i_flags & RTF_LOCAL) {
+               /* for copies of local routes, dst->dev needs to be the
+                * device if it is a master device, the master device if
+                * device is enslaved, and the loopback as the default
+                */
+               if (netif_is_l3_slave(dev) &&
+                   !rt6_need_strict(&rt->rt6i_dst.addr))
+                       dev = l3mdev_master_dev_rcu(dev);
+               else if (!netif_is_l3_master(dev))
+                       dev = dev_net(dev)->loopback_dev;
+               /* last case is netif_is_l3_master(dev) is true in which
+                * case we want dev returned to be dev
+                */
+       }
+
+       return dev;
+}
+
 static struct rt6_info *ip6_rt_cache_alloc(struct rt6_info *ort,
                                           const struct in6_addr *daddr,
                                           const struct in6_addr *saddr)
 {
+       struct net_device *dev;
        struct rt6_info *rt;
 
        /*
        if (ort->rt6i_flags & (RTF_CACHE | RTF_PCPU))
                ort = (struct rt6_info *)ort->dst.from;
 
-       rt = __ip6_dst_alloc(dev_net(ort->dst.dev), ort->dst.dev, 0);
-
+       rcu_read_lock();
+       dev = ip6_rt_get_dev_rcu(ort);
+       rt = __ip6_dst_alloc(dev_net(dev), dev, 0);
+       rcu_read_unlock();
        if (!rt)
                return NULL;
 
 
 static struct rt6_info *ip6_rt_pcpu_alloc(struct rt6_info *rt)
 {
+       struct net_device *dev;
        struct rt6_info *pcpu_rt;
 
-       pcpu_rt = __ip6_dst_alloc(dev_net(rt->dst.dev),
-                                 rt->dst.dev, rt->dst.flags);
-
+       rcu_read_lock();
+       dev = ip6_rt_get_dev_rcu(rt);
+       pcpu_rt = __ip6_dst_alloc(dev_net(dev), dev, rt->dst.flags);
+       rcu_read_unlock();
        if (!pcpu_rt)
                return NULL;
        ip6_rt_copy_init(pcpu_rt, rt);
 {
        u32 tb_id;
        struct net *net = dev_net(idev->dev);
-       struct net_device *dev = net->loopback_dev;
+       struct net_device *dev = idev->dev;
        struct rt6_info *rt;
 
-       /* use L3 Master device as loopback for host routes if device
-        * is enslaved and address is not link local or multicast
-        */
-       if (!rt6_need_strict(addr))
-               dev = l3mdev_master_dev_rcu(idev->dev) ? : dev;
-
        rt = ip6_dst_alloc(net, dev, DST_NOCOUNT);
        if (!rt)
                return ERR_PTR(-ENOMEM);