Fix "(unregistered net_device): Features changed" message
[deliverable/linux.git] / net / core / dev.c
index a4132766d363397624a1d8386383354e8e5f7cdb..77e5edb724f4b3d8647a801d0821cac7da9d24e8 100644 (file)
@@ -1281,10 +1281,13 @@ static int __dev_close_many(struct list_head *head)
 
 static int __dev_close(struct net_device *dev)
 {
+       int retval;
        LIST_HEAD(single);
 
        list_add(&dev->unreg_list, &single);
-       return __dev_close_many(&single);
+       retval = __dev_close_many(&single);
+       list_del(&single);
+       return retval;
 }
 
 static int dev_close_many(struct list_head *head)
@@ -1326,7 +1329,7 @@ int dev_close(struct net_device *dev)
 
        list_add(&dev->unreg_list, &single);
        dev_close_many(&single);
-
+       list_del(&single);
        return 0;
 }
 EXPORT_SYMBOL(dev_close);
@@ -1648,7 +1651,8 @@ int netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq)
        if (txq < 1 || txq > dev->num_tx_queues)
                return -EINVAL;
 
-       if (dev->reg_state == NETREG_REGISTERED) {
+       if (dev->reg_state == NETREG_REGISTERED ||
+           dev->reg_state == NETREG_UNREGISTERING) {
                ASSERT_RTNL();
 
                rc = netdev_queue_update_kobjects(dev, dev->real_num_tx_queues,
@@ -2606,7 +2610,8 @@ set_rps_cpu(struct net_device *dev, struct sk_buff *skb,
                int rc;
 
                /* Should we steer this flow to a different hardware queue? */
-               if (!skb_rx_queue_recorded(skb) || !dev->rx_cpu_rmap)
+               if (!skb_rx_queue_recorded(skb) || !dev->rx_cpu_rmap ||
+                   !(dev->features & NETIF_F_NTUPLE))
                        goto out;
                rxq_index = cpu_rmap_lookup_index(dev->rx_cpu_rmap, next_cpu);
                if (rxq_index == skb_get_rx_queue(skb))
@@ -5242,6 +5247,7 @@ static void rollback_registered(struct net_device *dev)
 
        list_add(&dev->unreg_list, &single);
        rollback_registered_many(&single);
+       list_del(&single);
 }
 
 u32 netdev_fix_features(struct net_device *dev, u32 features)
@@ -5273,6 +5279,12 @@ u32 netdev_fix_features(struct net_device *dev, u32 features)
                features &= ~NETIF_F_TSO;
        }
 
+       /* 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");
+               features &= ~NETIF_F_GSO;
+       }
+
        /* UFO needs SG and checksumming */
        if (features & NETIF_F_UFO) {
                /* maybe split UFO into V4 and V6? */
@@ -5295,6 +5307,37 @@ u32 netdev_fix_features(struct net_device *dev, u32 features)
 }
 EXPORT_SYMBOL(netdev_fix_features);
 
+void netdev_update_features(struct net_device *dev)
+{
+       u32 features;
+       int err = 0;
+
+       features = netdev_get_wanted_features(dev);
+
+       if (dev->netdev_ops->ndo_fix_features)
+               features = dev->netdev_ops->ndo_fix_features(dev, features);
+
+       /* driver might be less strict about feature dependencies */
+       features = netdev_fix_features(dev, features);
+
+       if (dev->features == features)
+               return;
+
+       netdev_info(dev, "Features changed: 0x%08x -> 0x%08x\n",
+               dev->features, features);
+
+       if (dev->netdev_ops->ndo_set_features)
+               err = dev->netdev_ops->ndo_set_features(dev, features);
+
+       if (!err)
+               dev->features = features;
+       else if (err < 0)
+               netdev_err(dev,
+                       "set_features() failed (%d); wanted 0x%08x, left 0x%08x\n",
+                       err, features, dev->features);
+}
+EXPORT_SYMBOL(netdev_update_features);
+
 /**
  *     netif_stacked_transfer_operstate -      transfer operstate
  *     @rootdev: the root or lower level device to transfer state from
@@ -5429,11 +5472,16 @@ int register_netdevice(struct net_device *dev)
        if (dev->iflink == -1)
                dev->iflink = dev->ifindex;
 
-       dev->features = netdev_fix_features(dev, dev->features);
+       /* Transfer changeable features to wanted_features and enable
+        * software offloads (GSO and GRO).
+        */
+       dev->hw_features |= NETIF_F_SOFT_FEATURES;
+       dev->wanted_features = (dev->features & dev->hw_features)
+               | NETIF_F_SOFT_FEATURES;
 
-       /* Enable software GSO if SG is supported. */
-       if (dev->features & NETIF_F_SG)
-               dev->features |= NETIF_F_GSO;
+       /* Avoid warning from netdev_fix_features() for GSO without SG */
+       if (!(dev->wanted_features & NETIF_F_SG))
+               dev->wanted_features &= ~NETIF_F_GSO;
 
        /* Enable GRO and NETIF_F_HIGHDMA for vlans by default,
         * vlan_dev_init() will do the dev->features check, so these features
@@ -5451,6 +5499,8 @@ int register_netdevice(struct net_device *dev)
                goto err_uninit;
        dev->reg_state = NETREG_REGISTERED;
 
+       netdev_update_features(dev);
+
        /*
         *      Default initial state at registry is that the
         *      device is present.
@@ -6388,6 +6438,7 @@ static void __net_exit default_device_exit_batch(struct list_head *net_list)
                }
        }
        unregister_netdevice_many(&dev_kill_list);
+       list_del(&dev_kill_list);
        rtnl_unlock();
 }
 
This page took 0.027293 seconds and 5 git commands to generate.