net: Call netdev_features_change() from netdev_update_features()
authorMichał Mirosław <mirq-linux@rere.qmqm.pl>
Sun, 3 Apr 2011 05:48:47 +0000 (22:48 -0700)
committerDavid S. Miller <davem@davemloft.net>
Sun, 3 Apr 2011 05:48:47 +0000 (22:48 -0700)
Issue FEAT_CHANGE notification when features are changed by
netdev_update_features().  This will allow changes made by extra constraints
on e.g. MTU change to be properly propagated like changes via ethtool.

Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/netdevice.h
net/core/dev.c
net/core/ethtool.c

index 5eeb2cd3631ce6f627978385608c8d2e52a48ff4..423a5447d2ed6a2cc3058dc5e047efac8efc56f9 100644 (file)
@@ -2550,6 +2550,7 @@ static inline u32 netdev_get_wanted_features(struct net_device *dev)
 }
 u32 netdev_increment_features(u32 all, u32 one, u32 mask);
 u32 netdev_fix_features(struct net_device *dev, u32 features);
+int __netdev_update_features(struct net_device *dev);
 void netdev_update_features(struct net_device *dev);
 
 void netif_stacked_transfer_operstate(const struct net_device *rootdev,
index 3da9fb06d47a658a59ce619f8aaa3d34caaedf26..02f56376fe993910b3317e45e73626b399f0f0ba 100644 (file)
@@ -5236,7 +5236,7 @@ u32 netdev_fix_features(struct net_device *dev, u32 features)
 }
 EXPORT_SYMBOL(netdev_fix_features);
 
-void netdev_update_features(struct net_device *dev)
+int __netdev_update_features(struct net_device *dev)
 {
        u32 features;
        int err = 0;
@@ -5250,7 +5250,7 @@ void netdev_update_features(struct net_device *dev)
        features = netdev_fix_features(dev, features);
 
        if (dev->features == features)
-               return;
+               return 0;
 
        netdev_info(dev, "Features changed: 0x%08x -> 0x%08x\n",
                dev->features, features);
@@ -5258,12 +5258,23 @@ void netdev_update_features(struct net_device *dev)
        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)
+       if (unlikely(err < 0)) {
                netdev_err(dev,
                        "set_features() failed (%d); wanted 0x%08x, left 0x%08x\n",
                        err, features, dev->features);
+               return -1;
+       }
+
+       if (!err)
+               dev->features = features;
+
+       return 1;
+}
+
+void netdev_update_features(struct net_device *dev)
+{
+       if (__netdev_update_features(dev))
+               netdev_features_change(dev);
 }
 EXPORT_SYMBOL(netdev_update_features);
 
@@ -5430,7 +5441,7 @@ int register_netdevice(struct net_device *dev)
                goto err_uninit;
        dev->reg_state = NETREG_REGISTERED;
 
-       netdev_update_features(dev);
+       __netdev_update_features(dev);
 
        /*
         *      Default initial state at registry is that the
index 74ead9eca126cd99121f3bb581e5bb7359c0406e..439e4b0e1312658b402ab33186c2e17a04961c9f 100644 (file)
@@ -317,7 +317,7 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr)
 
        dev->wanted_features &= ~features[0].valid;
        dev->wanted_features |= features[0].valid & features[0].requested;
-       netdev_update_features(dev);
+       __netdev_update_features(dev);
 
        if ((dev->wanted_features ^ dev->features) & features[0].valid)
                ret |= ETHTOOL_F_WISH;
@@ -499,7 +499,7 @@ static int ethtool_set_one_feature(struct net_device *dev,
                else
                        dev->wanted_features &= ~mask;
 
-               netdev_update_features(dev);
+               __netdev_update_features(dev);
                return 0;
        }
 
@@ -551,7 +551,7 @@ int __ethtool_set_flags(struct net_device *dev, u32 data)
        dev->wanted_features =
                (dev->wanted_features & ~changed) | data;
 
-       netdev_update_features(dev);
+       __netdev_update_features(dev);
 
        return 0;
 }