DPDK-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Dariusz Sosnowski <dsosnowski@nvidia.com>
To: Viacheslav Ovsiienko <viacheslavo@nvidia.com>,
	Bing Zhao <bingz@nvidia.com>, Ori Kam <orika@nvidia.com>,
	Suanming Mou <suanmingm@nvidia.com>,
	Matan Azrad <matan@nvidia.com>
Cc: <dev@dpdk.org>
Subject: [PATCH 12/13] net/mlx5: allow associated devices
Date: Mon, 26 Oct 2026 17:27:08 +0100	[thread overview]
Message-ID: <20261026162709.1292958-13-dsosnowski@nvidia.com> (raw)
In-Reply-To: <20261026162709.1292958-1-dsosnowski@nvidia.com>

Allow probing mlx5 networking devices using multiple rte_device's,
which are associated with single mlx5 common device.
This requires a few changes in probing:

- When going through list of IB devices to check for MPESW
  or bond setups, use owner IB device from common device,
  not the probed device.
- When preparing data for a list of spawned ports,
  keep "probed device" and "owner device" separate.
- Use the name of "probed device" when
  ethdev port name is constructed.
- Any device related to VIRTUAL devlink port,
  which is not an E-Switch owner should be accepted
  as a representor port. Representor devarg is not required.

Patch also extends mlx5_nl_check_switch_info() to query
the flavour of related devlink port if phys_port_name is not available.

As of this patch, probing through associated devices
is only allowed for PCI devices.

Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
Acked-by: Viacheslav Ovsiienko <viacheslavo@nvidia.com>
---
 drivers/common/mlx5/linux/mlx5_nl.c |  95 +++++++++++++++++++++++-
 drivers/common/mlx5/linux/mlx5_nl.h |   4 +-
 drivers/common/mlx5/mlx5_common.h   |   5 ++
 drivers/net/mlx5/linux/mlx5_os.c    | 109 +++++++++++++++++++++-------
 drivers/net/mlx5/mlx5.c             |   3 +-
 drivers/net/mlx5/mlx5.h             |   1 +
 drivers/net/mlx5/mlx5_ethdev.c      |  13 +++-
 drivers/net/mlx5/mlx5_mac.c         |   6 +-
 8 files changed, 199 insertions(+), 37 deletions(-)

diff --git a/drivers/common/mlx5/linux/mlx5_nl.c b/drivers/common/mlx5/linux/mlx5_nl.c
index e57007831c..6a22476a15 100644
--- a/drivers/common/mlx5/linux/mlx5_nl.c
+++ b/drivers/common/mlx5/linux/mlx5_nl.c
@@ -1620,7 +1620,7 @@ mlx5_nl_devlink_port_info_get_cb(struct nlmsghdr *nh, void *arg)
 	return -rte_errno;
 }
 
