aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGal Pressman <galp@mellanox.com>2018-01-10 10:11:11 -0500
committerSaeed Mahameed <saeedm@mellanox.com>2018-01-11 19:01:49 -0500
commit75b81ce719b79565eb0b39aa9954b6e11a5e73bf (patch)
tree90bb66dcc4e5990e7afebc5c11573ccf62e9a381
parent4b7d4363f14a0398eca48c7e96e46120c5eb6a96 (diff)
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: 0e405443e803 ("net/mlx5e: Improve set features ndo resiliency") Signed-off-by: Gal Pressman <galp@mellanox.com> Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_main.c43
1 files changed, 25 insertions, 18 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index d9d8227f195f..311d5ec8407c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -3219,12 +3219,12 @@ static int mlx5e_set_mac(struct net_device *netdev, void *addr)
3219 return 0; 3219 return 0;
3220} 3220}
3221 3221
3222#define MLX5E_SET_FEATURE(netdev, feature, enable) \ 3222#define MLX5E_SET_FEATURE(features, feature, enable) \
3223 do { \ 3223 do { \
3224 if (enable) \ 3224 if (enable) \
3225 netdev->features |= feature; \ 3225 *features |= feature; \
3226 else \ 3226 else \
3227 netdev->features &= ~feature; \ 3227 *features &= ~feature; \
3228 } while (0) 3228 } while (0)
3229 3229
3230typedef int (*mlx5e_feature_handler)(struct net_device *netdev, bool enable); 3230typedef 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#endif 3347#endif
3348 3348
3349static int mlx5e_handle_feature(struct net_device *netdev, 3349static int mlx5e_handle_feature(struct net_device *netdev,
3350 netdev_features_t *features,
3350 netdev_features_t wanted_features, 3351 netdev_features_t wanted_features,
3351 netdev_features_t feature, 3352 netdev_features_t feature,
3352 mlx5e_feature_handler feature_handler) 3353 mlx5e_feature_handler feature_handler)
@@ -3365,34 +3366,40 @@ static int mlx5e_handle_feature(struct net_device *netdev,
3365 return err; 3366 return err;
3366 } 3367 }
3367 3368
3368 MLX5E_SET_FEATURE(netdev, feature, enable); 3369 MLX5E_SET_FEATURE(features, feature, enable);
3369 return 0; 3370 return 0;
3370} 3371}
3371 3372
3372static int mlx5e_set_features(struct net_device *netdev, 3373static int mlx5e_set_features(struct net_device *netdev,
3373 netdev_features_t features) 3374 netdev_features_t features)
3374{ 3375{
3376 netdev_features_t oper_features = netdev->features;
3375 int err; 3377 int err;
3376 3378
3377 err = mlx5e_handle_feature(netdev, features, NETIF_F_LRO, 3379 err = mlx5e_handle_feature(netdev, &oper_features, features,
3378 set_feature_lro); 3380 NETIF_F_LRO, set_feature_lro);
3379 err |= mlx5e_handle_feature(netdev, features, 3381 err |= mlx5e_handle_feature(netdev, &oper_features, features,
3380 NETIF_F_HW_VLAN_CTAG_FILTER, 3382 NETIF_F_HW_VLAN_CTAG_FILTER,
3381 set_feature_cvlan_filter); 3383 set_feature_cvlan_filter);
3382 err |= mlx5e_handle_feature(netdev, features, NETIF_F_HW_TC, 3384 err |= mlx5e_handle_feature(netdev, &oper_features, features,
3383 set_feature_tc_num_filters); 3385 NETIF_F_HW_TC, set_feature_tc_num_filters);
3384 err |= mlx5e_handle_feature(netdev, features, NETIF_F_RXALL, 3386 err |= mlx5e_handle_feature(netdev, &oper_features, features,
3385 set_feature_rx_all); 3387 NETIF_F_RXALL, set_feature_rx_all);
3386 err |= mlx5e_handle_feature(netdev, features, NETIF_F_RXFCS, 3388 err |= mlx5e_handle_feature(netdev, &oper_features, features,
3387 set_feature_rx_fcs); 3389 NETIF_F_RXFCS, set_feature_rx_fcs);
3388 err |= mlx5e_handle_feature(netdev, features, NETIF_F_HW_VLAN_CTAG_RX, 3390 err |= mlx5e_handle_feature(netdev, &oper_features, features,
3389 set_feature_rx_vlan); 3391 NETIF_F_HW_VLAN_CTAG_RX, set_feature_rx_vlan);
3390#ifdef CONFIG_RFS_ACCEL 3392#ifdef CONFIG_RFS_ACCEL
3391 err |= mlx5e_handle_feature(netdev, features, NETIF_F_NTUPLE, 3393 err |= mlx5e_handle_feature(netdev, &oper_features, features,
3392 set_feature_arfs); 3394 NETIF_F_NTUPLE, set_feature_arfs);
3393#endif 3395#endif
3394 3396
3395 return err ? -EINVAL : 0; 3397 if (err) {
3398 netdev->features = oper_features;
3399 return -EINVAL;
3400 }
3401
3402 return 0;
3396} 3403}
3397 3404
3398static netdev_features_t mlx5e_fix_features(struct net_device *netdev, 3405static netdev_features_t mlx5e_fix_features(struct net_device *netdev,