* [PATCH net 0/5] net/mlx5: fixes for LAG max_tx_speed update flow
@ 2026-09-10 10:24 Tariq Toukan
2026-09-10 10:24 ` [PATCH net 1/5] net/mlx5: Lag, split aggregate speed into oper and max helpers Tariq Toukan
` (4 more replies)
0 siblings, 5 replies; 11+ messages in thread
From: Tariq Toukan @ 2026-09-10 10:24 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
netdev, Paolo Abeni
Cc: Edward Srouji, Gal Pressman, Jason Gunthorpe, Leon Romanovsky,
open list, linux-rdma, Maher Sanalla, Mark Bloch, Or Har-Toov,
Saeed Mahameed, Shay Drori, Tariq Toukan
Hi,
Commit 50f1d188c580 ("net/mlx5: Propagate LAG effective max_tx_speed to
vports") added a mechanism that computes the aggregated LAG TX speed and
programs it into each vport's max_tx_speed via MODIFY_VPORT_STATE. This
series by Or fixes bugs found in that flow.
The bugs:
1. Down ports were counted into the effective aggregate speed.
When a port goes down, PTYS eth_proto_oper is not necessary 0.
2. The aggregate was not limited by the NIC's PCIe bandwidth. It was
taken from the bond speed, which is calculated from PTYS, and PTYS
is not bounded by the PCI bandwidth of the NIC. FW initializes
max_tx_speed to the minimum of the port speed and the PCIe
bandwidth, so modifying it with a value computed by different rules
changes the meaning of the field rather than updating it.
3. MPESW teardown never reset the vport speeds, leaving stale values
after teardown.
4. RoCE LAG never told the RDMA layer about speed changes. The NIC is
considered to be in a bare metal configuration, without a valid or
enabled eswitch, so there are no VF, SF or PF rep vports to modify
and no event of speed change was raised.
Patch #1 splits the LAG aggregate speed into an operative and a max
helper, so that each can filter on port state on its own.
Patch #2 resets the vport speed on MPESW teardown.
Patch #3 caches the TX-enabled aggregate speed and programs that into
the vports, instead of reading it back from the bond netdev.
Patch #4 limits the aggregated TX speed by the NIC's PCIe bandwidth.
Patch #5 notifies the RDMA layer of RoCE LAG speed changes via a new
driver event.
Regards,
Tariq
Or Har-Toov (5):
net/mlx5: Lag, split aggregate speed into oper and max helpers
net/mlx5: Lag, reset vport speed on teardown
{RDMA,net}/mlx5: cache and use TX-enabled aggregate speed for vports
net/mlx5: Lag, limit aggregated TX speed by PCIe bandwidth
{RDMA,net}/mlx5: notify RoCE LAG speed change via driver event
drivers/infiniband/hw/mlx5/main.c | 12 +-
drivers/net/ethernet/mellanox/mlx5/core/dev.c | 20 +++
.../net/ethernet/mellanox/mlx5/core/lag/lag.c | 159 +++++++++++++++---
.../net/ethernet/mellanox/mlx5/core/lag/lag.h | 16 +-
.../ethernet/mellanox/mlx5/core/mlx5_core.h | 1 +
include/linux/mlx5/device.h | 1 +
include/linux/mlx5/driver.h | 1 +
7 files changed, 181 insertions(+), 29 deletions(-)
base-commit: 00f9fbc12320253bfc576fb7539d860029c82d0f
--
2.44.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH net 1/5] net/mlx5: Lag, split aggregate speed into oper and max helpers
2026-09-10 10:24 [PATCH net 0/5] net/mlx5: fixes for LAG max_tx_speed update flow Tariq Toukan
@ 2026-09-10 10:24 ` Tariq Toukan
2026-09-10 10:46 ` sashiko-bot
2026-09-10 10:24 ` [PATCH net 2/5] net/mlx5: Lag, reset vport speed on teardown Tariq Toukan
` (3 subsequent siblings)
4 siblings, 1 reply; 11+ messages in thread
From: Tariq Toukan @ 2026-09-10 10:24 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
netdev, Paolo Abeni
Cc: Edward Srouji, Gal Pressman, Jason Gunthorpe, Leon Romanovsky,
open list, linux-rdma, Maher Sanalla, Mark Bloch, Or Har-Toov,
Saeed Mahameed, Shay Drori, Tariq Toukan
From: Or Har-Toov <ohartoov@nvidia.com>
Split mlx5_lag_sum_devices_speed into mlx5_lag_get_devices_oper_speed
and mlx5_lag_get_devices_max_speed. The oper function reflects only
the speed currently available and the max function is state-independent
and represents the maximum achievable speed, taking the best single
port for active-backup and summing all ports for XOR, LACP and MPESW.
The oper function skips a port for two reasons:
- the bonding driver set tx_enabled=false - LACP converging or
active-backup standby slave, where carrier may still be up but the
port is intentionally not forwarding traffic.
- the link is down.
Fixes: 50f1d188c580 ("net/mlx5: Propagate LAG effective max_tx_speed to vports")
Signed-off-by: Or Har-Toov <ohartoov@nvidia.com>
Reviewed-by: Shay Drori <shayd@nvidia.com>
Reviewed-by: Mark Bloch <mbloch@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
---
.../net/ethernet/mellanox/mlx5/core/lag/lag.c | 71 ++++++++++++++-----
1 file changed, 53 insertions(+), 18 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
index c655f6e32e9b..5aa9d5c98fe1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
@@ -1412,16 +1412,20 @@ static bool mlx5_lag_should_disable_lag(struct mlx5_lag *ldev, bool do_bond)
}
#ifdef CONFIG_MLX5_ESWITCH
-static int
-mlx5_lag_sum_devices_speed(struct mlx5_lag *ldev, u32 *sum_speed,
- int (*get_speed)(struct mlx5_core_dev *, u32 *))
+static int mlx5_lag_get_devices_oper_speed(struct mlx5_lag *ldev,
+ u32 *sum_speed)
{
struct mlx5_core_dev *pf_mdev;
struct lag_func *pf;
int pf_idx;
+ bool mpesw;
u32 speed;
+ u8 opmod;
int ret;
+ mpesw = ldev->mode == MLX5_LAG_MODE_MPESW;
+ opmod = MLX5_VPORT_STATE_OP_MOD_VNIC_VPORT;
+
*sum_speed = 0;
mlx5_ldev_for_each(pf_idx, 0, ldev) {
pf = mlx5_lag_pf(ldev, pf_idx);
@@ -1430,13 +1434,20 @@ mlx5_lag_sum_devices_speed(struct mlx5_lag *ldev, u32 *sum_speed,
pf_mdev = pf->dev;
if (!pf_mdev)
continue;
+ if (mpesw) {
+ if (mlx5_query_vport_state(pf_mdev, opmod, 0) !=
+ VPORT_STATE_UP)
+ continue;
+ } else if (!ldev->tracker.netdev_state[pf_idx].tx_enabled ||
+ !ldev->tracker.netdev_state[pf_idx].link_up) {
+ continue;
+ }
- ret = get_speed(pf_mdev, &speed);
+ ret = mlx5_port_oper_linkspeed(pf_mdev, &speed);
if (ret) {
mlx5_core_dbg(pf_mdev,
- "Failed to get device speed using %ps. Device %s speed is not available (err=%d)\n",
- get_speed, dev_name(pf_mdev->device),
- ret);
+ "Failed to get device %s oper speed (err=%d)\n",
+ dev_name(pf_mdev->device), ret);
return ret;
}
@@ -1446,17 +1457,41 @@ mlx5_lag_sum_devices_speed(struct mlx5_lag *ldev, u32 *sum_speed,
return 0;
}
-static int mlx5_lag_sum_devices_max_speed(struct mlx5_lag *ldev, u32 *max_speed)
+static int mlx5_lag_get_devices_max_speed(struct mlx5_lag *ldev, u32 *max_speed)
{
- return mlx5_lag_sum_devices_speed(ldev, max_speed,
- mlx5_port_max_linkspeed);
-}
+ struct mlx5_core_dev *pf_mdev;
+ struct lag_func *pf;
+ bool take_max;
+ int pf_idx;
+ u32 speed;
+ int ret;
-static int mlx5_lag_sum_devices_oper_speed(struct mlx5_lag *ldev,
- u32 *oper_speed)
-{
- return mlx5_lag_sum_devices_speed(ldev, oper_speed,
- mlx5_port_oper_linkspeed);
+ take_max = ldev->tracker.tx_type == NETDEV_LAG_TX_TYPE_ACTIVEBACKUP;
+ if (ldev->mode == MLX5_LAG_MODE_MPESW)
+ take_max = false;
+
+ *max_speed = 0;
+ mlx5_ldev_for_each(pf_idx, 0, ldev) {
+ pf = mlx5_lag_pf(ldev, pf_idx);
+ if (!pf)
+ continue;
+ pf_mdev = pf->dev;
+ if (!pf_mdev)
+ continue;
+
+ ret = mlx5_port_max_linkspeed(pf_mdev, &speed);
+ if (ret) {
+ mlx5_core_dbg(pf_mdev,
+ "Failed to get device %s max speed (err=%d)\n",
+ dev_name(pf_mdev->device), ret);
+ return ret;
+ }
+
+ *max_speed = take_max ?
+ max(*max_speed, speed) : *max_speed + speed;
+ }
+
+ return 0;
}
static void mlx5_lag_modify_device_vports_speed(struct mlx5_core_dev *mdev,
@@ -1505,7 +1540,7 @@ void mlx5_lag_set_vports_agg_speed(struct mlx5_lag *ldev)
int pf_idx;
if (ldev->mode == MLX5_LAG_MODE_MPESW) {
- if (mlx5_lag_sum_devices_oper_speed(ldev, &speed))
+ if (mlx5_lag_get_devices_oper_speed(ldev, &speed))
return;
} else {
speed = ldev->tracker.bond_speed_mbps;
@@ -1514,7 +1549,7 @@ void mlx5_lag_set_vports_agg_speed(struct mlx5_lag *ldev)
}
/* If speed is not set, use the sum of max speeds of all PFs */
- if (!speed && mlx5_lag_sum_devices_max_speed(ldev, &speed))
+ if (!speed && mlx5_lag_get_devices_max_speed(ldev, &speed))
return;
speed = speed / MLX5_MAX_TX_SPEED_UNIT;
--
2.44.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH net 2/5] net/mlx5: Lag, reset vport speed on teardown
2026-09-10 10:24 [PATCH net 0/5] net/mlx5: fixes for LAG max_tx_speed update flow Tariq Toukan
2026-09-10 10:24 ` [PATCH net 1/5] net/mlx5: Lag, split aggregate speed into oper and max helpers Tariq Toukan
@ 2026-09-10 10:24 ` Tariq Toukan
2026-09-10 10:46 ` sashiko-bot
2026-09-10 10:24 ` [PATCH net 3/5] {RDMA,net}/mlx5: cache and use TX-enabled aggregate speed for vports Tariq Toukan
` (2 subsequent siblings)
4 siblings, 1 reply; 11+ messages in thread
From: Tariq Toukan @ 2026-09-10 10:24 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
netdev, Paolo Abeni
Cc: Edward Srouji, Gal Pressman, Jason Gunthorpe, Leon Romanovsky,
open list, linux-rdma, Maher Sanalla, Mark Bloch, Or Har-Toov,
Saeed Mahameed, Shay Drori, Tariq Toukan
From: Or Har-Toov <ohartoov@nvidia.com>
mlx5_lag_disable_mpesw() never resets the cached agg_max_tx_speed on
the vports, unlike regular LAG teardown. This leaves stale speed values
cached on struct mlx5_vport, and pushed to FW, after MPESW is torn
down.
Move the mlx5_lag_reset_vports_speed() call from mlx5_do_bond() into
mlx5_deactivate_lag(), so that every teardown path resets the vport
speeds.
Fixes: 50f1d188c580 ("net/mlx5: Propagate LAG effective max_tx_speed to vports")
Signed-off-by: Or Har-Toov <ohartoov@nvidia.com>
Reviewed-by: Shay Drori <shayd@nvidia.com>
Reviewed-by: Mark Bloch <mbloch@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
---
drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
index 5aa9d5c98fe1..c2f21eb4ea7c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
@@ -1075,6 +1075,8 @@ int mlx5_deactivate_lag(struct mlx5_lag *ldev)
if (master_idx < 0)
return -EINVAL;
+ mlx5_lag_reset_vports_speed(ldev);
+
dev0 = mlx5_lag_pf(ldev, master_idx)->dev;
ldev->mode = MLX5_LAG_MODE_NONE;
ldev->mode_flags = 0;
@@ -1676,7 +1678,6 @@ static void mlx5_do_bond(struct mlx5_lag *ldev)
mlx5_modify_lag(ldev, &tracker);
mlx5_lag_set_vports_agg_speed(ldev);
} else if (mlx5_lag_should_disable_lag(ldev, do_bond)) {
- mlx5_lag_reset_vports_speed(ldev);
mlx5_disable_lag(ldev);
}
}
--
2.44.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH net 3/5] {RDMA,net}/mlx5: cache and use TX-enabled aggregate speed for vports
2026-09-10 10:24 [PATCH net 0/5] net/mlx5: fixes for LAG max_tx_speed update flow Tariq Toukan
2026-09-10 10:24 ` [PATCH net 1/5] net/mlx5: Lag, split aggregate speed into oper and max helpers Tariq Toukan
2026-09-10 10:24 ` [PATCH net 2/5] net/mlx5: Lag, reset vport speed on teardown Tariq Toukan
@ 2026-09-10 10:24 ` Tariq Toukan
2026-09-10 10:46 ` sashiko-bot
2026-09-10 10:24 ` [PATCH net 4/5] net/mlx5: Lag, limit aggregated TX speed by PCIe bandwidth Tariq Toukan
2026-09-10 10:24 ` [PATCH net 5/5] {RDMA,net}/mlx5: notify RoCE LAG speed change via driver event Tariq Toukan
4 siblings, 1 reply; 11+ messages in thread
From: Tariq Toukan @ 2026-09-10 10:24 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
netdev, Paolo Abeni
Cc: Edward Srouji, Gal Pressman, Jason Gunthorpe, Leon Romanovsky,
open list, linux-rdma, Maher Sanalla, Mark Bloch, Or Har-Toov,
Saeed Mahameed, Shay Drori, Tariq Toukan
From: Or Har-Toov <ohartoov@nvidia.com>
Cache aggregate TX-enabled speed we calculated, and use it instead of
querying the bond speed so we can, in the following patch, limit it by
the PCI bandwidth.
The bond speed takes the calculation from PTYS, and PTYS is not bounded
by the PCI bandwidth of the NIC.
Fixes: 50f1d188c580 ("net/mlx5: Propagate LAG effective max_tx_speed to vports")
Signed-off-by: Or Har-Toov <ohartoov@nvidia.com>
Reviewed-by: Shay Drori <shayd@nvidia.com>
Reviewed-by: Mark Bloch <mbloch@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
---
drivers/infiniband/hw/mlx5/main.c | 2 +-
.../net/ethernet/mellanox/mlx5/core/lag/lag.c | 61 +++++++++++++++----
.../net/ethernet/mellanox/mlx5/core/lag/lag.h | 15 ++++-
include/linux/mlx5/driver.h | 1 +
4 files changed, 65 insertions(+), 14 deletions(-)
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index 373ee1f42d4a..6ab7f945e712 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -1654,7 +1654,7 @@ static int mlx5_ib_query_port_speed_from_bond(struct mlx5_ib_dev *dev,
u32 bond_speed;
int err;
- err = mlx5_lag_query_bond_speed(mdev, &bond_speed);
+ err = mlx5_lag_query_aggregated_speed(mdev, &bond_speed);
if (err)
return err;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
index c2f21eb4ea7c..76b574fa0d7a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
@@ -1413,7 +1413,6 @@ static bool mlx5_lag_should_disable_lag(struct mlx5_lag *ldev, bool do_bond)
ldev->mode != MLX5_LAG_MODE_MPESW;
}
-#ifdef CONFIG_MLX5_ESWITCH
static int mlx5_lag_get_devices_oper_speed(struct mlx5_lag *ldev,
u32 *sum_speed)
{
@@ -1496,6 +1495,30 @@ static int mlx5_lag_get_devices_max_speed(struct mlx5_lag *ldev, u32 *max_speed)
return 0;
}
+void mlx5_lag_update_agg_speed(struct mlx5_lag *ldev)
+{
+ u32 speed;
+
+ lockdep_assert_held(&ldev->lock);
+
+ if (mlx5_lag_get_devices_oper_speed(ldev, &speed))
+ return;
+
+ /* If speed is not set, use the sum of max speeds of all PFs */
+ if (!speed && mlx5_lag_get_devices_max_speed(ldev, &speed))
+ return;
+
+ ldev->agg_speed_mbps = speed;
+}
+
+void mlx5_lag_reset_agg_speed(struct mlx5_lag *ldev)
+{
+ lockdep_assert_held(&ldev->lock);
+
+ ldev->agg_speed_mbps = 0;
+}
+
+#ifdef CONFIG_MLX5_ESWITCH
static void mlx5_lag_modify_device_vports_speed(struct mlx5_core_dev *mdev,
u32 speed)
{
@@ -1541,17 +1564,10 @@ void mlx5_lag_set_vports_agg_speed(struct mlx5_lag *ldev)
u32 speed;
int pf_idx;
- if (ldev->mode == MLX5_LAG_MODE_MPESW) {
- if (mlx5_lag_get_devices_oper_speed(ldev, &speed))
- return;
- } else {
- speed = ldev->tracker.bond_speed_mbps;
- if (speed == SPEED_UNKNOWN)
- return;
- }
+ mlx5_lag_update_agg_speed(ldev);
+ speed = ldev->agg_speed_mbps;
- /* If speed is not set, use the sum of max speeds of all PFs */
- if (!speed && mlx5_lag_get_devices_max_speed(ldev, &speed))
+ if (!speed)
return;
speed = speed / MLX5_MAX_TX_SPEED_UNIT;
@@ -1576,6 +1592,7 @@ void mlx5_lag_reset_vports_speed(struct mlx5_lag *ldev)
int pf_idx;
int ret;
+ mlx5_lag_reset_agg_speed(ldev);
mlx5_ldev_for_each(pf_idx, 0, ldev) {
pf = mlx5_lag_pf(ldev, pf_idx);
if (!pf)
@@ -2068,6 +2085,28 @@ static int mlx5_handle_changeinfodata_event(struct mlx5_lag *ldev,
return 1;
}
+/* Returns speed in Mbps. */
+int mlx5_lag_query_aggregated_speed(struct mlx5_core_dev *mdev, u32 *speed)
+{
+ struct mlx5_lag *ldev;
+ int ret = 0;
+
+ ldev = mlx5_lag_dev(mdev);
+ if (!ldev)
+ return -ENODEV;
+
+ mutex_lock(&ldev->lock);
+ *speed = ldev->agg_speed_mbps;
+ if (*speed == 0)
+ ret = -EINVAL;
+ mutex_unlock(&ldev->lock);
+
+ if (ret == -EINVAL)
+ mlx5_core_dbg(mdev, "aggregated speed is unknown\n");
+ return ret;
+}
+EXPORT_SYMBOL_GPL(mlx5_lag_query_aggregated_speed);
+
static void mlx5_lag_update_tracker_speed(struct lag_tracker *tracker,
struct net_device *ndev)
{
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h
index e9f0ef83ce1d..744fbf9a0078 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h
@@ -99,6 +99,7 @@ struct mlx5_lag {
/* Protect lag fields/state changes */
struct mutex lock;
struct lag_mpesw lag_mpesw;
+ u32 agg_speed_mbps;
};
static inline struct mlx5_lag *
@@ -258,12 +259,22 @@ void mlx5_lag_rescan_dev_locked(struct mlx5_lag *ldev,
void mlx5_lag_add_devices_filter(struct mlx5_lag *ldev, u32 filter);
struct mlx5_devcom_comp_dev *mlx5_lag_get_devcom_comp(struct mlx5_lag *ldev);
+void mlx5_lag_update_agg_speed(struct mlx5_lag *ldev);
+void mlx5_lag_reset_agg_speed(struct mlx5_lag *ldev);
+
#ifdef CONFIG_MLX5_ESWITCH
void mlx5_lag_set_vports_agg_speed(struct mlx5_lag *ldev);
void mlx5_lag_reset_vports_speed(struct mlx5_lag *ldev);
#else
-static inline void mlx5_lag_set_vports_agg_speed(struct mlx5_lag *ldev) {}
-static inline void mlx5_lag_reset_vports_speed(struct mlx5_lag *ldev) {}
+static inline void mlx5_lag_set_vports_agg_speed(struct mlx5_lag *ldev)
+{
+ mlx5_lag_update_agg_speed(ldev);
+}
+
+static inline void mlx5_lag_reset_vports_speed(struct mlx5_lag *ldev)
+{
+ mlx5_lag_reset_agg_speed(ldev);
+}
#endif
static inline bool mlx5_lag_is_supported(struct mlx5_core_dev *dev)
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index 83d0a83bbfbc..a83926689e9a 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -1155,6 +1155,7 @@ bool mlx5_lag_is_roce(struct mlx5_core_dev *dev);
bool mlx5_lag_is_sriov(struct mlx5_core_dev *dev);
bool mlx5_lag_is_active(struct mlx5_core_dev *dev);
int mlx5_lag_query_bond_speed(struct mlx5_core_dev *dev, u32 *speed);
+int mlx5_lag_query_aggregated_speed(struct mlx5_core_dev *dev, u32 *speed);
bool mlx5_lag_mode_is_hash(struct mlx5_core_dev *dev);
bool mlx5_lag_is_master(struct mlx5_core_dev *dev);
bool mlx5_lag_is_shared_fdb(struct mlx5_core_dev *dev);
--
2.44.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH net 4/5] net/mlx5: Lag, limit aggregated TX speed by PCIe bandwidth
2026-09-10 10:24 [PATCH net 0/5] net/mlx5: fixes for LAG max_tx_speed update flow Tariq Toukan
` (2 preceding siblings ...)
2026-09-10 10:24 ` [PATCH net 3/5] {RDMA,net}/mlx5: cache and use TX-enabled aggregate speed for vports Tariq Toukan
@ 2026-09-10 10:24 ` Tariq Toukan
2026-09-10 10:46 ` sashiko-bot
2026-09-10 10:24 ` [PATCH net 5/5] {RDMA,net}/mlx5: notify RoCE LAG speed change via driver event Tariq Toukan
4 siblings, 1 reply; 11+ messages in thread
From: Tariq Toukan @ 2026-09-10 10:24 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
netdev, Paolo Abeni
Cc: Edward Srouji, Gal Pressman, Jason Gunthorpe, Leon Romanovsky,
open list, linux-rdma, Maher Sanalla, Mark Bloch, Or Har-Toov,
Saeed Mahameed, Shay Drori, Tariq Toukan
From: Or Har-Toov <ohartoov@nvidia.com>
FW initializes max_tx_speed to the minimum of the port speed and the
PCI bandwidth. Modifying it with a value computed by different rules
changes the meaning of the field rather than updating it.
Limit each uplink's contribution to the aggregated LAG TX speed by the
NIC's PCIe bandwidth and reset max_tx_speed to the same value when lag
is torn down.
Fixes: 50f1d188c580 ("net/mlx5: Propagate LAG effective max_tx_speed to vports")
Signed-off-by: Or Har-Toov <ohartoov@nvidia.com>
Reviewed-by: Shay Drori <shayd@nvidia.com>
Reviewed-by: Mark Bloch <mbloch@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
---
drivers/net/ethernet/mellanox/mlx5/core/dev.c | 20 +++++++++++++++++++
.../net/ethernet/mellanox/mlx5/core/lag/lag.c | 12 +++++++++++
.../ethernet/mellanox/mlx5/core/mlx5_core.h | 1 +
3 files changed, 33 insertions(+)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/dev.c b/drivers/net/ethernet/mellanox/mlx5/core/dev.c
index df2e3ad01819..81f3dc3b8034 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/dev.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/dev.c
@@ -30,6 +30,7 @@
* SOFTWARE.
*/
+#include <linux/bitfield.h>
#include <linux/mlx5/driver.h>
#include <linux/mlx5/eswitch.h>
#include <linux/mlx5/mlx5_ifc_vdpa.h>
@@ -40,6 +41,25 @@
static DEFINE_IDA(mlx5_adev_ida);
+#define MLX5_PCIE_MIN_SPEED_MBPS (2500)
+
+u32 mlx5_pcie_bandwidth(struct mlx5_core_dev *dev)
+{
+ u16 lnksta;
+ int speed;
+ u32 width;
+
+ if (pcie_capability_read_word(dev->pdev, PCI_EXP_LNKSTA, &lnksta))
+ return 0;
+
+ width = FIELD_GET(PCI_EXP_LNKSTA_NLW, lnksta);
+ speed = pcie_link_speed_mbps(dev->pdev);
+ if (speed < MLX5_PCIE_MIN_SPEED_MBPS)
+ return 0;
+
+ return speed * width;
+}
+
static bool is_eth_rep_supported(struct mlx5_core_dev *dev)
{
if (!IS_ENABLED(CONFIG_MLX5_ESWITCH))
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
index 76b574fa0d7a..fd91becd6848 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
@@ -1418,6 +1418,7 @@ static int mlx5_lag_get_devices_oper_speed(struct mlx5_lag *ldev,
{
struct mlx5_core_dev *pf_mdev;
struct lag_func *pf;
+ u32 pci_bw;
int pf_idx;
bool mpesw;
u32 speed;
@@ -1452,6 +1453,9 @@ static int mlx5_lag_get_devices_oper_speed(struct mlx5_lag *ldev,
return ret;
}
+ pci_bw = mlx5_pcie_bandwidth(pf_mdev);
+ if (pci_bw)
+ speed = min(speed, pci_bw);
*sum_speed += speed;
}
@@ -1463,6 +1467,7 @@ static int mlx5_lag_get_devices_max_speed(struct mlx5_lag *ldev, u32 *max_speed)
struct mlx5_core_dev *pf_mdev;
struct lag_func *pf;
bool take_max;
+ u32 pci_bw;
int pf_idx;
u32 speed;
int ret;
@@ -1488,6 +1493,9 @@ static int mlx5_lag_get_devices_max_speed(struct mlx5_lag *ldev, u32 *max_speed)
return ret;
}
+ pci_bw = mlx5_pcie_bandwidth(pf_mdev);
+ if (pci_bw)
+ speed = min(speed, pci_bw);
*max_speed = take_max ?
max(*max_speed, speed) : *max_speed + speed;
}
@@ -1588,6 +1596,7 @@ void mlx5_lag_reset_vports_speed(struct mlx5_lag *ldev)
{
struct mlx5_core_dev *mdev;
struct lag_func *pf;
+ u32 pci_bw;
u32 speed;
int pf_idx;
int ret;
@@ -1609,6 +1618,9 @@ void mlx5_lag_reset_vports_speed(struct mlx5_lag *ldev)
continue;
}
+ pci_bw = mlx5_pcie_bandwidth(mdev);
+ if (pci_bw)
+ speed = min(speed, pci_bw);
speed = speed / MLX5_MAX_TX_SPEED_UNIT;
mlx5_lag_modify_device_vports_speed(mdev, speed);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
index d6713a2ce676..555842085daf 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
@@ -281,6 +281,7 @@ void mlx5_events_cleanup(struct mlx5_core_dev *dev);
void mlx5_events_start(struct mlx5_core_dev *dev);
void mlx5_events_stop(struct mlx5_core_dev *dev);
+u32 mlx5_pcie_bandwidth(struct mlx5_core_dev *dev);
int mlx5_adev_idx_alloc(void);
void mlx5_adev_idx_free(int idx);
void mlx5_adev_cleanup(struct mlx5_core_dev *dev);
--
2.44.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH net 5/5] {RDMA,net}/mlx5: notify RoCE LAG speed change via driver event
2026-09-10 10:24 [PATCH net 0/5] net/mlx5: fixes for LAG max_tx_speed update flow Tariq Toukan
` (3 preceding siblings ...)
2026-09-10 10:24 ` [PATCH net 4/5] net/mlx5: Lag, limit aggregated TX speed by PCIe bandwidth Tariq Toukan
@ 2026-09-10 10:24 ` Tariq Toukan
2026-09-10 10:46 ` sashiko-bot
4 siblings, 1 reply; 11+ messages in thread
From: Tariq Toukan @ 2026-09-10 10:24 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
netdev, Paolo Abeni
Cc: Edward Srouji, Gal Pressman, Jason Gunthorpe, Leon Romanovsky,
open list, linux-rdma, Maher Sanalla, Mark Bloch, Or Har-Toov,
Saeed Mahameed, Shay Drori, Tariq Toukan
From: Or Har-Toov <ohartoov@nvidia.com>
In RoCE LAG we don't modify any max_tx_speed, so no
IB_EVENT_DEVICE_SPEED_CHANGE is ever fired.
Raise IB_EVENT_DEVICE_SPEED_CHANGE from the LAG layer, in
mlx5_lag_update_agg_speed(), right after the cached aggregate is
updated. That cache is where the IB layer now takes the effective speed
from, so a consumer that queries after receiving the event is
guaranteed to read the new value.
Fixes: c6df9a65cbb0 ("net/mlx5: Skip disabled vports when setting max TX speed")
Signed-off-by: Or Har-Toov <ohartoov@nvidia.com>
Reviewed-by: Shay Drori <shayd@nvidia.com>
Reviewed-by: Mark Bloch <mbloch@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
---
drivers/infiniband/hw/mlx5/main.c | 10 ++++++++++
.../net/ethernet/mellanox/mlx5/core/lag/lag.c | 20 +++++++++++++++++++
.../net/ethernet/mellanox/mlx5/core/lag/lag.h | 1 +
include/linux/mlx5/device.h | 1 +
4 files changed, 32 insertions(+)
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index 6ab7f945e712..bd54af47eda7 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -3693,6 +3693,16 @@ static int lag_event(struct notifier_block *nb, unsigned long event, void *data)
rdma_roce_rescan_port(ibdev, portnum + 1);
}
break;
+ case MLX5_DRIVER_EVENT_LAG_SPEED_CHANGE: {
+ struct ib_event speed_event = {};
+
+ if (!dev->ib_active)
+ break;
+ speed_event.device = ibdev;
+ speed_event.event = IB_EVENT_DEVICE_SPEED_CHANGE;
+ ib_dispatch_event(&speed_event);
+ break;
+ }
default:
return NOTIFY_DONE;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
index fd91becd6848..5e70ca3b09ba 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
@@ -1503,8 +1503,24 @@ static int mlx5_lag_get_devices_max_speed(struct mlx5_lag *ldev, u32 *max_speed)
return 0;
}
+void mlx5_lag_notify_speed_change(struct mlx5_lag *ldev)
+{
+ struct lag_func *pf;
+ int idx;
+
+ idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
+ if (idx < 0)
+ return;
+ pf = mlx5_lag_pf(ldev, idx);
+ if (!pf)
+ return;
+ blocking_notifier_call_chain(&pf->dev->priv.lag_nh,
+ MLX5_DRIVER_EVENT_LAG_SPEED_CHANGE, NULL);
+}
+
void mlx5_lag_update_agg_speed(struct mlx5_lag *ldev)
{
+ u32 old_speed;
u32 speed;
lockdep_assert_held(&ldev->lock);
@@ -1516,7 +1532,11 @@ void mlx5_lag_update_agg_speed(struct mlx5_lag *ldev)
if (!speed && mlx5_lag_get_devices_max_speed(ldev, &speed))
return;
+ old_speed = ldev->agg_speed_mbps;
ldev->agg_speed_mbps = speed;
+
+ if (mlx5_lag_is_roce_lag(ldev) && speed != old_speed)
+ mlx5_lag_notify_speed_change(ldev);
}
void mlx5_lag_reset_agg_speed(struct mlx5_lag *ldev)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h
index 744fbf9a0078..2b15a0b70fdf 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h
@@ -259,6 +259,7 @@ void mlx5_lag_rescan_dev_locked(struct mlx5_lag *ldev,
void mlx5_lag_add_devices_filter(struct mlx5_lag *ldev, u32 filter);
struct mlx5_devcom_comp_dev *mlx5_lag_get_devcom_comp(struct mlx5_lag *ldev);
+void mlx5_lag_notify_speed_change(struct mlx5_lag *ldev);
void mlx5_lag_update_agg_speed(struct mlx5_lag *ldev);
void mlx5_lag_reset_agg_speed(struct mlx5_lag *ldev);
diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h
index 8cb321a9fb3d..1ec2331c24ee 100644
--- a/include/linux/mlx5/device.h
+++ b/include/linux/mlx5/device.h
@@ -374,6 +374,7 @@ enum mlx5_driver_event {
MLX5_DRIVER_EVENT_AFFILIATION_DONE,
MLX5_DRIVER_EVENT_AFFILIATION_REMOVED,
MLX5_DRIVER_EVENT_ACTIVE_BACKUP_LAG_CHANGE_LOWERSTATE,
+ MLX5_DRIVER_EVENT_LAG_SPEED_CHANGE,
};
enum {
--
2.44.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH net 2/5] net/mlx5: Lag, reset vport speed on teardown
2026-09-10 10:24 ` [PATCH net 2/5] net/mlx5: Lag, reset vport speed on teardown Tariq Toukan
@ 2026-09-10 10:46 ` sashiko-bot
0 siblings, 0 replies; 11+ messages in thread
From: sashiko-bot @ 2026-09-10 10:46 UTC (permalink / raw)
To: Tariq Toukan; +Cc: linux-rdma
> From: Or Har-Toov <ohartoov@nvidia.com>
>
> mlx5_lag_disable_mpesw() never resets the cached agg_max_tx_speed on
> the vports, unlike regular LAG teardown. This leaves stale speed values
> cached on struct mlx5_vport, and pushed to FW, after MPESW is torn
> down.
>
> Move the mlx5_lag_reset_vports_speed() call from mlx5_do_bond() into
> mlx5_deactivate_lag(), so that every teardown path resets the vport
> speeds.
>
> Fixes: 50f1d188c580 ("net/mlx5: Propagate LAG effective max_tx_speed to vports")
> Signed-off-by: Or Har-Toov <ohartoov@nvidia.com>
> Reviewed-by: Shay Drori <shayd@nvidia.com>
> Reviewed-by: Mark Bloch <mbloch@nvidia.com>
> Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260910102432.3845360-1-tariqt@nvidia.com?part=2
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH net 4/5] net/mlx5: Lag, limit aggregated TX speed by PCIe bandwidth
2026-09-10 10:24 ` [PATCH net 4/5] net/mlx5: Lag, limit aggregated TX speed by PCIe bandwidth Tariq Toukan
@ 2026-09-10 10:46 ` sashiko-bot
0 siblings, 0 replies; 11+ messages in thread
From: sashiko-bot @ 2026-09-10 10:46 UTC (permalink / raw)
To: Tariq Toukan; +Cc: linux-rdma
> From: Or Har-Toov <ohartoov@nvidia.com>
>
> FW initializes max_tx_speed to the minimum of the port speed and the
> PCI bandwidth. Modifying it with a value computed by different rules
> changes the meaning of the field rather than updating it.
>
> Limit each uplink's contribution to the aggregated LAG TX speed by the
> NIC's PCIe bandwidth and reset max_tx_speed to the same value when lag
> is torn down.
>
> Fixes: 50f1d188c580 ("net/mlx5: Propagate LAG effective max_tx_speed to vports")
> Signed-off-by: Or Har-Toov <ohartoov@nvidia.com>
> Reviewed-by: Shay Drori <shayd@nvidia.com>
> Reviewed-by: Mark Bloch <mbloch@nvidia.com>
> Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260910102432.3845360-1-tariqt@nvidia.com?part=4
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH net 3/5] {RDMA,net}/mlx5: cache and use TX-enabled aggregate speed for vports
2026-09-10 10:24 ` [PATCH net 3/5] {RDMA,net}/mlx5: cache and use TX-enabled aggregate speed for vports Tariq Toukan
@ 2026-09-10 10:46 ` sashiko-bot
0 siblings, 0 replies; 11+ messages in thread
From: sashiko-bot @ 2026-09-10 10:46 UTC (permalink / raw)
To: Tariq Toukan; +Cc: linux-rdma
> From: Or Har-Toov <ohartoov@nvidia.com>
>
> Cache aggregate TX-enabled speed we calculated, and use it instead of
> querying the bond speed so we can, in the following patch, limit it by
> the PCI bandwidth.
>
> The bond speed takes the calculation from PTYS, and PTYS is not bounded
> by the PCI bandwidth of the NIC.
>
> Fixes: 50f1d188c580 ("net/mlx5: Propagate LAG effective max_tx_speed to vports")
> Signed-off-by: Or Har-Toov <ohartoov@nvidia.com>
> Reviewed-by: Shay Drori <shayd@nvidia.com>
> Reviewed-by: Mark Bloch <mbloch@nvidia.com>
> Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260910102432.3845360-1-tariqt@nvidia.com?part=3
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH net 5/5] {RDMA,net}/mlx5: notify RoCE LAG speed change via driver event
2026-09-10 10:24 ` [PATCH net 5/5] {RDMA,net}/mlx5: notify RoCE LAG speed change via driver event Tariq Toukan
@ 2026-09-10 10:46 ` sashiko-bot
0 siblings, 0 replies; 11+ messages in thread
From: sashiko-bot @ 2026-09-10 10:46 UTC (permalink / raw)
To: Tariq Toukan; +Cc: linux-rdma
> From: Or Har-Toov <ohartoov@nvidia.com>
>
> In RoCE LAG we don't modify any max_tx_speed, so no
> IB_EVENT_DEVICE_SPEED_CHANGE is ever fired.
>
> Raise IB_EVENT_DEVICE_SPEED_CHANGE from the LAG layer, in
> mlx5_lag_update_agg_speed(), right after the cached aggregate is
> updated. That cache is where the IB layer now takes the effective speed
> from, so a consumer that queries after receiving the event is
> guaranteed to read the new value.
>
> Fixes: c6df9a65cbb0 ("net/mlx5: Skip disabled vports when setting max TX speed")
> Signed-off-by: Or Har-Toov <ohartoov@nvidia.com>
> Reviewed-by: Shay Drori <shayd@nvidia.com>
> Reviewed-by: Mark Bloch <mbloch@nvidia.com>
> Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260910102432.3845360-1-tariqt@nvidia.com?part=5
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH net 1/5] net/mlx5: Lag, split aggregate speed into oper and max helpers
2026-09-10 10:24 ` [PATCH net 1/5] net/mlx5: Lag, split aggregate speed into oper and max helpers Tariq Toukan
@ 2026-09-10 10:46 ` sashiko-bot
0 siblings, 0 replies; 11+ messages in thread
From: sashiko-bot @ 2026-09-10 10:46 UTC (permalink / raw)
To: Tariq Toukan; +Cc: linux-rdma
> From: Or Har-Toov <ohartoov@nvidia.com>
>
> Split mlx5_lag_sum_devices_speed into mlx5_lag_get_devices_oper_speed
> and mlx5_lag_get_devices_max_speed. The oper function reflects only
> the speed currently available and the max function is state-independent
> and represents the maximum achievable speed, taking the best single
> port for active-backup and summing all ports for XOR, LACP and MPESW.
>
> The oper function skips a port for two reasons:
> - the bonding driver set tx_enabled=false - LACP converging or
> active-backup standby slave, where carrier may still be up but the
> port is intentionally not forwarding traffic.
> - the link is down.
>
> Fixes: 50f1d188c580 ("net/mlx5: Propagate LAG effective max_tx_speed to vports")
> Signed-off-by: Or Har-Toov <ohartoov@nvidia.com>
> Reviewed-by: Shay Drori <shayd@nvidia.com>
> Reviewed-by: Mark Bloch <mbloch@nvidia.com>
> Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260910102432.3845360-1-tariqt@nvidia.com?part=1
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2026-09-10 10:46 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-10 10:24 [PATCH net 0/5] net/mlx5: fixes for LAG max_tx_speed update flow Tariq Toukan
2026-09-10 10:24 ` [PATCH net 1/5] net/mlx5: Lag, split aggregate speed into oper and max helpers Tariq Toukan
2026-09-10 10:46 ` sashiko-bot
2026-09-10 10:24 ` [PATCH net 2/5] net/mlx5: Lag, reset vport speed on teardown Tariq Toukan
2026-09-10 10:46 ` sashiko-bot
2026-09-10 10:24 ` [PATCH net 3/5] {RDMA,net}/mlx5: cache and use TX-enabled aggregate speed for vports Tariq Toukan
2026-09-10 10:46 ` sashiko-bot
2026-09-10 10:24 ` [PATCH net 4/5] net/mlx5: Lag, limit aggregated TX speed by PCIe bandwidth Tariq Toukan
2026-09-10 10:46 ` sashiko-bot
2026-09-10 10:24 ` [PATCH net 5/5] {RDMA,net}/mlx5: notify RoCE LAG speed change via driver event Tariq Toukan
2026-09-10 10:46 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox