net/mlx5: E-Switch, preserve max tx speed on vport state modification

When modifying vport state, the firmware interprets a zero in the max tx
speed field as an intentional reset, which can overwrite previously set
values. This patch attempts to fix this by querying the current max tx
speed from firmware before modifying the vport state and passing it back
in the modification command. If the query fails, fall back to the cached
agg_max_tx_speed value to avoid inadvertently resetting the speed.

Fixes: 50f1d188c5 ("net/mlx5: Propagate LAG effective max_tx_speed to vports")
Signed-off-by: Or Har-Toov <ohartoov@nvidia.com>
Reviewed-by: Mark Bloch <mbloch@nvidia.com>
Reviewed-by: Shay Drori <shayd@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260816065015.3280733-4-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Or Har-Toov 2026-08-16 09:50:15 +03:00 committed by Jakub Kicinski
parent 20f11b5cfa
commit ad0ae7aefa
2 changed files with 44 additions and 0 deletions

View File

@ -11,6 +11,26 @@ int mlx5_esw_adj_vport_modify(struct mlx5_core_dev *dev, u16 vport,
lockdep_assert_held(&dev->priv.eswitch->state_lock);
if (MLX5_CAP_ESW(dev, esw_vport_state_max_tx_speed)) {
u8 op_mod = MLX5_VPORT_STATE_OP_MOD_ESW_VPORT;
struct mlx5_vport *esw_vport;
u32 speed = 0;
int err;
err = mlx5_query_vport_max_tx_speed(dev, op_mod, vport,
true, &speed, NULL);
if (err) {
esw_vport = mlx5_eswitch_get_vport(dev->priv.eswitch,
vport);
speed = IS_ERR(esw_vport) ? 0 :
esw_vport->agg_max_tx_speed;
mlx5_core_dbg(dev,
"Failed to query vport %d max tx speed, err=%d, using cached %u\n",
vport, err, speed);
}
MLX5_SET(modify_vport_state_in, in, max_tx_speed, speed);
}
MLX5_SET(modify_vport_state_in, in, opcode,
MLX5_CMD_OP_MODIFY_VPORT_STATE);
MLX5_SET(modify_vport_state_in, in, op_mod,

View File

@ -93,6 +93,30 @@ int mlx5_modify_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod,
lockdep_assert_held(&mdev->priv.eswitch->state_lock);
#endif
if (MLX5_CAP_ESW(mdev, esw_vport_state_max_tx_speed) &&
opmod == MLX5_VPORT_STATE_OP_MOD_ESW_VPORT &&
vport != MLX5_VPORT_UPLINK) {
u32 speed = 0;
int err;
err = mlx5_query_vport_max_tx_speed(mdev, opmod, vport,
other_vport, &speed, NULL);
if (err) {
#ifdef CONFIG_MLX5_ESWITCH
struct mlx5_vport *esw_vport;
esw_vport = mlx5_eswitch_get_vport(mdev->priv.eswitch,
vport);
speed = IS_ERR(esw_vport) ? 0 :
esw_vport->agg_max_tx_speed;
#endif
mlx5_core_dbg(mdev,
"Failed to query vport %d max tx speed, err=%d, using cached %u\n",
vport, err, speed);
}
MLX5_SET(modify_vport_state_in, in, max_tx_speed, speed);
}
MLX5_SET(modify_vport_state_in, in, opcode,
MLX5_CMD_OP_MODIFY_VPORT_STATE);
MLX5_SET(modify_vport_state_in, in, op_mod, opmod);