[PATCH net-next 01/15] net/mlx5: Distinguish VFs/SFs in the SW system image GUID for LAG grouping

From
Tariq Toukan <tariqt@nvidia.com>
Date
2026-11-03 17:11:04
Also in
linux-rdma, lkml
Reply to
Tariq Toukan, 2026-11-03
From: Shay Drory <redacted>

mlx5_query_nic_sw_system_image_guid() builds the key used to group
devices that may form a LAG. A PF and its VFs/SFs share the same FW
system image GUID, so without a discriminator a VF/SF that can join a
virt LAG would be grouped with its PF.

Appending bare discriminator bytes at conditional offsets is not enough:
distinct capability sets can collapse to the same key (a PF ending in a
load_balance byte of 0x01 vs a VF whose marker is 0x01). Give each
discriminator a fixed position instead, and add the VF and SF as such
fields. Trailing zero fields are trimmed, so keys of devices that set
none of the new fields are unchanged.

Set the VF/SF markers only when mlx5_virt_lag_is_supported(). The same
key also backs mlx5_same_hw_devs(), so a VF/SF that cannot join a virt
LAG keeps its current key and is still identified as the same HW as its
PF.

Signed-off-by: Shay Drory <redacted>
Reviewed-by: Mark Bloch <mbloch@nvidia.com>
Reviewed-by: Moshe Shemesh <redacted>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
---
 .../net/ethernet/mellanox/mlx5/core/lag/lag.h |  9 ++++
 .../net/ethernet/mellanox/mlx5/core/vport.c   | 41 +++++++++++++++++--
 include/linux/mlx5/driver.h                   |  2 +-
 3 files changed, 48 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h
index 8552792b9035..0ff337983a6d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h
@@ -266,6 +266,15 @@ 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) {}
 #endif
 
+static inline bool mlx5_virt_lag_is_supported(const struct mlx5_core_dev *dev)
+{
+	if (!MLX5_CAP_GEN(dev, multi_uplink_eswitch) ||
+	    !MLX5_CAP_GEN(dev, lag_master) ||
+	    MLX5_CAP_GEN(dev, num_lag_ports) >= 2)
+		return false;
+	return true;
+}
+
 static inline bool mlx5_lag_is_supported(struct mlx5_core_dev *dev)
 {
 	if (!MLX5_CAP_GEN(dev, vport_group_manager) ||
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/vport.c b/drivers/net/ethernet/mellanox/mlx5/core/vport.c
index 78f3d15b599d..50d2609374c4 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/vport.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/vport.c
@@ -38,6 +38,7 @@
 #include "mlx5_core.h"
 #include "eswitch.h"
 #include "sf/sf.h"
+#include "lag/lag.h"
 
 /* Mutex to hold while enabling or disabling RoCE */
 static DEFINE_MUTEX(mlx5_roce_en_lock);
@@ -1308,10 +1309,37 @@ u64 mlx5_query_nic_system_image_guid(struct mlx5_core_dev *mdev)
 }
 EXPORT_SYMBOL_GPL(mlx5_query_nic_system_image_guid);
 
+static u8 mlx5_sw_guid_load_balance(const struct mlx5_core_dev *mdev)
+{
+	if (MLX5_CAP_GEN_2(mdev, load_balance_id) &&
+	    MLX5_CAP_GEN_2(mdev, lag_per_mp_group))
+		return MLX5_CAP_GEN_2(mdev, load_balance_id);
+	return 0;
+}
+
+static u8 mlx5_sw_guid_sf(const struct mlx5_core_dev *mdev)
+{
+	return mlx5_core_is_sf(mdev) && mlx5_virt_lag_is_supported(mdev);
+}
+
+static u8 mlx5_sw_guid_vf(const struct mlx5_core_dev *mdev)
+{
+	return mlx5_core_is_vf(mdev) && mlx5_virt_lag_is_supported(mdev);
+}
+
+static u8 (* const mlx5_sw_guid_fields[])(const struct mlx5_core_dev *mdev) = {
+	mlx5_sw_guid_load_balance,
+	mlx5_sw_guid_vf,
+	mlx5_sw_guid_sf,
+	/* New fields should be added at the end */
+};
+
 void mlx5_query_nic_sw_system_image_guid(struct mlx5_core_dev *mdev, u8 *buf,
 					 u8 *len)
 {
 	u64 fw_system_image_guid;
+	u8 trim_len;
+	int i;
 
 	*len = 0;
 
@@ -1321,10 +1349,17 @@ void mlx5_query_nic_sw_system_image_guid(struct mlx5_core_dev *mdev, u8 *buf,
 
 	memcpy(buf, &fw_system_image_guid, sizeof(fw_system_image_guid));
 	*len += sizeof(fw_system_image_guid);
+	trim_len = *len;
 
-	if (MLX5_CAP_GEN_2(mdev, load_balance_id) &&
-	    MLX5_CAP_GEN_2(mdev, lag_per_mp_group))
-		buf[(*len)++] = MLX5_CAP_GEN_2(mdev, load_balance_id);
+	for (i = 0; i < ARRAY_SIZE(mlx5_sw_guid_fields); i++) {
+		u8 val = mlx5_sw_guid_fields[i](mdev);
+
+		buf[(*len)++] = val;
+		if (val)
+			trim_len = *len;
+	}
+
+	*len = trim_len;
 }
 
 bool mlx5_vport_use_vhca_id_as_func_id(struct mlx5_core_dev *dev,
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index abb99371ff13..d9d91faa0a1d 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -1395,7 +1395,7 @@ static inline struct net *mlx5_core_net(struct mlx5_core_dev *dev)
 	return devlink_net(priv_to_devlink(dev));
 }
 
-#define MLX5_SW_IMAGE_GUID_MAX_BYTES 9
+#define MLX5_SW_IMAGE_GUID_MAX_BYTES 11
 
 static inline bool mlx5_data_direct_supported(struct mlx5_core_dev *mdev)
 {
-- 
2.44.0
Thread (16 messages) 16 messages, 1 author, last reply 1d ago
Keyboard shortcuts
hback out one level
jnext message in thread / next series-diff position
kprevious message in thread / previous series-diff position
ldrill in
Escclose help / fold thread tree
?toggle this help