[PATCH net 5/5] {RDMA,net}/mlx5: notify RoCE LAG speed change via driver event
From: Tariq Toukan
Date: Thu Sep 10 2026 - 06:41:04 EST
From: Or Har-Toov <ohartoov@xxxxxxxxxx>
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@xxxxxxxxxx>
Reviewed-by: Shay Drori <shayd@xxxxxxxxxx>
Reviewed-by: Mark Bloch <mbloch@xxxxxxxxxx>
Signed-off-by: Tariq Toukan <tariqt@xxxxxxxxxx>
---
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