From: Tariq Toukan <tariqt@nvidia.com>
To: Andrew Lunn <andrew+netdev@lunn.ch>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, <netdev@vger.kernel.org>,
Paolo Abeni <pabeni@redhat.com>
Cc: Adithya Jayachandran <ajayachandra@nvidia.com>,
Edward Srouji <edwards@nvidia.com>, Gal Pressman <gal@nvidia.com>,
Jason Gunthorpe <jgg@ziepe.ca>, Jiri Pirko <jiri@resnulli.us>,
Leon Romanovsky <leon@kernel.org>, <linux-kernel@vger.kernel.org>,
<linux-rdma@vger.kernel.org>, Maher Sanalla <msanalla@nvidia.com>,
Mark Bloch <mbloch@nvidia.com>, Moshe Shemesh <moshe@nvidia.com>,
Or Har-Toov <ohartoov@nvidia.com>,
Saeed Mahameed <saeedm@nvidia.com>, Shay Drori <shayd@nvidia.com>,
Simon Horman <horms@kernel.org>, Tariq Toukan <tariqt@nvidia.com>
Subject: [PATCH net 1/3] net/mlx5: E-Switch, use state lock for vport state changes
Date: Sun, 16 Aug 2026 09:50:13 +0300 [thread overview]
Message-ID: <20260816065015.3280733-2-tariqt@nvidia.com> (raw)
In-Reply-To: <20260816065015.3280733-1-tariqt@nvidia.com>
From: Mark Bloch <mbloch@nvidia.com>
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: 7d0314b11cdd ("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>
---
.../net/ethernet/mellanox/mlx5/core/en_rep.c | 20 ++++++++++++++-----
.../mellanox/mlx5/core/esw/adj_vport.c | 2 ++
.../mellanox/mlx5/core/eswitch_offloads.c | 4 ++++
.../net/ethernet/mellanox/mlx5/core/lag/lag.c | 2 ++
.../net/ethernet/mellanox/mlx5/core/vport.c | 8 ++++++++
5 files changed, 31 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index c8b76d301c92..3d544fe4e6f7 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -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 = {
@@ -1337,9 +1344,12 @@ static void 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);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/adj_vport.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/adj_vport.c
index ca249b50f830..3624c680a861 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/adj_vport.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/adj_vport.c
@@ -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,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
index 247e5d85ec36..d603e294ee0e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
@@ -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");
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
index 28d16fdc3f06..2285c889c215 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
@@ -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)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/vport.c b/drivers/net/ethernet/mellanox/mlx5/core/vport.c
index 3676e26ac6b0..080f097b7bfa 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/vport.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/vport.c
@@ -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)
--
2.44.0
next prev parent reply other threads:[~2026-08-16 6:51 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-16 6:50 [PATCH net 0/3] net/mlx5: Preserve speed and state across vport modify commands Tariq Toukan
2026-08-16 6:50 ` Tariq Toukan [this message]
2026-08-16 6:50 ` [PATCH net 2/3] net/mlx5: Move vport DOWN state check out of mlx5_query_vport_max_tx_speed() Tariq Toukan
2026-08-16 6:50 ` [PATCH net 3/3] net/mlx5: E-Switch, preserve max tx speed on vport state modification Tariq Toukan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260816065015.3280733-2-tariqt@nvidia.com \
--to=tariqt@nvidia.com \
--cc=ajayachandra@nvidia.com \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=edwards@nvidia.com \
--cc=gal@nvidia.com \
--cc=horms@kernel.org \
--cc=jgg@ziepe.ca \
--cc=jiri@resnulli.us \
--cc=kuba@kernel.org \
--cc=leon@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rdma@vger.kernel.org \
--cc=mbloch@nvidia.com \
--cc=moshe@nvidia.com \
--cc=msanalla@nvidia.com \
--cc=netdev@vger.kernel.org \
--cc=ohartoov@nvidia.com \
--cc=pabeni@redhat.com \
--cc=saeedm@nvidia.com \
--cc=shayd@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox