net: Call netdev_features_change() from netdev_update_features()
[pandora-kernel.git] / net / core / ethtool.c
index c1a71bb..439e4b0 100644 (file)
@@ -141,9 +141,24 @@ u32 ethtool_op_get_flags(struct net_device *dev)
 }
 EXPORT_SYMBOL(ethtool_op_get_flags);
 
+/* Check if device can enable (or disable) particular feature coded in "data"
+ * argument. Flags "supported" describe features that can be toggled by device.
+ * If feature can not be toggled, it state (enabled or disabled) must match
+ * hardcoded device features state, otherwise flags are marked as invalid.
+ */
+bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported)
+{
+       u32 features = dev->features & flags_dup_features;
+       /* "data" can contain only flags_dup_features bits,
+        * see __ethtool_set_flags */
+
+       return (features & ~supported) != (data & ~supported);
+}
+EXPORT_SYMBOL(ethtool_invalid_flags);
+
 int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported)
 {
-       if (data & ~supported)
+       if (ethtool_invalid_flags(dev, data, supported))
                return -EINVAL;
 
        dev->features = ((dev->features & ~flags_dup_features) |
@@ -302,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;
@@ -484,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;
        }
 
@@ -513,7 +528,7 @@ static int ethtool_set_one_feature(struct net_device *dev,
        }
 }
 
-static int __ethtool_set_flags(struct net_device *dev, u32 data)
+int __ethtool_set_flags(struct net_device *dev, u32 data)
 {
        u32 changed;
 
@@ -536,7 +551,7 @@ static 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;
 }
@@ -1457,6 +1472,9 @@ static int __ethtool_set_sg(struct net_device *dev, u32 data)
 {
        int err;
 
+       if (!dev->ethtool_ops->set_sg)
+               return -EOPNOTSUPP;
+
        if (data && !(dev->features & NETIF_F_ALL_CSUM))
                return -EINVAL;