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: 0e405443e8
("net/mlx5e: Improve set features ndo resiliency")
Signed-off-by: Gal Pressman <galp@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
This commit is contained in:
parent
4b7d4363f1
commit
75b81ce719
|
@ -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)
|
||||||
#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,
|
||||||
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,
|
||||||
|
|
Loading…
Reference in New Issue