Commit 75b81ce7 authored by Gal Pressman's avatar Gal Pressman Committed by Saeed Mahameed

net/mlx5e: Don't override netdev features field unless in error flow

Set features function sets dev->features in order to keep track of which
features were successfully changed and which weren't (in case the user
asks for more than one change in a single command).

This breaks the logic in __netdev_update_features which assumes that
dev->features is not changed on success and checks for diffs between
features and dev->features (diffs that might not exist at this point
because of the driver override).

The solution is to keep track of successful/failed feature changes and
assign them to dev->features in case of failure only.

Fixes: 0e405443 ("net/mlx5e: Improve set features ndo resiliency")
Signed-off-by: default avatarGal Pressman <galp@mellanox.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@mellanox.com>
parent 4b7d4363
...@@ -3219,12 +3219,12 @@ static int mlx5e_set_mac(struct net_device *netdev, void *addr) ...@@ -3219,12 +3219,12 @@ static int mlx5e_set_mac(struct net_device *netdev, void *addr)
return 0; return 0;
} }
#define MLX5E_SET_FEATURE(netdev, feature, enable) \ #define MLX5E_SET_FEATURE(features, feature, enable) \
do { \ do { \
if (enable) \ if (enable) \
netdev->features |= feature; \ *features |= feature; \
else \ else \
netdev->features &= ~feature; \ *features &= ~feature; \
} while (0) } while (0)
typedef int (*mlx5e_feature_handler)(struct net_device *netdev, bool enable); typedef int (*mlx5e_feature_handler)(struct net_device *netdev, bool enable);
...@@ -3347,6 +3347,7 @@ static int set_feature_arfs(struct net_device *netdev, bool enable) ...@@ -3347,6 +3347,7 @@ static int set_feature_arfs(struct net_device *netdev, bool enable)
#endif #endif
static int mlx5e_handle_feature(struct net_device *netdev, static int mlx5e_handle_feature(struct net_device *netdev,
netdev_features_t *features,
netdev_features_t wanted_features, netdev_features_t wanted_features,
netdev_features_t feature, netdev_features_t feature,
mlx5e_feature_handler feature_handler) mlx5e_feature_handler feature_handler)
...@@ -3365,34 +3366,40 @@ static int mlx5e_handle_feature(struct net_device *netdev, ...@@ -3365,34 +3366,40 @@ static int mlx5e_handle_feature(struct net_device *netdev,
return err; return err;
} }
MLX5E_SET_FEATURE(netdev, feature, enable); MLX5E_SET_FEATURE(features, feature, enable);
return 0; return 0;
} }
static int mlx5e_set_features(struct net_device *netdev, static int mlx5e_set_features(struct net_device *netdev,
netdev_features_t features) netdev_features_t features)
{ {
netdev_features_t oper_features = netdev->features;
int err; int err;
err = mlx5e_handle_feature(netdev, features, NETIF_F_LRO, err = mlx5e_handle_feature(netdev, &oper_features, features,
set_feature_lro); NETIF_F_LRO, set_feature_lro);
err |= mlx5e_handle_feature(netdev, features, err |= mlx5e_handle_feature(netdev, &oper_features, features,
NETIF_F_HW_VLAN_CTAG_FILTER, NETIF_F_HW_VLAN_CTAG_FILTER,
set_feature_cvlan_filter); set_feature_cvlan_filter);
err |= mlx5e_handle_feature(netdev, features, NETIF_F_HW_TC, err |= mlx5e_handle_feature(netdev, &oper_features, features,
set_feature_tc_num_filters); NETIF_F_HW_TC, set_feature_tc_num_filters);
err |= mlx5e_handle_feature(netdev, features, NETIF_F_RXALL, err |= mlx5e_handle_feature(netdev, &oper_features, features,
set_feature_rx_all); NETIF_F_RXALL, set_feature_rx_all);
err |= mlx5e_handle_feature(netdev, features, NETIF_F_RXFCS, err |= mlx5e_handle_feature(netdev, &oper_features, features,
set_feature_rx_fcs); NETIF_F_RXFCS, set_feature_rx_fcs);
err |= mlx5e_handle_feature(netdev, features, NETIF_F_HW_VLAN_CTAG_RX, err |= mlx5e_handle_feature(netdev, &oper_features, features,
set_feature_rx_vlan); NETIF_F_HW_VLAN_CTAG_RX, set_feature_rx_vlan);
#ifdef CONFIG_RFS_ACCEL #ifdef CONFIG_RFS_ACCEL
err |= mlx5e_handle_feature(netdev, features, NETIF_F_NTUPLE, err |= mlx5e_handle_feature(netdev, &oper_features, features,
set_feature_arfs); NETIF_F_NTUPLE, set_feature_arfs);
#endif #endif
return err ? -EINVAL : 0; if (err) {
netdev->features = oper_features;
return -EINVAL;
}
return 0;
} }
static netdev_features_t mlx5e_fix_features(struct net_device *netdev, static netdev_features_t mlx5e_fix_features(struct net_device *netdev,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment