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 06/13] common/mlx5: gather associated devices
Date: Mon, 26 Oct 2026 17:27:02 +0100	[thread overview]
Message-ID: <20261026162709.1292958-7-dsosnowski@nvidia.com> (raw)
In-Reply-To: <20261026162709.1292958-1-dsosnowski@nvidia.com>

There was one-to-one association between rte_device
and mlx5_common_device. Specifically on Linux, this rte_device
is either PCI or auxiliary device where IBV context can be opened.
This association is limiting for cases where embedded switch is shared
between different PFs/VFs/SFs. In such cases:

- There is one IB device where IBV context can be opened.
  This IB device is owned by a single PF/VF/SF.
- There are multiple PCI/auxiliary devices within embedded switch
  domain.

Goal of this patch is to allow probing ports belonging to the
embedded switch using the real associated device name.

When mlx5_common_device is created on Linux, a list of associated
devices is gathered:

- Number of IB ports (for mlx5 driver IB port is equivalent
  to embedded switch port) is queried.
- Using netlink RDMA interface, mlx5 driver translates IB port
  to netdev ifindex.
- Using netlink interface, mlx5 queries parent device
  of each netdev.
- Each parent device is added to associated devices list:
    - Device is added as a pair of bus/name strings.
    - Later on probe this are matched to allocated rte_device
      and replaced with that info.

As of this patch, all mlx5 driver will support only probing
with the main device (IB device owner).
Future patches will allow networking driver to probe
using multiple rte_device's.

Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
Acked-by: Viacheslav Ovsiienko <viacheslavo@nvidia.com>
---
 drivers/common/mlx5/linux/mlx5_common_os.c   | 164 +++++++++++++++++++
 drivers/common/mlx5/linux/mlx5_common_os.h   |   4 +
 drivers/common/mlx5/mlx5_common.c            |  52 ++++++
 drivers/common/mlx5/mlx5_common.h            |  20 +++
 drivers/common/mlx5/windows/mlx5_common_os.c |  19 +++
 drivers/common/mlx5/windows/mlx5_common_os.h |   1 +
 6 files changed, 260 insertions(+)

diff --git a/drivers/common/mlx5/linux/mlx5_common_os.c b/drivers/common/mlx5/linux/mlx5_common_os.c
index 903963670d..bd23c990f0 100644
--- a/drivers/common/mlx5/linux/mlx5_common_os.c
+++ b/drivers/common/mlx5/linux/mlx5_common_os.c
@@ -1251,3 +1251,167 @@ mlx5_os_is_device_bond(const void *dev)
 	closedir(net_dir);
 	return result;
 }
