macvlan: remove one synchronize_rcu() call
[pandora-kernel.git] / net / core / dev.c
index 3bbb4c2..d945379 100644 (file)
@@ -948,7 +948,7 @@ int dev_alloc_name(struct net_device *dev, const char *name)
 }
 EXPORT_SYMBOL(dev_alloc_name);
 
-static int dev_get_valid_name(struct net_device *dev, const char *name, bool fmt)
+static int dev_get_valid_name(struct net_device *dev, const char *name)
 {
        struct net *net;
 
@@ -958,7 +958,7 @@ static int dev_get_valid_name(struct net_device *dev, const char *name, bool fmt
        if (!dev_valid_name(name))
                return -EINVAL;
 
-       if (fmt && strchr(name, '%'))
+       if (strchr(name, '%'))
                return dev_alloc_name(dev, name);
        else if (__dev_get_by_name(net, name))
                return -EEXIST;
@@ -995,7 +995,7 @@ int dev_change_name(struct net_device *dev, const char *newname)
 
        memcpy(oldname, dev->name, IFNAMSIZ);
 
-       err = dev_get_valid_name(dev, newname, 1);
+       err = dev_get_valid_name(dev, newname);
        if (err < 0)
                return err;
 
@@ -1007,7 +1007,7 @@ rollback:
        }
 
        write_lock_bh(&dev_base_lock);
-       hlist_del(&dev->name_hlist);
+       hlist_del_rcu(&dev->name_hlist);
        write_unlock_bh(&dev_base_lock);
 
        synchronize_rcu();
@@ -1284,11 +1284,13 @@ static int dev_close_many(struct list_head *head)
  */
 int dev_close(struct net_device *dev)
 {
-       LIST_HEAD(single);
+       if (dev->flags & IFF_UP) {
+               LIST_HEAD(single);
 
-       list_add(&dev->unreg_list, &single);
-       dev_close_many(&single);
-       list_del(&single);
+               list_add(&dev->unreg_list, &single);
+               dev_close_many(&single);
+               list_del(&single);
+       }
        return 0;
 }
 EXPORT_SYMBOL(dev_close);
@@ -4495,6 +4497,30 @@ void dev_set_rx_mode(struct net_device *dev)
        netif_addr_unlock_bh(dev);
 }
 
+/**
+ *     dev_ethtool_get_settings - call device's ethtool_ops::get_settings()
+ *     @dev: device
+ *     @cmd: memory area for ethtool_ops::get_settings() result
+ *
+ *      The cmd arg is initialized properly (cleared and
+ *      ethtool_cmd::cmd field set to ETHTOOL_GSET).
+ *
+ *     Return device's ethtool_ops::get_settings() result value or
+ *     -EOPNOTSUPP when device doesn't expose
+ *     ethtool_ops::get_settings() operation.
+ */
+int dev_ethtool_get_settings(struct net_device *dev,
+                            struct ethtool_cmd *cmd)
+{
+       if (!dev->ethtool_ops || !dev->ethtool_ops->get_settings)
+               return -EOPNOTSUPP;
+
+       memset(cmd, 0, sizeof(struct ethtool_cmd));
+       cmd->cmd = ETHTOOL_GSET;
+       return dev->ethtool_ops->get_settings(dev, cmd);
+}
+EXPORT_SYMBOL(dev_ethtool_get_settings);
+
 /**
  *     dev_get_flags - get flags reported to userspace
  *     @dev: device
@@ -4759,7 +4785,7 @@ static int dev_ifsioc_locked(struct net *net, struct ifreq *ifr, unsigned int cm
                 * is never reached
                 */
                WARN_ON(1);
-               err = -EINVAL;
+               err = -ENOTTY;
                break;
 
        }
@@ -5027,7 +5053,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
                /* Set the per device memory buffer space.
                 * Not applicable in our case */
        case SIOCSIFLINK:
-               return -EINVAL;
+               return -ENOTTY;
 
        /*
         *      Unknown or private ioctl.
@@ -5048,7 +5074,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
                /* Take care of Wireless Extensions */
                if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST)
                        return wext_handle_ioctl(net, &ifr, cmd, arg);
-               return -EINVAL;
+               return -ENOTTY;
        }
 }
 
@@ -5100,7 +5126,7 @@ static void rollback_registered_many(struct list_head *head)
                        list_del(&dev->unreg_list);
                        continue;
                }
-
+               dev->dismantle = true;
                BUG_ON(dev->reg_state != NETREG_REGISTERED);
        }
 
