| From 7f07d5dc7d2ab24c98be569c880615dd45cfc53c Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Mon, 29 Nov 2021 11:08:41 +0200 |
| Subject: net/mlx5e: Fix wrong features assignment in case of error |
| |
| From: Gal Pressman <gal@nvidia.com> |
| |
| [ Upstream commit 992d8a4e38f0527f24e273ce3a9cd6dea1a6a436 ] |
| |
| In case of an error in mlx5e_set_features(), 'netdev->features' must be |
| updated with the correct state of the device to indicate which features |
| were updated successfully. |
| To do that we maintain a copy of 'netdev->features' and update it after |
| successful feature changes, so we can assign it to back to |
| 'netdev->features' if needed. |
| |
| However, since not all netdev features are handled by the driver (e.g. |
| GRO/TSO/etc), some features may not be updated correctly in case of an |
| error updating another feature. |
| |
| For example, while requesting to disable TSO (feature which is not |
| handled by the driver) and enable HW-GRO, if an error occurs during |
| HW-GRO enable, 'oper_features' will be assigned with 'netdev->features' |
| and HW-GRO turned off. TSO will remain enabled in such case, which is a |
| bug. |
| |
| To solve that, instead of using 'netdev->features' as the baseline of |
| 'oper_features' and changing it on set feature success, use 'features' |
| instead and update it in case of errors. |
| |
| Fixes: 75b81ce719b7 ("net/mlx5e: Don't override netdev features field unless in error flow") |
| Signed-off-by: Gal Pressman <gal@nvidia.com> |
| Signed-off-by: Saeed Mahameed <saeedm@nvidia.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 11 +++++------ |
| 1 file changed, 5 insertions(+), 6 deletions(-) |
| |
| diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c |
| index 9003702892cda..5979fcf124bb4 100644 |
| --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c |
| +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c |
| @@ -3666,12 +3666,11 @@ static int set_feature_arfs(struct net_device *netdev, bool enable) |
| |
| static int mlx5e_handle_feature(struct net_device *netdev, |
| netdev_features_t *features, |
| - netdev_features_t wanted_features, |
| netdev_features_t feature, |
| mlx5e_feature_handler feature_handler) |
| { |
| - netdev_features_t changes = wanted_features ^ netdev->features; |
| - bool enable = !!(wanted_features & feature); |
| + netdev_features_t changes = *features ^ netdev->features; |
| + bool enable = !!(*features & feature); |
| int err; |
| |
| if (!(changes & feature)) |
| @@ -3679,23 +3678,23 @@ static int mlx5e_handle_feature(struct net_device *netdev, |
| |
| err = feature_handler(netdev, enable); |
| if (err) { |
| + MLX5E_SET_FEATURE(features, feature, !enable); |
| netdev_err(netdev, "%s feature %pNF failed, err %d\n", |
| enable ? "Enable" : "Disable", &feature, err); |
| return err; |
| } |
| |
| - MLX5E_SET_FEATURE(features, feature, enable); |
| return 0; |
| } |
| |
| static int mlx5e_set_features(struct net_device *netdev, |
| netdev_features_t features) |
| { |
| - netdev_features_t oper_features = netdev->features; |
| + netdev_features_t oper_features = features; |
| int err = 0; |
| |
| #define MLX5E_HANDLE_FEATURE(feature, handler) \ |
| - mlx5e_handle_feature(netdev, &oper_features, features, feature, handler) |
| + mlx5e_handle_feature(netdev, &oper_features, feature, handler) |
| |
| err |= MLX5E_HANDLE_FEATURE(NETIF_F_LRO, set_feature_lro); |
| err |= MLX5E_HANDLE_FEATURE(NETIF_F_HW_VLAN_CTAG_FILTER, |
| -- |
| 2.34.1 |
| |