+
+static bool
+associated_device_matches_dev(const struct mlx5_associated_device *assoc,
+			      const char *bus_name,
+			      const char *dev_name)
+{
+	return assoc->is_rte_device && mlx5_dev_matches(assoc->dev, bus_name, dev_name);
+}
+
+static bool
+associated_device_matches_info(const struct mlx5_associated_device *assoc,
+			       const char *bus_name,
+			       const char *dev_name)
+{
+	return !assoc->is_rte_device &&
+	       strcmp(assoc->info.bus_name, bus_name) == 0 &&
+	       strcmp(assoc->info.dev_name, dev_name) == 0;
+}
+
+static bool
+associated_device_exists(const struct mlx5_common_device *cdev,
+			 const char *bus_name,
+			 const char *dev_name)
+{
+	struct mlx5_associated_device *assoc;
+
+	TAILQ_FOREACH(assoc, &cdev->associated_devices, next) {
+		if (associated_device_matches_dev(assoc, bus_name, dev_name) ||
+		    associated_device_matches_info(assoc, bus_name, dev_name))
+			return true;
+	}
+
+	return false;
+}
+
+static struct mlx5_associated_device *
+associated_device_alloc(const char *bus_name, const char *dev_name)
+{
+	struct mlx5_associated_device *assoc;
+	size_t bus_name_len;
+	size_t dev_name_len;
+	size_t size;
+	char *dst;
+
+	bus_name_len = strlen(bus_name) + 1;
+	dev_name_len = strlen(dev_name) + 1;
+
+	size = sizeof(*assoc);
+	size += bus_name_len;
+	size += dev_name_len;
+
+	assoc = mlx5_malloc(MLX5_MEM_ZERO, size, 0, SOCKET_ID_ANY);
+	if (!assoc)
+		return NULL;
+
+	assoc->is_rte_device = false;
+
+	dst = (void *)(assoc + 1);
+	memcpy(dst, bus_name, bus_name_len);
+	assoc->info.bus_name = dst;
+
+	dst = RTE_PTR_ADD(dst, bus_name_len);
+	memcpy(dst, dev_name, dev_name_len);
+	assoc->info.dev_name = dst;
+
+	return assoc;
+}
+
+int
+mlx5_os_fill_associated_devices(struct mlx5_common_device *cdev)
+{
+	struct mlx5_associated_device *assoc;
+	struct ibv_device *ibdev;
+	unsigned int portnum;
+	int nl_route = -1;
+	int nl_rdma;
+	int ret = 0;
+
+	MLX5_ASSERT(cdev != NULL);
+	MLX5_ASSERT(cdev->dev != NULL);
+	MLX5_ASSERT(TAILQ_EMPTY(&cdev->associated_devices));
+
+	assoc = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*assoc), 0, SOCKET_ID_ANY);
+	if (!assoc)
+		return -ENOMEM;
+	assoc->is_rte_device = true;
+	assoc->dev = cdev->dev;
+	TAILQ_INSERT_HEAD(&cdev->associated_devices, assoc, next);
+
+	ibdev = ((struct ibv_context *)cdev->ctx)->device;
+
+	nl_rdma = mlx5_nl_init(NETLINK_RDMA, 0);
+	if (nl_rdma < 0) {
+		ret = -rte_errno;
+		goto release_return;
+	}
+
+	portnum = mlx5_nl_portnum(nl_rdma, ibdev->name, NULL);
+	if (portnum == 0) {
+		ret = -rte_errno;
+		goto release_return;
+	}
+	if (portnum == 1) {
+		ret = 0;
+		goto release_return;
+	}
+
+	nl_route = mlx5_nl_init(NETLINK_ROUTE, 0);
+	if (nl_route < 0) {
+		ret = -rte_errno;
+		goto release_return;
+	}
+
+	for (unsigned int port = 1; port <= portnum; ++port) {
+		struct mlx5_netdev_info netdev_info = { 0 };
+
+		netdev_info.ifindex = mlx5_nl_ifindex(nl_rdma, ibdev->name, port, NULL);
+		if (netdev_info.ifindex == 0)
+			continue;
+
+		ret = mlx5_nl_netdev_info_get(nl_route, &netdev_info);
+		if (ret < 0) {
+			/*
+			 * On any failure just skip and don't add the device
+			 * to the associated devices list.
+			 */
+			DRV_LOG(DEBUG,
+				"ibdev %s port %u ifindex %u failed to get netdev info (%s)",
+				ibdev->name, port, netdev_info.ifindex, rte_strerror(-ret));
+			ret = 0;
+			continue;
+		}
+
+		if (!(netdev_info.flags & MLX5_NETDEV_INFO_FLAG_PARENT_DEV_NAME) ||
+		    !(netdev_info.flags & MLX5_NETDEV_INFO_FLAG_PARENT_DEV_BUS_NAME))
+			continue;
+
+		if (associated_device_exists(cdev,
+					     netdev_info.parent_dev_bus_name,
+					     netdev_info.parent_dev_name))
+			continue;
+
+		assoc = associated_device_alloc(netdev_info.parent_dev_bus_name,
+						netdev_info.parent_dev_name);
+		if (assoc == NULL) {
+			ret = -ENOMEM;
+			goto release_return;
+		}
+
+		TAILQ_INSERT_HEAD(&cdev->associated_devices, assoc, next);
+	}
+
+release_return:
+	while (ret < 0 && !TAILQ_EMPTY(&cdev->associated_devices)) {
+		assoc = TAILQ_FIRST(&cdev->associated_devices);
+		TAILQ_REMOVE(&cdev->associated_devices, assoc, next);
+		mlx5_free(assoc);
+	}
+	if (nl_rdma >= 0)
+		close(nl_rdma);
+	if (nl_route >= 0)
+		close(nl_route);
+	return ret;
+}
diff --git a/drivers/common/mlx5/linux/mlx5_common_os.h b/drivers/common/mlx5/linux/mlx5_common_os.h
index 7d4e3c5fe8..e39afcb9de 100644
--- a/drivers/common/mlx5/linux/mlx5_common_os.h
+++ b/drivers/common/mlx5/linux/mlx5_common_os.h
@@ -22,6 +22,8 @@
 #include "mlx5_glue.h"
 #include "mlx5_malloc.h"
 