@@ -5170,27 +5196,27 @@ u32 netdev_fix_features(struct net_device *dev, u32 features)
        /* Fix illegal checksum combinations */
        if ((features & NETIF_F_HW_CSUM) &&
            (features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) {
-               netdev_info(dev, "mixed HW and IP checksum settings.\n");
+               netdev_warn(dev, "mixed HW and IP checksum settings.\n");
                features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM);
        }
 
        if ((features & NETIF_F_NO_CSUM) &&
            (features & (NETIF_F_HW_CSUM|NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) {
-               netdev_info(dev, "mixed no checksumming and other settings.\n");
+               netdev_warn(dev, "mixed no checksumming and other settings.\n");
                features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM|NETIF_F_HW_CSUM);
        }
 
        /* Fix illegal SG+CSUM combinations. */
        if ((features & NETIF_F_SG) &&
            !(features & NETIF_F_ALL_CSUM)) {
-               netdev_info(dev,
-                           "Dropping NETIF_F_SG since no checksum feature.\n");
+               netdev_dbg(dev,
+                       "Dropping NETIF_F_SG since no checksum feature.\n");
                features &= ~NETIF_F_SG;
        }
 
        /* TSO requires that SG is present as well. */
        if ((features & NETIF_F_ALL_TSO) && !(features & NETIF_F_SG)) {
-               netdev_info(dev, "Dropping TSO features since no SG feature.\n");
+               netdev_dbg(dev, "Dropping TSO features since no SG feature.\n");
                features &= ~NETIF_F_ALL_TSO;
        }
 
@@ -5200,7 +5226,7 @@ u32 netdev_fix_features(struct net_device *dev, u32 features)
 
        /* Software GSO depends on SG. */
        if ((features & NETIF_F_GSO) && !(features & NETIF_F_SG)) {
-               netdev_info(dev, "Dropping NETIF_F_GSO since no SG feature.\n");
+               netdev_dbg(dev, "Dropping NETIF_F_GSO since no SG feature.\n");
                features &= ~NETIF_F_GSO;
        }
 
@@ -5210,13 +5236,13 @@ u32 netdev_fix_features(struct net_device *dev, u32 features)
                if (!((features & NETIF_F_GEN_CSUM) ||
                    (features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))
                            == (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) {
-                       netdev_info(dev,
+                       netdev_dbg(dev,
                                "Dropping NETIF_F_UFO since no checksum offload features.\n");
                        features &= ~NETIF_F_UFO;
                }
 
                if (!(features & NETIF_F_SG)) {
-                       netdev_info(dev,
+                       netdev_dbg(dev,
                                "Dropping NETIF_F_UFO since no NETIF_F_SG feature.\n");
                        features &= ~NETIF_F_UFO;
                }
@@ -5244,7 +5270,7 @@ int __netdev_update_features(struct net_device *dev)
        if (dev->features == features)
                return 0;
 
-       netdev_info(dev, "Features changed: 0x%08x -> 0x%08x\n",
+       netdev_dbg(dev, "Features changed: 0x%08x -> 0x%08x\n",
                dev->features, features);
 
        if (dev->netdev_ops->ndo_set_features)
@@ -5263,6 +5289,14 @@ int __netdev_update_features(struct net_device *dev)
        return 1;
 }
 
+/**
+ *     netdev_update_features - recalculate device features
+ *     @dev: the device to check
+ *
+ *     Recalculate dev->features set and send notifications if it
+ *     has changed. Should be called after driver or hardware dependent
+ *     conditions might have changed that influence the features.
+ */
 void netdev_update_features(struct net_device *dev)
 {
        if (__netdev_update_features(dev))
@@ -5270,6 +5304,23 @@ void netdev_update_features(struct net_device *dev)
 }
 EXPORT_SYMBOL(netdev_update_features);
 
+/**
+ *     netdev_change_features - recalculate device features
+ *     @dev: the device to check
+ *
+ *     Recalculate dev->features set and send notifications even
+ *     if they have not changed. Should be called instead of
+ *     netdev_update_features() if also dev->vlan_features might
+ *     have changed to allow the changes to be propagated to stacked
+ *     VLAN devices.
+ */
+void netdev_change_features(struct net_device *dev)
+{
+       __netdev_update_features(dev);
+       netdev_features_change(dev);
+}
+EXPORT_SYMBOL(netdev_change_features);
+
 /**
  *     netif_stacked_transfer_operstate -      transfer operstate
  *     @rootdev: the root or lower level device to transfer state from
@@ -5386,6 +5437,10 @@ int register_netdevice(struct net_device *dev)
 
        dev->iflink = -1;
 
+       ret = dev_get_valid_name(dev, dev->name);
+       if (ret < 0)
+               goto out;
+
        /* Init, if this function is available */
        if (dev->netdev_ops->ndo_init) {
                ret = dev->netdev_ops->ndo_init(dev);
@@ -5396,10 +5451,6 @@ int register_netdevice(struct net_device *dev)
                }
        }
 
-       ret = dev_get_valid_name(dev, dev->name, 0);
-       if (ret)
-               goto err_uninit;
-
        dev->ifindex = dev_new_index(net);
        if (dev->iflink == -1)
                dev->iflink = dev->ifindex;
@@ -5411,12 +5462,6 @@ int register_netdevice(struct net_device *dev)
        dev->features |= NETIF_F_SOFT_FEATURES;
        dev->wanted_features = dev->features & dev->hw_features;
 
-       /* Avoid warning from netdev_fix_features() for GSO without SG */
-       if (!(dev->wanted_features & NETIF_F_SG)) {
-               dev->wanted_features &= ~NETIF_F_GSO;
-               dev->features &= ~NETIF_F_GSO;
-       }
-
        /* Turn on no cache copy if HW is doing checksum */
        dev->hw_features |= NETIF_F_NOCACHE_COPY;
        if ((dev->features & NETIF_F_ALL_CSUM) &&
@@ -5538,19 +5583,7 @@ int register_netdev(struct net_device *dev)
        int err;
 
        rtnl_lock();
-
-       /*
-        * If the name is a format string the caller wants us to do a
-        * name allocation.
-        */
-       if (strchr(dev->name, '%')) {
-               err = dev_alloc_name(dev, dev->name);
-               if (err < 0)
-                       goto out;
-       }
-
        err = register_netdevice(dev);
-out:
        rtnl_unlock();
        return err;
 }
@@ -6032,7 +6065,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
                /* We get here if we can't use the current device name */
                if (!pat)
                        goto out;
-               if (dev_get_valid_name(dev, pat, 1))
+               if (dev_get_valid_name(dev, pat) < 0)
                        goto out;
        }
 
@@ -6164,33 +6197,20 @@ static int dev_cpu_callback(struct notifier_block *nfb,
  */
 u32 netdev_increment_features(u32 all, u32 one, u32 mask)
 {
-       /* If device needs checksumming, downgrade to it. */
-       if (all & NETIF_F_NO_CSUM && !(one & NETIF_F_NO_CSUM))
-               all ^= NETIF_F_NO_CSUM | (one & NETIF_F_ALL_CSUM);
-       else if (mask & NETIF_F_ALL_CSUM) {
-               /* If one device supports v4/v6 checksumming, set for all. */
-               if (one & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM) &&
-                   !(all & NETIF_F_GEN_CSUM)) {
-                       all &= ~NETIF_F_ALL_CSUM;
-                       all |= one & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
-               }
-
-               /* If one device supports hw checksumming, set for all. */
-               if (one & NETIF_F_GEN_CSUM && !(all & NETIF_F_GEN_CSUM)) {
-                       all &= ~NETIF_F_ALL_CSUM;
-                       all |= NETIF_F_HW_CSUM;
-               }
-       }
+       if (mask & NETIF_F_GEN_CSUM)
+               mask |= NETIF_F_ALL_CSUM;
+       mask |= NETIF_F_VLAN_CHALLENGED;
 
-       /* If device can't no cache copy, don't do for all */
-       if (!(one & NETIF_F_NOCACHE_COPY))
-               all &= ~NETIF_F_NOCACHE_COPY;
+       all |= one & (NETIF_F_ONE_FOR_ALL|NETIF_F_ALL_CSUM) & mask;
+       all &= one | ~NETIF_F_ALL_FOR_ALL;
 
-       one |= NETIF_F_ALL_CSUM;
+       /* If device needs checksumming, downgrade to it. */
+       if (all & (NETIF_F_ALL_CSUM & ~NETIF_F_NO_CSUM))
+               all &= ~NETIF_F_NO_CSUM;
 
-       one |= all & NETIF_F_ONE_FOR_ALL;
-       all &= one | NETIF_F_LLTX | NETIF_F_GSO | NETIF_F_UFO;
-       all |= one & mask & NETIF_F_ONE_FOR_ALL;
+       /* If one device supports hw checksumming, set for all. */
+       if (all & NETIF_F_GEN_CSUM)
+               all &= ~(NETIF_F_ALL_CSUM & ~NETIF_F_GEN_CSUM);
 
        return all;
 }