mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 04:34:03 +02:00
net/mlx5: E-Switch, use state lock for vport state changes
Protect vport admin state modifications and vport iteration with the
eswitch state_lock mutex to ensure proper serialization of concurrent
vport state changes.
Currently, calls to mlx5_modify_vport_admin_state() and loops iterating
over eswitch vports can race with each other, potentially leading to
inconsistent vport state. Fix this by acquiring esw->state_lock
Fixes: 7d0314b11c ("net/mlx5e: Modify uplink state on interface up/down")
Signed-off-by: Mark Bloch <mbloch@nvidia.com>
Reviewed-by: Shay Drori <shayd@nvidia.com>
Reviewed-by: Or Har-Toov <ohartoov@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260816065015.3280733-2-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
c5ae83ee02
commit
ff0f9b7aa1
|
|
@ -689,11 +689,13 @@ static int mlx5e_rep_open(struct net_device *dev)
|
|||
if (err)
|
||||
goto unlock;
|
||||
|
||||
mutex_lock(&rep->esw->state_lock);
|
||||
if (!mlx5_modify_vport_admin_state(priv->mdev,
|
||||
MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
|
||||
rep->vport, 1,
|
||||
MLX5_VPORT_ADMIN_STATE_UP))
|
||||
netif_carrier_on(dev);
|
||||
mutex_unlock(&rep->esw->state_lock);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&priv->state_lock);
|
||||
|
|
@ -708,10 +710,12 @@ static int mlx5e_rep_close(struct net_device *dev)
|
|||
int ret;
|
||||
|
||||
mutex_lock(&priv->state_lock);
|
||||
mutex_lock(&rep->esw->state_lock);
|
||||
mlx5_modify_vport_admin_state(priv->mdev,
|
||||
MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
|
||||
rep->vport, 1,
|
||||
MLX5_VPORT_ADMIN_STATE_DOWN);
|
||||
mutex_unlock(&rep->esw->state_lock);
|
||||
ret = mlx5e_close_locked(dev);
|
||||
mutex_unlock(&priv->state_lock);
|
||||
return ret;
|
||||
|
|
@ -783,22 +787,25 @@ static int mlx5e_rep_change_carrier(struct net_device *dev, bool new_carrier)
|
|||
struct mlx5e_priv *priv = netdev_priv(dev);
|
||||
struct mlx5e_rep_priv *rpriv = priv->ppriv;
|
||||
struct mlx5_eswitch_rep *rep = rpriv->rep;
|
||||
int err;
|
||||
int err = 0;
|
||||
|
||||
mutex_lock(&rep->esw->state_lock);
|
||||
if (new_carrier) {
|
||||
err = mlx5_modify_vport_admin_state(priv->mdev, MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
|
||||
rep->vport, 1, MLX5_VPORT_ADMIN_STATE_UP);
|
||||
if (err)
|
||||
return err;
|
||||
goto unlock;
|
||||
netif_carrier_on(dev);
|
||||
} else {
|
||||
err = mlx5_modify_vport_admin_state(priv->mdev, MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
|
||||
rep->vport, 1, MLX5_VPORT_ADMIN_STATE_DOWN);
|
||||
if (err)
|
||||
return err;
|
||||
goto unlock;
|
||||
netif_carrier_off(dev);
|
||||
}
|
||||
return 0;
|
||||
unlock:
|
||||
mutex_unlock(&rep->esw->state_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
static const struct net_device_ops mlx5e_netdev_ops_rep = {
|
||||
|
|
@ -1339,9 +1346,12 @@ static int mlx5e_uplink_rep_enable(struct mlx5e_priv *priv)
|
|||
|
||||
mlx5e_rep_tc_enable(priv);
|
||||
|
||||
if (MLX5_CAP_GEN(mdev, uplink_follow))
|
||||
if (MLX5_CAP_GEN(mdev, uplink_follow)) {
|
||||
mutex_lock(&mdev->priv.eswitch->state_lock);
|
||||
mlx5_modify_vport_admin_state(mdev, MLX5_VPORT_STATE_OP_MOD_UPLINK,
|
||||
0, 0, MLX5_VPORT_ADMIN_STATE_AUTO);
|
||||
mutex_unlock(&mdev->priv.eswitch->state_lock);
|
||||
}
|
||||
mlx5_lag_add_netdev(mdev, netdev);
|
||||
priv->events_nb.notifier_call = uplink_rep_async_event;
|
||||
mlx5_notifier_register(mdev, &priv->events_nb);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ int mlx5_esw_adj_vport_modify(struct mlx5_core_dev *dev, u16 vport,
|
|||
{
|
||||
u32 in[MLX5_ST_SZ_DW(modify_vport_state_in)] = {};
|
||||
|
||||
lockdep_assert_held(&dev->priv.eswitch->state_lock);
|
||||
|
||||
MLX5_SET(modify_vport_state_in, in, opcode,
|
||||
MLX5_CMD_OP_MODIFY_VPORT_STATE);
|
||||
MLX5_SET(modify_vport_state_in, in, op_mod,
|
||||
|
|
|
|||
|
|
@ -2567,6 +2567,7 @@ static void mlx5_esw_fdb_active(struct mlx5_eswitch *esw)
|
|||
mlx5_esw_fdb_drop_destroy(esw);
|
||||
mlx5_mpfs_enable(esw->dev);
|
||||
|
||||
mutex_lock(&esw->state_lock);
|
||||
mlx5_esw_for_each_vf_vport(esw, i, vport, U16_MAX) {
|
||||
if (!vport->adjacent)
|
||||
continue;
|
||||
|
|
@ -2574,6 +2575,7 @@ static void mlx5_esw_fdb_active(struct mlx5_eswitch *esw)
|
|||
vport->vport);
|
||||
mlx5_esw_adj_vport_modify(esw->dev, vport->vport, true);
|
||||
}
|
||||
mutex_unlock(&esw->state_lock);
|
||||
|
||||
esw->offloads_inactive = false;
|
||||
esw_warn(esw->dev, "MPFS/FDB active\n");
|
||||
|
|
@ -2587,6 +2589,7 @@ static void mlx5_esw_fdb_inactive(struct mlx5_eswitch *esw)
|
|||
mlx5_mpfs_disable(esw->dev);
|
||||
mlx5_esw_fdb_drop_create(esw);
|
||||
|
||||
mutex_lock(&esw->state_lock);
|
||||
mlx5_esw_for_each_vf_vport(esw, i, vport, U16_MAX) {
|
||||
if (!vport->adjacent)
|
||||
continue;
|
||||
|
|
@ -2595,6 +2598,7 @@ static void mlx5_esw_fdb_inactive(struct mlx5_eswitch *esw)
|
|||
|
||||
mlx5_esw_adj_vport_modify(esw->dev, vport->vport, false);
|
||||
}
|
||||
mutex_unlock(&esw->state_lock);
|
||||
|
||||
esw->offloads_inactive = true;
|
||||
esw_warn(esw->dev, "MPFS/FDB inactive\n");
|
||||
|
|
|
|||
|
|
@ -1471,6 +1471,7 @@ static void mlx5_lag_modify_device_vports_speed(struct mlx5_core_dev *mdev,
|
|||
if (!MLX5_CAP_ESW(mdev, esw_vport_state_max_tx_speed))
|
||||
return;
|
||||
|
||||
mutex_lock(&esw->state_lock);
|
||||
mlx5_esw_for_each_vport(esw, i, vport) {
|
||||
if (!vport)
|
||||
continue;
|
||||
|
|
@ -1490,6 +1491,7 @@ static void mlx5_lag_modify_device_vports_speed(struct mlx5_core_dev *mdev,
|
|||
"Failed to set vport %d speed %d, err=%d\n",
|
||||
vport->vport, speed, ret);
|
||||
}
|
||||
mutex_unlock(&esw->state_lock);
|
||||
}
|
||||
|
||||
void mlx5_lag_set_vports_agg_speed(struct mlx5_lag *ldev)
|
||||
|
|
|
|||
|
|
@ -89,6 +89,10 @@ int mlx5_modify_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod,
|
|||
{
|
||||
u32 in[MLX5_ST_SZ_DW(modify_vport_state_in)] = {};
|
||||
|
||||
#ifdef CONFIG_MLX5_ESWITCH
|
||||
lockdep_assert_held(&mdev->priv.eswitch->state_lock);
|
||||
#endif
|
||||
|
||||
MLX5_SET(modify_vport_state_in, in, opcode,
|
||||
MLX5_CMD_OP_MODIFY_VPORT_STATE);
|
||||
MLX5_SET(modify_vport_state_in, in, op_mod, opmod);
|
||||
|
|
@ -106,6 +110,10 @@ int mlx5_modify_vport_max_tx_speed(struct mlx5_core_dev *mdev, u8 opmod,
|
|||
u8 admin_state;
|
||||
int err;
|
||||
|
||||
#ifdef CONFIG_MLX5_ESWITCH
|
||||
lockdep_assert_held(&mdev->priv.eswitch->state_lock);
|
||||
#endif
|
||||
|
||||
err = mlx5_query_vport_admin_state(mdev, opmod, vport, other_vport,
|
||||
&admin_state);
|
||||
if (err)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user