-static int __rte_unused
+static int
 mlx5_nl_devlink_port_info_get(int nl, int family, struct mlx5_devlink_port_info *info)
 {
 	struct nlmsghdr *nlh;
@@ -1668,6 +1668,8 @@ mlx5_nl_devlink_port_info_get(int nl, int family, struct mlx5_devlink_port_info
  * Analyze gathered port parameters via Netlink to recognize master
  * and representor devices for E-Switch configuration.
  *
+ * @param[in] parent_dev_match
+ *   True if underlying netdev's parent device is the same as for IB device.
  * @param[in] num_vf_set
  *   flag of presence of number of VFs port attribute.
  * @param[inout] switch_info
@@ -1679,7 +1681,8 @@ mlx5_nl_devlink_port_info_get(int nl, int family, struct mlx5_devlink_port_info
  *   recognized parameters (if any).
  */
 static void
-mlx5_nl_check_switch_info(bool num_vf_set,
+mlx5_nl_check_switch_info(bool parent_dev_match,
+			  bool num_vf_set,
 			  struct mlx5_switch_info *switch_info)
 {
 	switch (switch_info->name_type) {
@@ -1714,12 +1717,67 @@ mlx5_nl_check_switch_info(bool num_vf_set,
 		/* New representors naming schema. */
 		switch_info->representor = 1;
 		break;
+	case MLX5_PHYS_PORT_NAME_TYPE_VIRTUAL:
+		switch_info->master = parent_dev_match;
+		switch_info->representor = !parent_dev_match;
+		break;
 	}
 }
 
+static void
+check_virtual_port(struct mlx5_netdev_info *netdev_info,
+		   struct mlx5_switch_info *switch_info)
+{
+	struct mlx5_devlink_port_info devlink_port_info = {
+		.bus_name = netdev_info->devlink_port_bus_name,
+		.dev_name = netdev_info->devlink_port_dev_name,
+		.index = netdev_info->devlink_port_index,
+	};
+	int nl;
+	int family;
+	int ret = 0;
+
+	nl = mlx5_nl_init(NETLINK_GENERIC, 0);
+	if (nl < 0) {
+		DRV_LOG(DEBUG, "Unable to open NETLINK_GENERIC socket");
+		return;
+	}
+
+	family = mlx5_nl_devlink_family_id_get(nl);
+	if (family < 0) {
+		DRV_LOG(DEBUG, "Unable to query devlink genetlink family ID");
+		goto exit_end;
+	}
+
+	if (mlx5_netdev_info_has_devlink_port(netdev_info)) {
+		ret = mlx5_nl_devlink_port_info_get(nl, family, &devlink_port_info);
+	} else {
+		/*
+		 * TODO: Kernel too old. Devlink port must be found by dumping all ports
+		 * and matching by netdev_ifindex. Until this is done, log unsupported.
+		 */
+		DRV_LOG(DEBUG, "Kernel does not expose IFLA_DEVLINK_PORT");
+		ret = -ENOTSUP;
+	}
+
+	if (ret < 0) {
+		DRV_LOG(DEBUG, "Unable to query devlink port flavour");
+		goto exit_end;
+	}
+
+	if ((devlink_port_info.flags & MLX5_DEVLINK_PORT_INFO_FLAG_FLAVOUR) &&
+	    devlink_port_info.flavour == MLX5_DEVLINK_PORT_FLAVOUR_VIRTUAL)
+		switch_info->name_type = MLX5_PHYS_PORT_NAME_TYPE_VIRTUAL;
+
+exit_end:
+	close(nl);
+}
+
 /**
  * Get switch information associated with network interface.
  *
+ * @param cdev
+ *   Pointer to common device.
  * @param nl
  *   Netlink socket of the ROUTE kind (NETLINK_ROUTE).
  * @param ifindex
@@ -1732,12 +1790,15 @@ mlx5_nl_check_switch_info(bool num_vf_set,
  */
 RTE_EXPORT_INTERNAL_SYMBOL(mlx5_nl_switch_info)
 int
-mlx5_nl_switch_info(int nl, unsigned int ifindex,
+mlx5_nl_switch_info(struct mlx5_common_device *cdev,
+		    int nl,
+		    unsigned int ifindex,
 		    struct mlx5_switch_info *info)
 {
 	struct mlx5_netdev_info netdev_info = {
 		.ifindex = ifindex,
 	};
+	bool parent_dev_match;
 	bool num_vf_set;
 	int ret;
 
@@ -1756,7 +1817,33 @@ mlx5_nl_switch_info(int nl, unsigned int ifindex,
 
 	if (netdev_info.flags & MLX5_NETDEV_INFO_FLAG_PHYS_SWITCH_ID) {
 		info->switch_id = netdev_info.phys_switch_id;
-		mlx5_nl_check_switch_info(num_vf_set, info);
+
+		if (info->name_type == MLX5_PHYS_PORT_NAME_TYPE_NOTSET)
+			check_virtual_port(&netdev_info, info);
+
+		/* Port type could be updated to virtual. Recheck. */
+		if (info->name_type == MLX5_PHYS_PORT_NAME_TYPE_VIRTUAL) {
+			if (!(netdev_info.flags & MLX5_NETDEV_INFO_FLAG_PARENT_DEV_NAME) ||
+			    !(netdev_info.flags & MLX5_NETDEV_INFO_FLAG_PARENT_DEV_BUS_NAME)) {
+				DRV_LOG(ERR, "ifindex %u cannot get parent dev", ifindex);
+				rte_errno = EINVAL;
+				return -rte_errno;
+			}
+
+			strlcpy(info->parent_dev_bus_name, netdev_info.parent_dev_bus_name,
+				sizeof(info->parent_dev_bus_name));
+			strlcpy(info->parent_dev_name, netdev_info.parent_dev_name,
+				sizeof(info->parent_dev_name));
+
+			parent_dev_match = mlx5_dev_matches(cdev->dev,
+							    netdev_info.parent_dev_bus_name,
+							    netdev_info.parent_dev_name);
+		} else {
+			/* Irrelevant for other port flavours. */
+			parent_dev_match = false;
+		}
+
+		mlx5_nl_check_switch_info(parent_dev_match, num_vf_set, info);
 	}
 
 	if (info->master && info->representor) {
diff --git a/drivers/common/mlx5/linux/mlx5_nl.h b/drivers/common/mlx5/linux/mlx5_nl.h
index 0a9aab6610..7663864e56 100644
--- a/drivers/common/mlx5/linux/mlx5_nl.h
+++ b/drivers/common/mlx5/linux/mlx5_nl.h
@@ -144,7 +144,9 @@ __rte_internal
 int mlx5_nl_vf_mac_addr_modify(int nlsk_fd, unsigned int iface_idx,
 			       struct rte_ether_addr *mac, int vf_index);
 __rte_internal
-int mlx5_nl_switch_info(int nl, unsigned int ifindex,
+int mlx5_nl_switch_info(struct mlx5_common_device *cdev,
+			int nl,
+			unsigned int ifindex,
 			struct mlx5_switch_info *info);
 
 __rte_internal
diff --git a/drivers/common/mlx5/mlx5_common.h b/drivers/common/mlx5/mlx5_common.h
index 548f0c887b..fb73b3a038 100644
--- a/drivers/common/mlx5/mlx5_common.h
+++ b/drivers/common/mlx5/mlx5_common.h
@@ -152,6 +152,7 @@ enum mlx5_nl_phys_port_name_type {
 	MLX5_PHYS_PORT_NAME_TYPE_PFVF, /* pf0vf0, kernel ver >= 5.0 */
 	MLX5_PHYS_PORT_NAME_TYPE_PFHPF, /* pf0, kernel ver >= 5.7, HPF rep */
 	MLX5_PHYS_PORT_NAME_TYPE_PFSF, /* pf0sf0, kernel ver >= 5.0 */
+	MLX5_PHYS_PORT_NAME_TYPE_VIRTUAL, /* Virtual devlink port. */
 	MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN, /* Unrecognized. */
 };
 
@@ -169,6 +170,8 @@ struct mlx5_dev_info {
 	struct mlx5_port_nl_info *port_info;
 };
 
+#define MLX5_SWITCH_INFO_PARENT_DEV_NAME_MAX (128)
+
 /** Switch information returned by mlx5_nl_switch_info(). */
 struct mlx5_switch_info {
 	uint32_t master:1; /**< Master device. */
@@ -179,6 +182,8 @@ struct mlx5_switch_info {
 	int32_t port_name; /**< Representor port name. */
 	int32_t mpesw_owner; /**< MPESW owner port number. */
 	uint64_t switch_id; /**< Switch identifier. */
+	char parent_dev_bus_name[MLX5_SWITCH_INFO_PARENT_DEV_NAME_MAX];
+	char parent_dev_name[MLX5_SWITCH_INFO_PARENT_DEV_NAME_MAX];
 };
 
 /* CQE status. */
diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c
index 1b1b1bb013..83c9774443 100644
--- a/drivers/net/mlx5/linux/mlx5_os.c
+++ b/drivers/net/mlx5/linux/mlx5_os.c
@@ -1122,6 +1122,9 @@ build_port_name(struct rte_device *dpdk_dev,
 		written += ret;
 		if (written >= (int)name_sz)
 			return written;
+	} else if (spawn->info.name_type == MLX5_PHYS_PORT_NAME_TYPE_VIRTUAL) {
+		/* All relevant information was put in the name. Finish here. */
+		goto end;
 	} else if (spawn->info.representor) {
 		/*
 		 * If port is a representor, then switchdev has been enabled.
@@ -1249,6 +1252,13 @@ mlx5_representor_match(struct mlx5_dev_spawn_data *spawn,
 	bool ignore_ctrl_num = eth_da->nb_mh_controllers == 0 ||
 			       switch_info->name_type == MLX5_PHYS_PORT_NAME_TYPE_UPLINK;
 
+	/*
+	 * Representor on virtual devlink port always match.
+	 * Probing logic filters out unwanted ports before mlx5_dev_spawn() is reached.
+	 */
+	if (switch_info->name_type == MLX5_PHYS_PORT_NAME_TYPE_VIRTUAL)
+		return true;
+
 	switch (eth_da->type) {
 	case RTE_ETH_REPRESENTOR_PF:
 		if (switch_info->name_type != MLX5_PHYS_PORT_NAME_TYPE_UPLINK) {
@@ -1299,8 +1309,6 @@ mlx5_representor_match(struct mlx5_dev_spawn_data *spawn,
 /**
  * Spawn an Ethernet device from Verbs information.
  *
- * @param dpdk_dev
- *   Backing DPDK device.
  * @param spawn
  *   Verbs device parameters (name, port, switch_info) to spawn.
  * @param eth_da
@@ -1316,11 +1324,11 @@ mlx5_representor_match(struct mlx5_dev_spawn_data *spawn,
  *   EEXIST: device is already spawned
  */
 static struct rte_eth_dev *
-mlx5_dev_spawn(struct rte_device *dpdk_dev,
-	       struct mlx5_dev_spawn_data *spawn,
+mlx5_dev_spawn(struct mlx5_dev_spawn_data *spawn,
 	       struct rte_eth_devargs *eth_da,
 	       struct mlx5_kvargs_ctrl *mkvlist)
 {
+	struct rte_device *dpdk_dev = spawn->dpdk_dev;
 	const struct mlx5_switch_info *switch_info = &spawn->info;
 	struct mlx5_dev_ctx_shared *sh = NULL;
 	struct ibv_port_attr port_attr = { .state = IBV_PORT_NOP };
@@ -2477,6 +2485,7 @@ calc_nb_uplinks_hpfs(struct ibv_device **ibv_match,
  */
 static int
 mlx5_os_pci_probe_pf(struct mlx5_common_device *cdev,
+		     struct rte_device *dev,
 		     struct rte_eth_devargs *req_eth_da,
 		     uint16_t owner_id, struct mlx5_kvargs_ctrl *mkvlist)
 {
@@ -2511,13 +2520,22 @@ mlx5_os_pci_probe_pf(struct mlx5_common_device *cdev,
 	 *  >= 0 - MPESW device. Value is the port index of the MPESW owner.
 	 */
 	int mpesw = MLX5_MPESW_PORT_INVALID;
-	struct rte_pci_device *pci_dev = RTE_BUS_DEVICE(cdev->dev, *pci_dev);
+	struct rte_pci_device *owner_pci_dev;
 	struct mlx5_dev_spawn_data *list = NULL;
 	struct rte_eth_devargs eth_da = *req_eth_da;
-	struct rte_pci_addr owner_pci = pci_dev->addr; /* Owner PF. */
+	struct rte_pci_addr owner_pci; /* Owner PF. */
 	struct mlx5_bond_info bond_info;
 	int ret = -1;
 
+	if (!mlx5_dev_is_pci(cdev->dev)) {
+		DRV_LOG(ERR, "Owner device is not PCI: dev %s owner %s",
+			dev->name, cdev->dev->name);
+		rte_errno = EINVAL;
+		return -rte_errno;
+	}
+	owner_pci_dev = RTE_BUS_DEVICE(cdev->dev, *owner_pci_dev);
+	owner_pci = owner_pci_dev->addr;
+
 	errno = 0;
 	ibv_list = mlx5_glue->get_device_list(&ret);
 	if (!ibv_list) {
@@ -2699,8 +2717,9 @@ mlx5_os_pci_probe_pf(struct mlx5_common_device *cdev,
 			list[ns].phys_port = i;
 			list[ns].phys_dev_name = ibv_match[0]->name;
 			list[ns].eth_dev = NULL;
-			list[ns].pci_dev = pci_dev;
+			list[ns].pci_dev = owner_pci_dev;
 			list[ns].cdev = cdev;
+			list[ns].dpdk_dev = dev;
 			list[ns].pf_bond = bd;
 			list[ns].mpesw_port = MLX5_MPESW_PORT_INVALID;
 			list[ns].ifindex = mlx5_nl_ifindex(nl_rdma,
@@ -2718,7 +2737,7 @@ mlx5_os_pci_probe_pf(struct mlx5_common_device *cdev,
 			}
 			ret = -1;
 			if (nl_route >= 0)
-				ret = mlx5_nl_switch_info(nl_route,
+				ret = mlx5_nl_switch_info(cdev, nl_route,
 							  list[ns].ifindex,
 							  &list[ns].info);
 			if (ret || (!list[ns].info.representor &&
@@ -2731,6 +2750,11 @@ mlx5_os_pci_probe_pf(struct mlx5_common_device *cdev,
 				ret = mlx5_sysfs_switch_info(list[ns].ifindex,
 							     &list[ns].info);
 			}
+			/* Allow usage of associated devices only for VIRTUAL devlink ports. */
+			if (!ret &&
+			    list[ns].info.name_type != MLX5_PHYS_PORT_NAME_TYPE_VIRTUAL &&
+			    cdev->dev != dev)
+				continue;
 			if (!ret && bd >= 0) {
 				switch (list[ns].info.name_type) {
 				case MLX5_PHYS_PORT_NAME_TYPE_UPLINK:
@@ -2790,13 +2814,26 @@ mlx5_os_pci_probe_pf(struct mlx5_common_device *cdev,
 					list[ns].info.mpesw_owner = mpesw;
 					ns++;
 					break;
+				case MLX5_PHYS_PORT_NAME_TYPE_VIRTUAL:
+					list[ns].mpesw_port = mpesw;
+					list[ns].info.mpesw_owner = mpesw;
+					/* Spawn the device if and only if it matches. */
+					if (mlx5_dev_matches(list[ns].dpdk_dev,
+							     list[ns].info.parent_dev_bus_name,
+							     list[ns].info.parent_dev_name))
+						ns++;
+					break;
 				default:
 					break;
 				}
 				continue;
 			}
-			if (!ret && (list[ns].info.representor ^
-				     list[ns].info.master))
+			if (!ret && list[ns].info.name_type == MLX5_PHYS_PORT_NAME_TYPE_VIRTUAL) {
+				if (mlx5_dev_matches(list[ns].dpdk_dev,
+						     list[ns].info.parent_dev_bus_name,
+						     list[ns].info.parent_dev_name))
+					ns++;
+			} else if (!ret && (list[ns].info.representor ^ list[ns].info.master))
 				ns++;
 		}
 	} else {
@@ -2824,8 +2861,9 @@ mlx5_os_pci_probe_pf(struct mlx5_common_device *cdev,
 			list[ns].phys_port = 1;
 			list[ns].phys_dev_name = ibv_match[i]->name;
 			list[ns].eth_dev = NULL;
-			list[ns].pci_dev = pci_dev;
+			list[ns].pci_dev = owner_pci_dev;
 			list[ns].cdev = cdev;
+			list[ns].dpdk_dev = dev;
 			list[ns].pf_bond = -1;
 			list[ns].mpesw_port = MLX5_MPESW_PORT_INVALID;
 			list[ns].ifindex = 0;
@@ -2872,7 +2910,7 @@ mlx5_os_pci_probe_pf(struct mlx5_common_device *cdev,
 			}
 			ret = -1;
 			if (nl_route >= 0)
-				ret = mlx5_nl_switch_info(nl_route,
+				ret = mlx5_nl_switch_info(cdev, nl_route,
 							  list[ns].ifindex,
 							  &list[ns].info);
 			if (ret || (!list[ns].info.representor &&
@@ -2885,6 +2923,11 @@ mlx5_os_pci_probe_pf(struct mlx5_common_device *cdev,
 				ret = mlx5_sysfs_switch_info(list[ns].ifindex,
 							     &list[ns].info);
 			}
+			/* Allow usage of associated devices only for VIRTUAL devlink ports. */
+			if (!ret &&
+			    list[ns].info.name_type != MLX5_PHYS_PORT_NAME_TYPE_VIRTUAL &&
+			    cdev->dev != dev)
+				continue;
 			if (!ret && (list[ns].info.representor ^
 				     list[ns].info.master)) {
 				ns++;
@@ -2921,7 +2964,12 @@ mlx5_os_pci_probe_pf(struct mlx5_common_device *cdev,
 			list[0].info.representor = 0;
 		}
 	}
-	MLX5_ASSERT(ns);
+	if (ns == 0) {
+		DRV_LOG(ERR, "Unable to match any IB port to probed device");
+		rte_errno = ENOENT;
+		ret = -rte_errno;
+		goto exit;
+	}
 	/* Calculate number of uplinks and host PFs for each matched IB device. */
 	calc_nb_uplinks_hpfs(ibv_match, nd, list, ns);
 	/*
@@ -2934,7 +2982,7 @@ mlx5_os_pci_probe_pf(struct mlx5_common_device *cdev,
 		if (eth_da.nb_ports == 0 && ns > 0) {
 			if (list[0].pf_bond >= 0 && list[0].info.representor)
 				DRV_LOG(WARNING, "Representor on Bonding device should use pf#vf# syntax: %s",
-					pci_dev->device.devargs->args);
+					dev->devargs->args);
 			eth_da.nb_ports = 1;
 			eth_da.ports[0] = list[0].info.port_name;
 		}
@@ -2946,8 +2994,7 @@ mlx5_os_pci_probe_pf(struct mlx5_common_device *cdev,
 	for (i = 0; i != ns; ++i) {
 		uint32_t restore;
 
-		list[i].eth_dev = mlx5_dev_spawn(cdev->dev, &list[i], &eth_da,
-						 mkvlist);
+		list[i].eth_dev = mlx5_dev_spawn(&list[i], &eth_da, mkvlist);
 		if (!list[i].eth_dev) {
 			if (rte_errno != EBUSY && rte_errno != EEXIST)
 				break;
@@ -2955,7 +3002,7 @@ mlx5_os_pci_probe_pf(struct mlx5_common_device *cdev,
 			continue;
 		}
 		restore = list[i].eth_dev->data->dev_flags;
-		rte_eth_copy_pci_info(list[i].eth_dev, pci_dev);
+		rte_eth_copy_pci_info(list[i].eth_dev, list[i].pci_dev);
 		/**
 		 * Each representor has a dedicated interrupts vector.
 		 * rte_eth_copy_pci_info() assigns PF interrupts handle to
@@ -3070,21 +3117,22 @@ mlx5_os_parse_eth_devargs(struct rte_device *dev,
  */
 static int
 mlx5_os_pci_probe(struct mlx5_common_device *cdev,
+		  struct rte_device *dev,
 		  struct mlx5_kvargs_ctrl *mkvlist)
 {
-	struct rte_pci_device *pci_dev = RTE_BUS_DEVICE(cdev->dev, *pci_dev);
+	struct rte_pci_device *pci_dev = RTE_BUS_DEVICE(dev, *pci_dev);
 	struct rte_eth_devargs eth_da = { .nb_ports = 0 };
 	int ret = 0;
 	uint16_t p;
 
-	ret = mlx5_os_parse_eth_devargs(cdev->dev, &eth_da);
+	ret = mlx5_os_parse_eth_devargs(dev, &eth_da);
 	if (ret != 0)
 		return ret;
 
 	if (eth_da.nb_ports > 0) {
 		/* Iterate all port if devargs pf is range: "pf[0-1]vf[...]". */
 		for (p = 0; p < eth_da.nb_ports; p++) {
-			ret = mlx5_os_pci_probe_pf(cdev, &eth_da,
+			ret = mlx5_os_pci_probe_pf(cdev, dev, &eth_da,
 						   eth_da.ports[p], mkvlist);
 			if (ret) {
 				DRV_LOG(INFO, "Probe of PCI device " PCI_PRI_FMT " "
@@ -3098,7 +3146,7 @@ mlx5_os_pci_probe(struct mlx5_common_device *cdev,
 			}
 		}
 	} else {
-		ret = mlx5_os_pci_probe_pf(cdev, &eth_da, 0, mkvlist);
+		ret = mlx5_os_pci_probe_pf(cdev, dev, &eth_da, 0, mkvlist);
 	}
 	return ret;
 }
@@ -3106,6 +3154,7 @@ mlx5_os_pci_probe(struct mlx5_common_device *cdev,
 /* Probe a single SF device on auxiliary bus, no representor support. */
 static int
 mlx5_os_auxiliary_probe(struct mlx5_common_device *cdev,
+			struct rte_device *dev,
 			struct mlx5_kvargs_ctrl *mkvlist)
 {
 	struct rte_eth_devargs eth_da = { .nb_ports = 0 };
@@ -3113,11 +3162,16 @@ mlx5_os_auxiliary_probe(struct mlx5_common_device *cdev,
 		.pf_bond = -1,
 		.mpesw_port = MLX5_MPESW_PORT_INVALID,
 	};
-	struct rte_device *dev = cdev->dev;
 	struct rte_auxiliary_device *adev = RTE_BUS_DEVICE(dev, *adev);
 	struct rte_eth_dev *eth_dev;
 	int ret = 0;
 
+	if (cdev->dev != dev) {
+		DRV_LOG(ERR, "Invalid device %s used to probe common device %s",
+			dev->name, cdev->dev->name);
+		rte_errno = EINVAL;
+		return -rte_errno;
+	}
 	/* Parse ethdev devargs. */
 	ret = mlx5_os_parse_eth_devargs(dev, &eth_da);
 	if (ret != 0)
@@ -3133,8 +3187,9 @@ mlx5_os_auxiliary_probe(struct mlx5_common_device *cdev,
 	}
 	spawn.ifindex = ret;
 	spawn.cdev = cdev;
+	spawn.dpdk_dev = dev;
 	/* Spawn device. */
-	eth_dev = mlx5_dev_spawn(dev, &spawn, &eth_da, mkvlist);
+	eth_dev = mlx5_dev_spawn(&spawn, &eth_da, mkvlist);
 	if (eth_dev == NULL)
 		return -rte_errno;
 	/* Post create. */
@@ -3165,7 +3220,7 @@ mlx5_os_auxiliary_probe(struct mlx5_common_device *cdev,
  */
 int
 mlx5_os_net_probe(struct mlx5_common_device *cdev,
-		  struct rte_device *dev __rte_unused,
+		  struct rte_device *dev,
 		  struct mlx5_kvargs_ctrl *mkvlist)
 {
 	int ret;
@@ -3184,10 +3239,10 @@ mlx5_os_net_probe(struct mlx5_common_device *cdev,
 			strerror(rte_errno));
 		return -rte_errno;
 	}
-	if (mlx5_dev_is_pci(cdev->dev))
-		return mlx5_os_pci_probe(cdev, mkvlist);
+	if (mlx5_dev_is_pci(dev))
+		return mlx5_os_pci_probe(cdev, dev, mkvlist);
 	else
-		return mlx5_os_auxiliary_probe(cdev, mkvlist);
+		return mlx5_os_auxiliary_probe(cdev, dev, mkvlist);
 }
 
 /**
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 615b2ff943..9dc3402e22 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -3881,7 +3881,7 @@ mlx5_net_remove(struct mlx5_common_device *cdev)
 	uint16_t port_id;
 	int ret = 0;
 
-	RTE_ETH_FOREACH_DEV_OF(port_id, cdev->dev) {
+	MLX5_ETH_FOREACH_SIBLING(port_id, cdev) {
 		/*
 		 * mlx5_dev_close() is not registered to secondary process,
 		 * call the close function explicitly for secondary process.
@@ -3999,6 +3999,7 @@ static struct mlx5_class_driver mlx5_net_driver = {
 	.probe = mlx5_os_net_probe,
 	.remove = mlx5_net_remove,
 	.probe_again = 1,
+	.probe_associated = 1,
 	.intr_lsc = 1,
 	.intr_rmv = 1,
 };
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index e4ebdd4c2f..de969c0b2e 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -234,6 +234,7 @@ struct mlx5_dev_spawn_data {
 	const char *phys_dev_name; /**< Name of physical device. */
 	struct rte_eth_dev *eth_dev; /**< Associated Ethernet device. */
 	struct rte_pci_device *pci_dev; /**< Backend PCI device. */
+	struct rte_device *dpdk_dev; /**< Backend DPDK device. */
 	struct mlx5_common_device *cdev; /**< Backend common device. */
 	struct mlx5_bond_info *bond_info;
 };
diff --git a/drivers/net/mlx5/mlx5_ethdev.c b/drivers/net/mlx5/mlx5_ethdev.c
index f41724725c..115b67ffdf 100644
--- a/drivers/net/mlx5/mlx5_ethdev.c
+++ b/drivers/net/mlx5/mlx5_ethdev.c
@@ -472,6 +472,8 @@ mlx5_representor_id_encode(const struct mlx5_switch_info *info,
 		type = RTE_ETH_REPRESENTOR_PF;
 		pf = info->mpesw_owner;
 		break;
+	case MLX5_PHYS_PORT_NAME_TYPE_VIRTUAL:
+		return UINT16_MAX;
 	case MLX5_PHYS_PORT_NAME_TYPE_PFSF:
 		type = RTE_ETH_REPRESENTOR_SF;
 		break;
@@ -507,10 +509,13 @@ mlx5_representor_info_count_one(struct mlx5_priv *priv)
 	case MLX5_PHYS_PORT_NAME_TYPE_PFSF:
 		/* FALLTHROUGH */
 	case MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN:
-		/* FALLTHROUGH */
-	default:
 		return 1;
+	case MLX5_PHYS_PORT_NAME_TYPE_VIRTUAL:
+		return 0;
 	}
+
+	/* Suppress "control reaches end of non-void function" warning without adding "default". */
+	return 0;
 }
 
 static unsigned int
@@ -606,6 +611,10 @@ mlx5_representor_info_fill_one(struct mlx5_priv *priv,
 		range->id_end = range->id_base;
 		snprintf(range->name, sizeof(range->name), "pf%dvf", range->pf);
 		break;
+	case MLX5_PHYS_PORT_NAME_TYPE_VIRTUAL:
+		/* Rejected by mlx5_representor_info_count_one() */
+		MLX5_ASSERT(false);
+		break;
 	}
 
 	info->nb_ranges += count;
diff --git a/drivers/net/mlx5/mlx5_mac.c b/drivers/net/mlx5/mlx5_mac.c
index 8cbaaf67dd..2ee8580f14 100644
--- a/drivers/net/mlx5/mlx5_mac.c
+++ b/drivers/net/mlx5/mlx5_mac.c
@@ -177,10 +177,12 @@ mlx5_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr)
 	 * need to skip the special cases:
 	 * - HPF on BlueField,
 	 * - SF representors,
-	 * - uplink ports when running in MPESW mode.
+	 * - uplink ports when running in MPESW mode,
+	 * - VIRTUAL switch ports (nested E-Switch).
 	 */
 	if (priv->representor && !mlx5_is_hpf(dev) && !mlx5_is_sf_repr(dev) &&
-	    !priv->mpesw_uplink) {
+	    !priv->mpesw_uplink &&
+	    priv->port_info.type != MLX5_PHYS_PORT_NAME_TYPE_VIRTUAL) {
 		DRV_LOG(DEBUG, "VF represented by port %u setting primary MAC address",
 			dev->data->port_id);
 		if (priv->pf_bond >= 0) {
-- 
2.43.0


  parent reply	other threads:[~2026-10-26 16:29 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-26 16:26 [PATCH 00/13] net/mlx5: support nested E-Switch Dariusz Sosnowski
2026-10-26 16:26 ` [PATCH 01/13] common/mlx5: rework IB port number query Dariusz Sosnowski
2026-10-26 16:26 ` [PATCH 02/13] common/mlx5: allow ifindex query without cache Dariusz Sosnowski
2026-10-26 16:26 ` [PATCH 03/13] common/mlx5: separate netdev info from switch info Dariusz Sosnowski
2026-10-26 16:27 ` [PATCH 04/13] common/mlx5: query parent device over Netlink Dariusz Sosnowski
2026-10-26 16:27 ` [PATCH 05/13] common/mlx5: add check for auxiliary device Dariusz Sosnowski
2026-10-26 16:27 ` [PATCH 06/13] common/mlx5: gather associated devices Dariusz Sosnowski
2026-10-26 16:27 ` [PATCH 07/13] common/mlx5: always use EAL device for probing Dariusz Sosnowski
2026-10-26 16:27 ` [PATCH 08/13] common/mlx5: query devlink port for netdevs Dariusz Sosnowski
2026-10-26 16:27 ` [PATCH 09/13] common/mlx5: get devlink port by port index Dariusz Sosnowski
2026-10-26 16:27 ` [PATCH 10/13] common/mlx5: add check for managed device Dariusz Sosnowski
2026-10-26 16:27 ` [PATCH 11/13] net/mlx5: add sibling device iteration macro Dariusz Sosnowski
2026-10-26 16:27 ` Dariusz Sosnowski [this message]
2026-10-26 16:27 ` [PATCH 13/13] net/mlx5: allow multiport auxiliary device probe Dariusz Sosnowski

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=20261026162709.1292958-13-dsosnowski@nvidia.com \
    --to=dsosnowski@nvidia.com \
    --cc=bingz@nvidia.com \
    --cc=dev@dpdk.org \
    --cc=matan@nvidia.com \
    --cc=orika@nvidia.com \
    --cc=suanmingm@nvidia.com \
    --cc=viacheslavo@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