Merge tag 'powerpc-5.9-3' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc...
[linux-2.6-microblaze.git] / net / ethtool / features.c
index 4e632dc..495635f 100644 (file)
@@ -224,7 +224,9 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info)
        DECLARE_BITMAP(wanted_diff_mask, NETDEV_FEATURE_COUNT);
        DECLARE_BITMAP(active_diff_mask, NETDEV_FEATURE_COUNT);
        DECLARE_BITMAP(old_active, NETDEV_FEATURE_COUNT);
+       DECLARE_BITMAP(old_wanted, NETDEV_FEATURE_COUNT);
        DECLARE_BITMAP(new_active, NETDEV_FEATURE_COUNT);
+       DECLARE_BITMAP(new_wanted, NETDEV_FEATURE_COUNT);
        DECLARE_BITMAP(req_wanted, NETDEV_FEATURE_COUNT);
        DECLARE_BITMAP(req_mask, NETDEV_FEATURE_COUNT);
        struct nlattr *tb[ETHTOOL_A_FEATURES_MAX + 1];
@@ -250,6 +252,7 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info)
 
        rtnl_lock();
        ethnl_features_to_bitmap(old_active, dev->features);
+       ethnl_features_to_bitmap(old_wanted, dev->wanted_features);
        ret = ethnl_parse_bitset(req_wanted, req_mask, NETDEV_FEATURE_COUNT,
                                 tb[ETHTOOL_A_FEATURES_WANTED],
                                 netdev_features_strings, info->extack);
@@ -261,17 +264,15 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info)
                goto out_rtnl;
        }
 
-       /* set req_wanted bits not in req_mask from old_active */
+       /* set req_wanted bits not in req_mask from old_wanted */
        bitmap_and(req_wanted, req_wanted, req_mask, NETDEV_FEATURE_COUNT);
-       bitmap_andnot(new_active, old_active, req_mask, NETDEV_FEATURE_COUNT);
-       bitmap_or(req_wanted, new_active, req_wanted, NETDEV_FEATURE_COUNT);
-       if (bitmap_equal(req_wanted, old_active, NETDEV_FEATURE_COUNT)) {
-               ret = 0;
-               goto out_rtnl;
+       bitmap_andnot(new_wanted, old_wanted, req_mask, NETDEV_FEATURE_COUNT);
+       bitmap_or(req_wanted, new_wanted, req_wanted, NETDEV_FEATURE_COUNT);
+       if (!bitmap_equal(req_wanted, old_wanted, NETDEV_FEATURE_COUNT)) {
+               dev->wanted_features &= ~dev->hw_features;
+               dev->wanted_features |= ethnl_bitmap_to_features(req_wanted) & dev->hw_features;
+               __netdev_update_features(dev);
        }
-
-       dev->wanted_features = ethnl_bitmap_to_features(req_wanted);
-       __netdev_update_features(dev);
        ethnl_features_to_bitmap(new_active, dev->features);
        mod = !bitmap_equal(old_active, new_active, NETDEV_FEATURE_COUNT);