+struct mlx5_common_device;
+
 /* verb enumerations translations to local enums. */
 enum {
 	MLX5_FS_NAME_MAX = IBV_SYSFS_NAME_MAX + 1,
@@ -326,4 +328,6 @@ mlx5_os_interrupt_handler_destroy(struct rte_intr_handle *intr_handle,
 __rte_internal
 bool mlx5_os_is_device_bond(const void *dev);
 
+int mlx5_os_fill_associated_devices(struct mlx5_common_device *cdev);
+
 #endif /* RTE_PMD_MLX5_COMMON_OS_H_ */
diff --git a/drivers/common/mlx5/mlx5_common.c b/drivers/common/mlx5/mlx5_common.c
index 11a53c8b56..67566e01b2 100644
--- a/drivers/common/mlx5/mlx5_common.c
+++ b/drivers/common/mlx5/mlx5_common.c
@@ -755,6 +755,18 @@ mlx5_dev_hw_global_prepare(struct mlx5_common_device *cdev, uint32_t classes)
 	return ret;
 }
 
+static void
+mlx5_associated_devices_release(struct mlx5_common_device *cdev)
+{
+	struct mlx5_associated_device *assoc;
+
+	while (!TAILQ_EMPTY(&cdev->associated_devices)) {
+		assoc = TAILQ_FIRST(&cdev->associated_devices);
+		TAILQ_REMOVE(&cdev->associated_devices, assoc, next);
+		mlx5_free(assoc);
+	}
+}
+
 static void
 mlx5_common_dev_release(struct mlx5_common_device *cdev)
 {
@@ -762,6 +774,7 @@ mlx5_common_dev_release(struct mlx5_common_device *cdev)
 	TAILQ_REMOVE(&devices_list, cdev, next);
 	pthread_mutex_unlock(&devices_list_lock);
 	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+		mlx5_associated_devices_release(cdev);
 		if (TAILQ_EMPTY(&devices_list))
 			rte_mem_event_callback_unregister("MLX5_MEM_EVENT_CB",
 							  NULL);
@@ -791,6 +804,7 @@ mlx5_common_dev_create(struct rte_device *eal_dev, uint32_t classes,
 		return NULL;
 	}
 	cdev->dev = eal_dev;
+	TAILQ_INIT(&cdev->associated_devices);
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		goto exit;
 	/* Parse device parameters. */
@@ -822,6 +836,16 @@ mlx5_common_dev_create(struct rte_device *eal_dev, uint32_t classes,
 		rte_mem_event_callback_register("MLX5_MEM_EVENT_CB",
 						mlx5_mr_mem_event_cb, NULL);
 	cdev->dev_info.probe_opt = cdev->config.probe_opt;
+
+	ret = mlx5_os_fill_associated_devices(cdev);
+	if (ret < 0) {
+		DRV_LOG(DEBUG,
+			"cdev %s Failed to initialize associated devices list. "
+			"Only owner device is allowed",
+			cdev->dev->name);
+		rte_errno = 0;
+	}
+
 exit:
 	pthread_mutex_lock(&devices_list_lock);
 	TAILQ_INSERT_HEAD(&devices_list, cdev, next);
@@ -1468,4 +1492,32 @@ mlx5_devx_uar_prepare(struct mlx5_common_device *cdev, struct mlx5_uar *uar)
 	return 0;
 }
 
+RTE_EXPORT_INTERNAL_SYMBOL(mlx5_dev_matches)
+bool
+mlx5_dev_matches(const struct rte_device *dev,
+		 const char *bus_name,
+		 const char *dev_name)
+{
+	if (strcmp(dev->bus->name, bus_name) != 0)
+		return false;
+
+	if (mlx5_dev_is_pci(dev)) {
+		const struct rte_pci_device *pci_dev = RTE_BUS_DEVICE(dev, *pci_dev);
+		struct rte_pci_addr addr;
+
+		if (rte_pci_addr_parse(dev_name, &addr) < 0)
+			return false;
+
+		return rte_pci_addr_cmp(&addr, &pci_dev->addr) == 0;
+	}
+
+	if (mlx5_dev_is_auxiliary(dev)) {
+		const struct rte_auxiliary_device *aux_dev = RTE_BUS_DEVICE(dev, *aux_dev);
+
+		return strcmp(dev_name, aux_dev->name) == 0;
+	}
+
+	return false;
+}
+
 RTE_PMD_EXPORT_NAME(mlx5_common_driver);
diff --git a/drivers/common/mlx5/mlx5_common.h b/drivers/common/mlx5/mlx5_common.h
index f579ca0904..8f8ab01700 100644
--- a/drivers/common/mlx5/mlx5_common.h
+++ b/drivers/common/mlx5/mlx5_common.h
@@ -515,6 +515,22 @@ struct mlx5_common_dev_config {
 	/* Whether memseg should be extended for MR creation. */
 };
 
+struct mlx5_associated_device_info {
+	const char *bus_name;
+	const char *dev_name;
+};
+
+struct mlx5_associated_device {
+	TAILQ_ENTRY(mlx5_associated_device) next;
+	bool is_rte_device;
+	union {
+		const struct rte_device *dev;
+		struct mlx5_associated_device_info info;
+	};
+};
+
+TAILQ_HEAD(mlx5_associated_device_list, mlx5_associated_device);
+
 struct mlx5_common_device {
 	struct rte_device *dev;
 	TAILQ_ENTRY(mlx5_common_device) next;
@@ -525,6 +541,7 @@ struct mlx5_common_device {
 	uint32_t pdn; /* Protection Domain Number. */
 	struct mlx5_mr_share_cache mr_scache; /* Global shared MR cache. */
 	struct mlx5_common_dev_config config; /* Device configuration. */
+	struct mlx5_associated_device_list associated_devices;
 };
 
 /**
@@ -669,4 +686,7 @@ __rte_internal
 void
 mlx5_os_wrapped_mkey_destroy(struct mlx5_pmd_wrapped_mr *pmd_mr);
 
+__rte_internal
+bool mlx5_dev_matches(const struct rte_device *dev, const char *bus_name, const char *dev_name);
+
 #endif /* RTE_PMD_MLX5_COMMON_H_ */
diff --git a/drivers/common/mlx5/windows/mlx5_common_os.c b/drivers/common/mlx5/windows/mlx5_common_os.c
index bdafb95df9..e15a97677f 100644
--- a/drivers/common/mlx5/windows/mlx5_common_os.c
+++ b/drivers/common/mlx5/windows/mlx5_common_os.c
@@ -493,3 +493,22 @@ mlx5_os_wrapped_mkey_destroy(struct mlx5_pmd_wrapped_mr *wpmd_mr)
 	mlx5_os_dereg_mr(&pmd_mr);
 	memset(wpmd_mr, 0, sizeof(*wpmd_mr));
 }
+
+int
+mlx5_os_fill_associated_devices(struct mlx5_common_device *cdev)
+{
+	struct mlx5_associated_device *assoc;
+
+	MLX5_ASSERT(cdev != NULL);
+	MLX5_ASSERT(cdev->dev != NULL);
+	MLX5_ASSERT(TAILQ_EMPTY(&cdev->associated_devices));
+
+	assoc = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*assoc), 0, SOCKET_ID_ANY);
+	if (!assoc)
+		return -ENOMEM;
+	assoc->is_rte_device = true;
+	assoc->dev = cdev->dev;
+	TAILQ_INSERT_HEAD(&cdev->associated_devices, assoc, next);
+
+	return 0;
+}
diff --git a/drivers/common/mlx5/windows/mlx5_common_os.h b/drivers/common/mlx5/windows/mlx5_common_os.h
index 65394035de..a63e29f5f1 100644
--- a/drivers/common/mlx5/windows/mlx5_common_os.h
+++ b/drivers/common/mlx5/windows/mlx5_common_os.h
@@ -282,5 +282,6 @@ mlx5_os_interrupt_handler_destroy(struct rte_intr_handle *intr_handle,
 	(void)cb_arg;
 }
 
+int mlx5_os_fill_associated_devices(struct mlx5_common_device *cdev);
 
 #endif /* RTE_PMD_MLX5_COMMON_OS_H_ */
-- 
2.43.0


  parent reply	other threads:[~2026-10-26 16:28 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 ` Dariusz Sosnowski [this message]
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 ` [PATCH 12/13] net/mlx5: allow associated devices Dariusz Sosnowski
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-7-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