From: Tariq Toukan <tariqt@nvidia.com>
To: Andrew Lunn <andrew+netdev@lunn.ch>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@kernel.org>,
Jakub Kicinski <kuba@kernel.org>, <netdev@vger.kernel.org>,
Paolo Abeni <pabeni@redhat.com>
Cc: Bjorn Helgaas <bhelgaas@google.com>,
Carolina Jubran <cjubran@nvidia.com>,
Cosmin Ratiu <cratiu@nvidia.com>,
Edward Srouji <edwards@nvidia.com>,
"Gal Pressman" <gal@nvidia.com>, Jason Gunthorpe <jgg@ziepe.ca>,
Kees Cook <kees@kernel.org>, Leon Romanovsky <leon@kernel.org>,
open list <linux-kernel@vger.kernel.org>,
<linux-pci@vger.kernel.org>, <linux-rdma@vger.kernel.org>,
Maher Sanalla <msanalla@nvidia.com>,
Mark Bloch <mbloch@nvidia.com>, Or Har-Toov <ohartoov@nvidia.com>,
Saeed Mahameed <saeedm@nvidia.com>, Shay Drori <shayd@nvidia.com>,
Tariq Toukan <tariqt@nvidia.com>
Subject: [PATCH net V2 4/4] net/mlx5: Lag, save and restore vport max_tx_speed across LAG
Date: Thu, 22 Oct 2026 22:30:53 +0300 [thread overview]
Message-ID: <20261022193053.3815866-5-tariqt@nvidia.com> (raw)
In-Reply-To: <20261022193053.3815866-1-tariqt@nvidia.com>
From: Or Har-Toov <ohartoov@nvidia.com>
mlx5_lag_reset_vports_speed() queries the oper link speed at LAG
teardown and writes it back to each vport. When the link is down at
that moment, mlx5_port_oper_linkspeed() returns 0, which FW treats as
"not provided" and ignores, leaving the aggregate rate limit on the
vports after teardown.
Save each vport's max_tx_speed when the vport is enabled, before the
LAG aggregate or a deferred aggregate replay can overwrite it. While a
LAG is active, only a vport with a pending aggregate is saved, as FW
may already hold the aggregate for any other vport. Restore the saved
value per vport at teardown instead of querying the oper speed, and
update agg_max_tx_speed to the pre-LAG value so disabled vports replay
the correct rate when they are later enabled. A vport keeps its
saved value after teardown, as it is the baseline for the next LAG, and
for a disabled vport it is also the pending restore value.
If the max_tx_speed of a vport could not be saved, it stays zero and
mlx5_lag_get_restore_speed() falls back to a link-derived speed at
teardown. The aggregate is still applied to such a vport.
This also covers the case where the oper speed query fails and the PF
is skipped entirely, leaving the aggregate in FW and in
agg_max_tx_speed, as raised in the AI review of v1 of "net/mlx5: Lag,
reset vport speed on teardown". It is unrelated to that patch, so it is
fixed here separately.
Firmware never returns zero as a configured max_tx_speed; zero means
"not supported", so using it as a sentinel for "not yet saved" is safe.
A vport disabled for the entire LAG period was never assigned a
per-vport rate limit, so no original speed exists to restore; deferring
through agg_max_tx_speed on re-enable is correct.
Fixes: 50f1d188c580 ("net/mlx5: Propagate LAG effective max_tx_speed to vports")
Link: https://lore.kernel.org/all/20260915015118.875210-1-kuba@kernel.org/
Signed-off-by: Or Har-Toov <ohartoov@nvidia.com>
Reviewed-by: Mark Bloch <mbloch@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
---
.../net/ethernet/mellanox/mlx5/core/eswitch.c | 22 ++++++
.../net/ethernet/mellanox/mlx5/core/eswitch.h | 1 +
.../net/ethernet/mellanox/mlx5/core/lag/lag.c | 68 ++++++++++++++++---
3 files changed, 81 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
index fc197d1dc9df..7cf9c15ec65d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
@@ -935,6 +935,27 @@ static void esw_vport_cleanup(struct mlx5_eswitch *esw, struct mlx5_vport *vport
esw_vport_cleanup_acl(esw, vport);
}
+static void mlx5_esw_vport_save_max_tx_speed(struct mlx5_eswitch *esw,
+ struct mlx5_vport *vport)
+{
+ u16 op_mod = MLX5_VPORT_STATE_OP_MOD_ESW_VPORT;
+ int ret;
+
+ if (!MLX5_CAP_ESW(esw->dev, esw_vport_state_max_tx_speed) ||
+ vport->vport == MLX5_VPORT_UPLINK || vport->max_tx_speed)
+ return;
+
+ if (mlx5_lag_is_active(esw->dev) && !vport->agg_max_tx_speed)
+ return;
+
+ ret = mlx5_query_vport_max_tx_speed(esw->dev, op_mod, vport->vport,
+ true, &vport->max_tx_speed, NULL);
+ if (ret)
+ mlx5_core_dbg(esw->dev,
+ "Failed to save vport %d max tx speed, err=%d\n",
+ vport->vport, ret);
+}
+
static void mlx5_esw_vport_set_max_tx_speed(struct mlx5_eswitch *esw,
struct mlx5_vport *vport)
{
@@ -999,6 +1020,7 @@ int mlx5_esw_vport_enable(struct mlx5_eswitch *esw, struct mlx5_vport *vport,
esw->enabled_vports++;
esw_debug(esw->dev, "Enabled VPORT(%d)\n", vport_num);
+ mlx5_esw_vport_save_max_tx_speed(esw, vport);
if (vport->agg_max_tx_speed)
mlx5_esw_vport_set_max_tx_speed(esw, vport);
done:
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
index 8b1f93b13ea9..3717fb6de0b6 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
@@ -261,6 +261,7 @@ struct mlx5_vport {
int index;
struct mlx5_devlink_port *dl_port;
u32 agg_max_tx_speed;
+ u32 max_tx_speed;
};
struct mlx5_esw_indir_table;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
index afe0b9909f2d..3e623c96b2a1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
@@ -1712,11 +1712,37 @@ void mlx5_lag_set_vports_agg_speed(struct mlx5_lag *ldev)
}
}
+static int mlx5_lag_get_restore_speed(struct mlx5_core_dev *mdev,
+ struct mlx5_vport *vport, u32 *speed)
+{
+ u32 pci_bw;
+
+ if (vport->max_tx_speed) {
+ *speed = vport->max_tx_speed;
+ return 0;
+ }
+
+ *speed = 0;
+ mlx5_port_oper_linkspeed(mdev, speed);
+ if (!*speed && mlx5_port_max_linkspeed(mdev, speed))
+ return -ENODATA;
+
+ pci_bw = pcie_bandwidth_mbps(mdev->pdev);
+ if (pci_bw)
+ *speed = min(*speed, pci_bw);
+ *speed /= MLX5_MAX_TX_SPEED_UNIT;
+ return 0;
+}
+
void mlx5_lag_reset_vports_speed(struct mlx5_lag *ldev)
{
+ u16 op_mod = MLX5_VPORT_STATE_OP_MOD_ESW_VPORT;
struct mlx5_core_dev *mdev;
+ struct mlx5_eswitch *esw;
+ struct mlx5_vport *vport;
struct lag_func *pf;
- u32 speed;
+ u32 restore_speed;
+ unsigned long i;
int pf_idx;
int ret;
@@ -1728,17 +1754,39 @@ void mlx5_lag_reset_vports_speed(struct mlx5_lag *ldev)
mdev = pf->dev;
if (!mdev)
continue;
-
- ret = mlx5_port_oper_linkspeed(mdev, &speed);
- if (ret) {
- mlx5_core_dbg(mdev,
- "Failed to reset vports speed for device %s. Oper speed is not available (err=%d)\n",
- dev_name(mdev->device), ret);
+ esw = mdev->priv.eswitch;
+ if (!esw || !MLX5_CAP_ESW(mdev, esw_vport_state_max_tx_speed))
continue;
- }
- speed = speed / MLX5_MAX_TX_SPEED_UNIT;
- mlx5_lag_modify_device_vports_speed(mdev, speed);
+ mutex_lock(&esw->state_lock);
+ mlx5_esw_for_each_vport(esw, i, vport) {
+ if (!vport || vport->vport == MLX5_VPORT_UPLINK)
+ continue;
+
+ if (!vport->enabled) {
+ vport->agg_max_tx_speed = vport->max_tx_speed;
+ continue;
+ }
+
+ if (mlx5_lag_get_restore_speed(mdev, vport,
+ &restore_speed)) {
+ vport->agg_max_tx_speed = 0;
+ continue;
+ }
+
+ ret = mlx5_modify_vport_max_tx_speed(mdev, op_mod,
+ vport->vport,
+ true,
+ restore_speed);
+ if (ret) {
+ mlx5_core_dbg(mdev,
+ "Failed to restore vport %d max tx speed, err=%d\n",
+ vport->vport, ret);
+ continue;
+ }
+ vport->agg_max_tx_speed = 0;
+ }
+ mutex_unlock(&esw->state_lock);
}
}
#endif
--
2.44.0
next prev parent reply other threads:[~2026-10-22 19:32 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-22 19:30 [PATCH net V2 0/4] net/mlx5: fixes for LAG max_tx_speed update flow Tariq Toukan
2026-10-22 19:30 ` [PATCH net V2 1/4] {RDMA,net}/mlx5: cache and use TX-enabled aggregate speed for vports Tariq Toukan
2026-10-22 19:30 ` [PATCH net V2 2/4] net/mlx5: Lag, limit aggregated TX speed by PCIe bandwidth Tariq Toukan
2026-10-22 19:30 ` [PATCH net V2 3/4] {RDMA,net}/mlx5: notify IB uplink on LAG aggregate speed change Tariq Toukan
2026-10-22 19:30 ` Tariq Toukan [this message]
2026-10-22 19:37 ` [PATCH net V2 0/4] net/mlx5: fixes for LAG max_tx_speed update flow netdev-bot+sinfo
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=20261022193053.3815866-5-tariqt@nvidia.com \
--to=tariqt@nvidia.com \
--cc=andrew+netdev@lunn.ch \
--cc=bhelgaas@google.com \
--cc=cjubran@nvidia.com \
--cc=cratiu@nvidia.com \
--cc=davem@davemloft.net \
--cc=edumazet@kernel.org \
--cc=edwards@nvidia.com \
--cc=gal@nvidia.com \
--cc=jgg@ziepe.ca \
--cc=kees@kernel.org \
--cc=kuba@kernel.org \
--cc=leon@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=linux-rdma@vger.kernel.org \
--cc=mbloch@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
all inboxes | Powered by JetHome®