diff --git a/drivers/common/mlx5/linux/mlx5_common_os.c b/drivers/common/mlx5/linux/mlx5_common_os.c
index 9e0c823c97..2aa5684b05 100644
--- a/drivers/common/mlx5/linux/mlx5_common_os.c
+++ b/drivers/common/mlx5/linux/mlx5_common_os.c
@@ -16,6 +16,7 @@
 
 #include "mlx5_common.h"
 #include "mlx5_common_log.h"
+#include "mlx5_common_defs.h"
 #include "mlx5_common_os.h"
 #include "mlx5_glue.h"
 
@@ -428,3 +429,88 @@ mlx5_os_get_ibv_device(const struct rte_pci_addr *addr)
 	mlx5_glue->free_device_list(ibv_list);
 	return ibv_match;
 }
+
+static int
+mlx5_config_doorbell_mapping_env(int dbnc)
+{
+	char *env;
+	int value;
+
+	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
+	/* Get environment variable to store. */
+	env = getenv(MLX5_SHUT_UP_BF);
+	value = env ? !!strcmp(env, "0") : MLX5_ARG_UNSET;
+	if (dbnc == MLX5_ARG_UNSET)
+		setenv(MLX5_SHUT_UP_BF, MLX5_SHUT_UP_BF_DEFAULT, 1);
+	else
+		setenv(MLX5_SHUT_UP_BF,
+		       dbnc == MLX5_TXDB_NCACHED ? "1" : "0", 1);
+	return value;
+}
+
+static void
+mlx5_restore_doorbell_mapping_env(int value)
+{
+	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
+	/* Restore the original environment variable state. */
+	if (value == MLX5_ARG_UNSET)
+		unsetenv(MLX5_SHUT_UP_BF);
+	else
+		setenv(MLX5_SHUT_UP_BF, value ? "1" : "0", 1);
+}
+
+/**
+ * Function API to open IB device.
+ *
+ *
+ * @param cdev
+ *   Pointer to the mlx5 device.
+ * @param ctx_ptr
+ *   Pointer to fill inside pointer to device context.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+int
+mlx5_os_open_device(struct mlx5_common_device *cdev, void **ctx_ptr)
+{
+	struct ibv_device *ibv;
+	struct ibv_context *ctx = NULL;
+	int dbmap_env;
+
+	ibv = mlx5_os_get_ibv_dev(cdev->dev);
+	if (!ibv)
+		return -rte_errno;
+	DRV_LOG(INFO, "Dev information matches for device \"%s\".", ibv->name);
+	/*
+	 * Configure environment variable "MLX5_BF_SHUT_UP" before the device
+	 * creation. The rdma_core library checks the variable at device
+	 * creation and stores the result internally.
+	 */
+	dbmap_env = mlx5_config_doorbell_mapping_env(cdev->config.dbnc);
+	/* Try to open IB device with DV first, then usual Verbs. */
+	errno = 0;
+	ctx = mlx5_glue->dv_open_device(ibv);
+	if (ctx) {
+		cdev->config.devx = 1;
+		DRV_LOG(DEBUG, "DevX is supported.");
+	} else {
+		/* The environment variable is still configured. */
+		ctx = mlx5_glue->open_device(ibv);
+		if (ctx == NULL)
+			goto error;
+		DRV_LOG(DEBUG, "DevX is NOT supported.");
+	}
+	/* The device is created, no need for environment. */
+	mlx5_restore_doorbell_mapping_env(dbmap_env);
+	/* Hint libmlx5 to use PMD allocator for data plane resources */
+	mlx5_set_context_attr(cdev->dev, ctx);
+	*ctx_ptr = (void *)ctx;
+	return 0;
+error:
+	rte_errno = errno ? errno : ENODEV;
+	/* The device creation is failed, no need for environment. */
+	mlx5_restore_doorbell_mapping_env(dbmap_env);
+	DRV_LOG(ERR, "Failed to open IB device \"%s\".", ibv->name);
+	return -rte_errno;
+}
diff --git a/drivers/common/mlx5/linux/mlx5_common_os.h b/drivers/common/mlx5/linux/mlx5_common_os.h
index c3202b6786..05c8ae1ba5 100644
--- a/drivers/common/mlx5/linux/mlx5_common_os.h
+++ b/drivers/common/mlx5/linux/mlx5_common_os.h
@@ -296,4 +296,7 @@ __rte_internal
 struct ibv_device *
 mlx5_os_get_ibv_dev(const struct rte_device *dev);
 
+void
+mlx5_set_context_attr(struct rte_device *dev, struct ibv_context *ctx);
+
 #endif /* RTE_PMD_MLX5_COMMON_OS_H_ */
diff --git a/drivers/common/mlx5/linux/mlx5_common_verbs.c b/drivers/common/mlx5/linux/mlx5_common_verbs.c
index 9080bd3e87..e5a1244867 100644
--- a/drivers/common/mlx5/linux/mlx5_common_verbs.c
+++ b/drivers/common/mlx5/linux/mlx5_common_verbs.c
@@ -12,6 +12,7 @@
 
 #include <rte_errno.h>
 #include <rte_bus_pci.h>
+#include <rte_eal_paging.h>
 #include <rte_bus_auxiliary.h>
 
 #include "mlx5_common_utils.h"
@@ -19,6 +20,7 @@
 #include "mlx5_common_private.h"
 #include "mlx5_autoconf.h"
 #include <mlx5_glue.h>
+#include <mlx5_malloc.h>
 #include <mlx5_common.h>
 #include <mlx5_common_mr.h>
 
@@ -38,6 +40,74 @@ mlx5_os_get_ibv_dev(const struct rte_device *dev)
 	return ibv;
 }
 
+/**
+ * Verbs callback to allocate a memory. This function should allocate the space
+ * according to the size provided residing inside a huge page.
+ * Please note that all allocation must respect the alignment from libmlx5
+ * (i.e. currently rte_mem_page_size()).
+ *
+ * @param[in] size
+ *   The size in bytes of the memory to allocate.
+ * @param[in] data
+ *   A pointer to the callback data.
+ *
+ * @return
+ *   Allocated buffer, NULL otherwise and rte_errno is set.
+ */
+static void *
+mlx5_alloc_verbs_buf(size_t size, void *data)
+{
+	struct rte_device *dev = data;
+	void *ret;
+	size_t alignment = rte_mem_page_size();
+	if (alignment == (size_t)-1) {
+		DRV_LOG(ERR, "Failed to get mem page size");
+		rte_errno = ENOMEM;
+		return NULL;
+	}
+
+	MLX5_ASSERT(data != NULL);
+	ret = mlx5_malloc(0, size, alignment, dev->numa_node);
+	if (!ret && size)
+		rte_errno = ENOMEM;
+	return ret;
+}
+
+/**
+ * Verbs callback to free a memory.
+ *
+ * @param[in] ptr
+ *   A pointer to the memory to free.
+ * @param[in] data
+ *   A pointer to the callback data.
+ */
+static void
+mlx5_free_verbs_buf(void *ptr, void *data __rte_unused)
+{
+	MLX5_ASSERT(data != NULL);
+	mlx5_free(ptr);
+}
+
+/**
+ * Hint libmlx5 to use PMD allocator for data plane resources.
+ *
+ * @param dev
+ *   Pointer to the generic device.
+ */
+void
+mlx5_set_context_attr(struct rte_device *dev, struct ibv_context *ctx)
+{
+	struct mlx5dv_ctx_allocators allocator = {
+		.alloc = &mlx5_alloc_verbs_buf,
+		.free = &mlx5_free_verbs_buf,
+		.data = dev,
+	};
+
+	/* Hint libmlx5 to use PMD allocator for data plane resources */
+	mlx5_glue->dv_set_context_attr(ctx, MLX5DV_CTX_ATTR_BUF_ALLOCATORS,
+				       (void *)((uintptr_t)&allocator));
+}
+
 /**
  * Register mr. Given protection domain pointer, pointer to addr and length
  * register the memory region.
diff --git a/drivers/common/mlx5/mlx5_common.h b/drivers/common/mlx5/mlx5_common.h
index f922757da1..f36791f24e 100644
--- a/drivers/common/mlx5/mlx5_common.h
+++ b/drivers/common/mlx5/mlx5_common.h
@@ -334,6 +334,7 @@ void mlx5_common_init(void);
  */
 struct mlx5_common_dev_config {
 	int dbnc; /* Skip doorbell register write barrier. */
+	unsigned int devx:1; /* Whether devx interface is available or not. */
 	unsigned int sys_mem_en:1; /* The default memory allocator. */
 	unsigned int mr_mempool_reg_en:1;
 	/* Allow/prevent implicit mempool memory registration. */
@@ -443,4 +444,9 @@ __rte_internal
 bool
 mlx5_dev_is_pci(const struct rte_device *dev);
 
+/* mlx5_common_os.c */
+
+__rte_internal
+int mlx5_os_open_device(struct mlx5_common_device *cdev, void **ctx);
+
 #endif /* RTE_PMD_MLX5_COMMON_H_ */
diff --git a/drivers/common/mlx5/version.map b/drivers/common/mlx5/version.map
index 9d17366d19..63fe89cccc 100644
--- a/drivers/common/mlx5/version.map
+++ b/drivers/common/mlx5/version.map
@@ -144,6 +144,7 @@ INTERNAL {
 	mlx5_os_dealloc_pd;
 	mlx5_os_dereg_mr;
 	mlx5_os_get_ibv_dev; # WINDOWS_NO_EXPORT
+    mlx5_os_open_device;
 	mlx5_os_reg_mr;
 	mlx5_os_umem_dereg;
 	mlx5_os_umem_reg;
diff --git a/drivers/common/mlx5/windows/mlx5_common_os.c b/drivers/common/mlx5/windows/mlx5_common_os.c
index 5031bdca26..e426a955ff 100644
--- a/drivers/common/mlx5/windows/mlx5_common_os.c
+++ b/drivers/common/mlx5/windows/mlx5_common_os.c
@@ -72,6 +72,167 @@ mlx5_os_dealloc_pd(void *pd)
 	return 0;
 }
 
+/**
+ * Detect if a devx_device_bdf object has identical DBDF values to the
+ * rte_pci_addr found in bus/pci probing.
+ *
+ * @param[in] devx_bdf
+ *   Pointer to the devx_device_bdf structure.
+ * @param[in] addr
+ *   Pointer to the rte_pci_addr structure.
+ *
+ * @return
+ *   1 on Device match, 0 on mismatch.
+ */
+static int
+mlx5_match_devx_bdf_to_addr(struct devx_device_bdf *devx_bdf,
+			    struct rte_pci_addr *addr)
+{
+	if (addr->domain != (devx_bdf->bus_id >> 8) ||
+	    addr->bus != (devx_bdf->bus_id & 0xff) ||
+	    addr->devid != devx_bdf->dev_id ||
+	    addr->function != devx_bdf->fnc_id) {
+		return 0;
+	}
+	return 1;
+}
+
+/**
+ * Detect if a devx_device_bdf object matches the rte_pci_addr
+ * found in bus/pci probing
+ * Compare both the Native/PF BDF and the raw_bdf representing a VF BDF.
+ *
+ * @param[in] devx_bdf
+ *   Pointer to the devx_device_bdf structure.
+ * @param[in] addr
+ *   Pointer to the rte_pci_addr structure.
+ *
+ * @return
+ *   1 on Device match, 0 on mismatch, rte_errno code on failure.
+ */
+static int
+mlx5_match_devx_devices_to_addr(struct devx_device_bdf *devx_bdf,
+				struct rte_pci_addr *addr)
+{
+	int err;
+	struct devx_device mlx5_dev;
+
+	if (mlx5_match_devx_bdf_to_addr(devx_bdf, addr))
+		return 1;
+	/*
+	 * Didn't match on Native/PF BDF, could still match a VF BDF,
+	 * check it next.
+	 */
+	err = mlx5_glue->query_device(devx_bdf, &mlx5_dev);
+	if (err) {
+		DRV_LOG(ERR, "query_device failed");
+		rte_errno = err;
+		return rte_errno;
+	}
+	if (mlx5_match_devx_bdf_to_addr(&mlx5_dev.raw_bdf, addr))
+		return 1;
+	return 0;
+}
+
+/**
+ * Look for DevX device that match to given rte_device.
+ *
+ * @param dev
+ *   Pointer to the generic device.
+ * @param devx_list
+ *   Pointer to head of DevX devices list.
+ * @param n
+ *   Number of devices in given DevX devices list.
+ *
+ * @return
+ *   A device match on success, NULL otherwise and rte_errno is set.
+ */
+static struct devx_device_bdf *
+mlx5_os_get_devx_device(struct rte_device *dev,
+			struct devx_device_bdf *devx_list, int n)
+{
+	struct devx_device_bdf *devx_match = NULL;
+	struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev);
+	struct rte_pci_addr *addr = &pci_dev->addr;
+
+	while (n-- > 0) {
+		int ret = mlx5_match_devx_devices_to_addr(devx_list, addr);
+		if (!ret) {
+			devx_list++;
+			continue;
+		}
+		if (ret != 1) {
+			rte_errno = ret;
+			return NULL;
+		}
+		devx_match = devx_list;
+		break;
+	}
+	if (devx_match == NULL) {
+		/* No device matches, just complain and bail out. */
+		DRV_LOG(WARNING,
+			"No DevX device matches PCI device " PCI_PRI_FMT ","
+			" is DevX Configured?",
+			addr->domain, addr->bus, addr->devid, addr->function);
+		rte_errno = ENOENT;
+	}
+	return devx_match;
+}
+
+/**
+ * Function API open device under Windows.
+ *
+ * This function calls the Windows glue APIs to open a device.
+ *
+ * @param dev
+ *   Pointer to mlx5 device structure.
+ * @param ctx
+ *   Pointer to fill inside pointer to device context.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+int
+mlx5_os_open_device(struct mlx5_common_device *cdev, void **ctx)
+{
+	struct devx_device_bdf *devx_bdf_dev = NULL;
+	struct devx_device_bdf *devx_list;
+	struct mlx5_context *mlx5_ctx = NULL;
+	int n;
+
+	errno = 0;
+	devx_list = mlx5_glue->get_device_list(&n);
+	if (devx_list == NULL) {
+		rte_errno = errno ? errno : ENOSYS;
+		DRV_LOG(ERR, "Cannot list devices, is DevX enabled?");
+		return -rte_errno;
+	}
+	devx_bdf_dev = mlx5_os_get_devx_device(cdev->dev, devx_list, n);
+	if (devx_bdf_dev == NULL)
+		goto error;
+	/* Try to open DevX device with DV. */
+	mlx5_ctx = mlx5_glue->open_device(devx_bdf_dev);
+	if (mlx5_ctx == NULL) {
+		DRV_LOG(ERR, "Failed to open DevX device.");
+		rte_errno = errno;
+		goto error;
+	}
+	if (mlx5_glue->query_device(devx_bdf_dev, &mlx5_ctx->mlx5_dev)) {
+		DRV_LOG(ERR, "Failed to query device context fields.");
+		rte_errno = errno;
+		goto error;
+	}
+	cdev->config.devx = 1;
+	*ctx = (void *)mlx5_ctx;
+	mlx5_glue->free_device_list(devx_list);
+	return 0;
+error:
+	if (mlx5_ctx != NULL)
+		claim_zero(mlx5_glue->close_device(mlx5_ctx));
+	mlx5_glue->free_device_list(devx_list);
+	return -rte_errno;
+}
+
 /**
  * Register umem.
  *
diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c
index d3b789bd72..c1b828a422 100644
--- a/drivers/net/mlx5/linux/mlx5_os.c
+++ b/drivers/net/mlx5/linux/mlx5_os.c
@@ -197,39 +197,6 @@ mlx5_os_get_dev_attr(void *ctx, struct mlx5_dev_attr *device_attr)
 	return err;
 }
 
-/**
- * Verbs callback to allocate a memory. This function should allocate the space
- * according to the size provided residing inside a huge page.
- * Please note that all allocation must respect the alignment from libmlx5
- * (i.e. currently rte_mem_page_size()).
- *
- * @param[in] size
- *   The size in bytes of the memory to allocate.
- * @param[in] data
- *   A pointer to the callback data.
- *
- * @return
- *   Allocated buffer, NULL otherwise and rte_errno is set.
- */
-static void *
-mlx5_alloc_verbs_buf(size_t size, void *data)
-{
-	struct mlx5_dev_ctx_shared *sh = data;
-	void *ret;
-	size_t alignment = rte_mem_page_size();
-	if (alignment == (size_t)-1) {
-		DRV_LOG(ERR, "Failed to get mem page size");
-		rte_errno = ENOMEM;
-		return NULL;
-	}
-
-	MLX5_ASSERT(data != NULL);
-	ret = mlx5_malloc(0, size, alignment, sh->numa_node);
-	if (!ret && size)
-		rte_errno = ENOMEM;
-	return ret;
-}
-
 /**
  * Detect misc5 support or not
  *
@@ -303,21 +270,6 @@ __mlx5_discovery_misc5_cap(struct mlx5_priv *priv)
 }
 #endif
 
-/**
- * Verbs callback to free a memory.
- *
- * @param[in] ptr
- *   A pointer to the memory to free.
- * @param[in] data
- *   A pointer to the callback data.
- */
-static void
-mlx5_free_verbs_buf(void *ptr, void *data __rte_unused)
-{
-	MLX5_ASSERT(data != NULL);
-	mlx5_free(ptr);
-}
-
 /**
  * Initialize DR related data within private structure.
  * Routine checks the reference counter and does actual
@@ -938,7 +890,7 @@ mlx5_representor_match(struct mlx5_dev_spawn_data *spawn,
  *   Verbs device parameters (name, port, switch_info) to spawn.
  * @param config
  *   Device configuration parameters.
- * @param config
+ * @param eth_da
  *   Device arguments.
  *
  * @return
@@ -997,12 +949,10 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
 		/* Bonding device. */
 		if (!switch_info->representor) {
 			err = snprintf(name, sizeof(name), "%s_%s",
-				 dpdk_dev->name,
-				 mlx5_os_get_dev_device_name(spawn->phys_dev));
+				       dpdk_dev->name, spawn->phys_dev_name);
 		} else {
 			err = snprintf(name, sizeof(name), "%s_%s_representor_c%dpf%d%s%u",
-				dpdk_dev->name,
-				mlx5_os_get_dev_device_name(spawn->phys_dev),
+				dpdk_dev->name, spawn->phys_dev_name,
 				switch_info->ctrl_num,
 				switch_info->pf_num,
 				switch_info->name_type ==
@@ -1224,9 +1174,8 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
 						 &vport_info);
 		if (err) {
 			DRV_LOG(WARNING,
-				"can't query devx port %d on device %s",
-				spawn->phys_port,
-				mlx5_os_get_dev_device_name(spawn->phys_dev));
+				"Cannot query devx port %d on device %s",
+				spawn->phys_port, spawn->phys_dev_name);
 			vport_info.query_flags = 0;
 		}
 	}
@@ -1234,20 +1183,16 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
 		priv->vport_meta_tag = vport_info.vport_meta_tag;
 		priv->vport_meta_mask = vport_info.vport_meta_mask;
 		if (!priv->vport_meta_mask) {
-			DRV_LOG(ERR, "vport zero mask for port %d"
-				     " on bonding device %s",
-				     spawn->phys_port,
-				     mlx5_os_get_dev_device_name
-							(spawn->phys_dev));
+			DRV_LOG(ERR,
+				"vport zero mask for port %d on bonding device %s",
+				spawn->phys_port, spawn->phys_dev_name);
 			err = ENOTSUP;
 			goto error;
 		}
 		if (priv->vport_meta_tag & ~priv->vport_meta_mask) {
-			DRV_LOG(ERR, "invalid vport tag for port %d"
-				     " on bonding device %s",
-				     spawn->phys_port,
-				     mlx5_os_get_dev_device_name
-							(spawn->phys_dev));
+			DRV_LOG(ERR,
+				"Invalid vport tag for port %d on bonding device %s",
+				spawn->phys_port, spawn->phys_dev_name);
 			err = ENOTSUP;
 			goto error;
 		}
@@ -1256,10 +1201,9 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
 		priv->vport_id = vport_info.vport_id;
 	} else if (spawn->pf_bond >= 0 &&
 		   (switch_info->representor || switch_info->master)) {
-		DRV_LOG(ERR, "can't deduce vport index for port %d"
-			     " on bonding device %s",
-			     spawn->phys_port,
-			     mlx5_os_get_dev_device_name(spawn->phys_dev));
+		DRV_LOG(ERR,
+			"Cannot deduce vport index for port %d on bonding device %s",
+			spawn->phys_port, spawn->phys_dev_name);
 		err = ENOTSUP;
 		goto error;
 	} else {
@@ -1742,14 +1686,6 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
 	priv->mtr_profile_tbl = mlx5_l3t_create(MLX5_L3T_TYPE_PTR);
 	if (!priv->mtr_profile_tbl)
 		goto error;
-	/* Hint libmlx5 to use PMD allocator for data plane resources */
-	mlx5_glue->dv_set_context_attr(sh->ctx,
-			MLX5DV_CTX_ATTR_BUF_ALLOCATORS,
-			(void *)((uintptr_t)&(struct mlx5dv_ctx_allocators){
-				.alloc = &mlx5_alloc_verbs_buf,
-				.free = &mlx5_free_verbs_buf,
-				.data = sh,
-			}));
 	/* Bring Ethernet device up. */
 	DRV_LOG(DEBUG, "port %u forcing Ethernet interface up",
 		eth_dev->data->port_id);
@@ -2155,7 +2091,7 @@ mlx5_os_config_default(struct mlx5_dev_config *config)
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 static int
-mlx5_os_pci_probe_pf(struct mlx5_common_device *cdev,
+mlx5_os_pci_probe_pf(struct mlx5_common_device *cdev, void *ctx,
 		     struct rte_eth_devargs *req_eth_da,
 		     uint16_t owner_id)
 {
@@ -2197,7 +2133,7 @@ mlx5_os_pci_probe_pf(struct mlx5_common_device *cdev,
 	ibv_list = mlx5_glue->get_device_list(&ret);
 	if (!ibv_list) {
 		rte_errno = errno ? errno : ENOSYS;
-		DRV_LOG(ERR, "cannot list devices, is ib_uverbs loaded?");
+		DRV_LOG(ERR, "Cannot list devices, is ib_uverbs loaded?");
 		return -rte_errno;
 	}
 	/*
@@ -2212,7 +2148,7 @@ mlx5_os_pci_probe_pf(struct mlx5_common_device *cdev,
 	while (ret-- > 0) {
 		struct rte_pci_addr pci_addr;
 
-		DRV_LOG(DEBUG, "checking device \"%s\"", ibv_list[ret]->name);
+		DRV_LOG(DEBUG, "Checking device \"%s\"", ibv_list[ret]->name);
 		bd = mlx5_device_bond_pci_match
 				(ibv_list[ret], &owner_pci, nl_rdma, owner_id,
 				 &bond_info);
@@ -2259,7 +2195,7 @@ mlx5_os_pci_probe_pf(struct mlx5_common_device *cdev,
 	if (!nd) {
 		/* No device matches, just complain and bail out. */
 		DRV_LOG(WARNING,
-			"no Verbs device matches PCI device " PCI_PRI_FMT ","
+			"No Verbs device matches PCI device " PCI_PRI_FMT ","
 			" are kernel drivers loaded?",
 			owner_pci.domain, owner_pci.bus,
 			owner_pci.devid, owner_pci.function);
@@ -2276,26 +2212,22 @@ mlx5_os_pci_probe_pf(struct mlx5_common_device *cdev,
 		if (nl_rdma >= 0)
 			np = mlx5_nl_portnum(nl_rdma, ibv_match[0]->name);
 		if (!np)
-			DRV_LOG(WARNING, "can not get IB device \"%s\""
-					 " ports number", ibv_match[0]->name);
+			DRV_LOG(WARNING,
+				"Cannot get IB device \"%s\" ports number.",
+				ibv_match[0]->name);
 		if (bd >= 0 && !np) {
-			DRV_LOG(ERR, "can not get ports"
-				     " for bonding device");
+			DRV_LOG(ERR, "Cannot get ports for bonding device.");
 			rte_errno = ENOENT;
 			ret = -rte_errno;
 			goto exit;
 		}
 	}
-	/*
-	 * Now we can determine the maximal
-	 * amount of devices to be spawned.
-	 */
+	/* Now we can determine the maximal amount of devices to be spawned. */
 	list = mlx5_malloc(MLX5_MEM_ZERO,
-			   sizeof(struct mlx5_dev_spawn_data) *
-			   (np ? np : nd),
+			   sizeof(struct mlx5_dev_spawn_data) * (np ? np : nd),
 			   RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
 	if (!list) {
-		DRV_LOG(ERR, "spawn data array allocation failure");
+		DRV_LOG(ERR, "Spawn data array allocation failure.");
 		rte_errno = ENOMEM;
 		ret = -rte_errno;
 		goto exit;
@@ -2314,15 +2246,15 @@ mlx5_os_pci_probe_pf(struct mlx5_common_device *cdev,
 			list[ns].bond_info = &bond_info;
 			list[ns].max_port = np;
 			list[ns].phys_port = i;
-			list[ns].phys_dev = ibv_match[0];
+			list[ns].phys_dev_name = ibv_match[0]->name;
+			list[ns].ctx = ctx;
 			list[ns].eth_dev = NULL;
 			list[ns].pci_dev = pci_dev;
 			list[ns].cdev = cdev;
 			list[ns].pf_bond = bd;
-			list[ns].ifindex = mlx5_nl_ifindex
-				(nl_rdma,
-				mlx5_os_get_dev_device_name
-						(list[ns].phys_dev), i);
+			list[ns].ifindex = mlx5_nl_ifindex(nl_rdma,
+							   ibv_match[0]->name,
+							   i);
 			if (!list[ns].ifindex) {
 				/*
 				 * No network interface index found for the
@@ -2335,10 +2267,9 @@ mlx5_os_pci_probe_pf(struct mlx5_common_device *cdev,
 			}
 			ret = -1;
 			if (nl_route >= 0)
-				ret = mlx5_nl_switch_info
-					       (nl_route,
-						list[ns].ifindex,
-						&list[ns].info);
+				ret = mlx5_nl_switch_info(nl_route,
+							  list[ns].ifindex,
+							  &list[ns].info);
 			if (ret || (!list[ns].info.representor &&
 				    !list[ns].info.master)) {
 				/*
@@ -2346,9 +2277,8 @@ mlx5_os_pci_probe_pf(struct mlx5_common_device *cdev,
 				 * Netlink, let's try to perform the task
 				 * with sysfs.
 				 */
-				ret =  mlx5_sysfs_switch_info
-						(list[ns].ifindex,
-						 &list[ns].info);
+				ret = mlx5_sysfs_switch_info(list[ns].ifindex,
+							     &list[ns].info);
 			}
 			if (!ret && bd >= 0) {
 				switch (list[ns].info.name_type) {
@@ -2384,8 +2314,7 @@ mlx5_os_pci_probe_pf(struct mlx5_common_device *cdev,
 		}
 		if (!ns) {
 			DRV_LOG(ERR,
-				"unable to recognize master/representors"
-				" on the IB device with multiple ports");
+				"Unable to recognize master/representors on the IB device with multiple ports.");
 			rte_errno = ENOENT;
 			ret = -rte_errno;
 			goto exit;
@@ -2413,7 +2342,8 @@ mlx5_os_pci_probe_pf(struct mlx5_common_device *cdev,
 			list[ns].bond_info = NULL;
 			list[ns].max_port = 1;
 			list[ns].phys_port = 1;
-			list[ns].phys_dev = ibv_match[i];
+			list[ns].phys_dev_name = ibv_match[i]->name;
+			list[ns].ctx = ctx;
 			list[ns].eth_dev = NULL;
 			list[ns].pci_dev = pci_dev;
 			list[ns].cdev = cdev;
@@ -2421,9 +2351,9 @@ mlx5_os_pci_probe_pf(struct mlx5_common_device *cdev,
 			list[ns].ifindex = 0;
 			if (nl_rdma >= 0)
 				list[ns].ifindex = mlx5_nl_ifindex
-				(nl_rdma,
-				mlx5_os_get_dev_device_name
-						(list[ns].phys_dev), 1);
+							    (nl_rdma,
+							     ibv_match[i]->name,
+							     1);
 			if (!list[ns].ifindex) {
 				char ifname[IF_NAMESIZE];
 
@@ -2473,9 +2403,8 @@ mlx5_os_pci_probe_pf(struct mlx5_common_device *cdev,
 				 * Netlink, let's try to perform the task
 				 * with sysfs.
 				 */
-				ret =  mlx5_sysfs_switch_info
-						(list[ns].ifindex,
-						 &list[ns].info);
+				ret = mlx5_sysfs_switch_info(list[ns].ifindex,
+							     &list[ns].info);
 			}
 			if (!ret && (list[ns].info.representor ^
 				     list[ns].info.master)) {
@@ -2484,21 +2413,19 @@ mlx5_os_pci_probe_pf(struct mlx5_common_device *cdev,
 				   !list[ns].info.representor &&
 				   !list[ns].info.master) {
 				/*
-				 * Single IB device with
-				 * one physical port and
+				 * Single IB device with one physical port and
 				 * attached network device.
-				 * May be SRIOV is not enabled
-				 * or there is no representors.
+				 * May be SRIOV is not enabled or there is no
+				 * representors.
 				 */
-				DRV_LOG(INFO, "no E-Switch support detected");
+				DRV_LOG(INFO, "No E-Switch support detected.");
 				ns++;
 				break;
 			}
 		}
 		if (!ns) {
 			DRV_LOG(ERR,
-				"unable to recognize master/representors"
-				" on the multiple IB devices");
+				"Unable to recognize master/representors on the multiple IB devices.");
 			rte_errno = ENOENT;
 			ret = -rte_errno;
 			goto exit;
@@ -2681,7 +2608,7 @@ mlx5_os_parse_eth_devargs(struct rte_device *dev,
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 static int
-mlx5_os_pci_probe(struct mlx5_common_device *cdev)
+mlx5_os_pci_probe(struct mlx5_common_device *cdev, void *ctx)
 {
 	struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(cdev->dev);
 	struct rte_eth_devargs eth_da = { .nb_ports = 0 };
@@ -2695,7 +2622,7 @@ mlx5_os_pci_probe(struct mlx5_common_device *cdev)
 	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, ctx, &eth_da,
 						   eth_da.ports[p]);
 			if (ret)
 				break;
@@ -2709,14 +2636,14 @@ mlx5_os_pci_probe(struct mlx5_common_device *cdev)
 			mlx5_net_remove(cdev);
 		}
 	} else {
-		ret = mlx5_os_pci_probe_pf(cdev, &eth_da, 0);
+		ret = mlx5_os_pci_probe_pf(cdev, ctx, &eth_da, 0);
 	}
 	return ret;
 }
 
 /* Probe a single SF device on auxiliary bus, no representor support. */
 static int
-mlx5_os_auxiliary_probe(struct mlx5_common_device *cdev)
+mlx5_os_auxiliary_probe(struct mlx5_common_device *cdev, void *ctx)
 {
 	struct rte_eth_devargs eth_da = { .nb_ports = 0 };
 	struct mlx5_dev_config config;
@@ -2736,9 +2663,8 @@ mlx5_os_auxiliary_probe(struct mlx5_common_device *cdev)
 	/* Init spawn data. */
 	spawn.max_port = 1;
 	spawn.phys_port = 1;
-	spawn.phys_dev = mlx5_os_get_ibv_dev(dev);
-	if (spawn.phys_dev == NULL)
-		return -rte_errno;
+	spawn.ctx = ctx;
+	spawn.phys_dev_name = mlx5_os_get_ctx_device_name(ctx);
 	ret = mlx5_auxiliary_get_ifindex(dev->name);
 	if (ret < 0) {
 		DRV_LOG(ERR, "failed to get ethdev ifindex: %s", dev->name);
@@ -2776,48 +2702,28 @@ int
 mlx5_os_net_probe(struct mlx5_common_device *cdev)
 {
 	int ret;
+	void *ctx = NULL;
 
-	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+		ret = mlx5_os_open_device(cdev, &ctx);
+		if (ret) {
+			DRV_LOG(ERR, "Fail to open device %s", cdev->dev->name);
+			return -rte_errno;
+		}
 		mlx5_pmd_socket_init();
+	}
 	ret = mlx5_init_once();
 	if (ret) {
 		DRV_LOG(ERR, "Unable to init PMD global data: %s",
 			strerror(rte_errno));
+		if (ctx != NULL)
+			claim_zero(mlx5_glue->close_device(ctx));
 		return -rte_errno;
 	}
 	if (mlx5_dev_is_pci(cdev->dev))
-		return mlx5_os_pci_probe(cdev);
-	else
-		return mlx5_os_auxiliary_probe(cdev);
-}
-
-static int
-mlx5_config_doorbell_mapping_env(const struct mlx5_common_dev_config *config)
-{
-	char *env;
-	int value;
-
-	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
-	/* Get environment variable to store. */
-	env = getenv(MLX5_SHUT_UP_BF);
-	value = env ? !!strcmp(env, "0") : MLX5_ARG_UNSET;
-	if (config->dbnc == MLX5_ARG_UNSET)
-		setenv(MLX5_SHUT_UP_BF, MLX5_SHUT_UP_BF_DEFAULT, 1);
+		return mlx5_os_pci_probe(cdev, ctx);
 	else
-		setenv(MLX5_SHUT_UP_BF,
-		       config->dbnc == MLX5_TXDB_NCACHED ? "1" : "0", 1);
-	return value;
-}
-
-static void
-mlx5_restore_doorbell_mapping_env(int value)
-{
-	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
-	/* Restore the original environment variable state. */
-	if (value == MLX5_ARG_UNSET)
-		unsetenv(MLX5_SHUT_UP_BF);
-	else
-		setenv(MLX5_SHUT_UP_BF, value ? "1" : "0", 1);
+		return mlx5_os_auxiliary_probe(cdev, ctx);
 }
 
 /**
@@ -2855,69 +2761,6 @@ mlx5_os_get_pdn(void *pd, uint32_t *pdn)
 #endif /* HAVE_IBV_FLOW_DV_SUPPORT */
 }
 
-/**
- * Function API to open IB device.
- *
- * This function calls the Linux glue APIs to open a device.
- *
- * @param[in] spawn
- *   Pointer to the IB device attributes (name, port, etc).
- * @param[out] sh
- *   Pointer to shared context structure.
- *
- * @return
- *   0 on success, a positive error value otherwise.
- */
-int
-mlx5_os_open_device(const struct mlx5_dev_spawn_data *spawn,
-		     struct mlx5_dev_ctx_shared *sh)
-{
-	int dbmap_env;
-	int err = 0;
-
-	pthread_mutex_init(&sh->txpp.mutex, NULL);
-	/*
-	 * Configure environment variable "MLX5_BF_SHUT_UP"
-	 * before the device creation. The rdma_core library
-	 * checks the variable at device creation and
-	 * stores the result internally.
-	 */
-	dbmap_env = mlx5_config_doorbell_mapping_env(&spawn->cdev->config);
-	/* Try to open IB device with DV first, then usual Verbs. */
-	errno = 0;
-	sh->ctx = mlx5_glue->dv_open_device(spawn->phys_dev);
-	if (sh->ctx) {
-		sh->devx = 1;
-		DRV_LOG(DEBUG, "DevX is supported");
-		/* The device is created, no need for environment. */
-		mlx5_restore_doorbell_mapping_env(dbmap_env);
-	} else {
-		/* The environment variable is still configured. */
-		sh->ctx = mlx5_glue->open_device(spawn->phys_dev);
-		err = errno ? errno : ENODEV;
-		/*
-		 * The environment variable is not needed anymore,
-		 * all device creation attempts are completed.
-		 */
-		mlx5_restore_doorbell_mapping_env(dbmap_env);
-		if (!sh->ctx)
-			return err;
-		DRV_LOG(DEBUG, "DevX is NOT supported");
-		err = 0;
-	}
-	if (!err && sh->ctx) {
-		/* Hint libmlx5 to use PMD allocator for data plane resources */
-		mlx5_glue->dv_set_context_attr(sh->ctx,
-			MLX5DV_CTX_ATTR_BUF_ALLOCATORS,
-			(void *)((uintptr_t)&(struct mlx5dv_ctx_allocators){
-				.alloc = &mlx5_alloc_verbs_buf,
-				.free = &mlx5_free_verbs_buf,
-				.data = sh,
-			}));
-	}
-	return err;
-}
-
 /**
  * Install shared asynchronous device events handler.
  * This function is implemented to support event sharing
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index b5af21b0f6..bfdce8da72 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -1262,7 +1262,7 @@ mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn,
 	/* Search for IB context by device name. */
 	LIST_FOREACH(sh, &mlx5_dev_ctx_list, next) {
 		if (!strcmp(sh->ibdev_name,
-			mlx5_os_get_dev_device_name(spawn->phys_dev))) {
+			mlx5_os_get_ctx_device_name(spawn->ctx))) {
 			sh->refcnt++;
 			goto exit;
 		}
@@ -1279,13 +1279,13 @@ mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn,
 		rte_errno  = ENOMEM;
 		goto exit;
 	}
+	pthread_mutex_init(&sh->txpp.mutex, NULL);
 	sh->numa_node = spawn->cdev->dev->numa_node;
 	sh->cdev = spawn->cdev;
+	sh->devx = sh->cdev->config.devx;
+	sh->ctx = spawn->ctx;
 	if (spawn->bond_info)
 		sh->bond = *spawn->bond_info;
-	err = mlx5_os_open_device(spawn, sh);
-	if (!sh->ctx)
-		goto error;
 	err = mlx5_os_get_dev_attr(sh->ctx, &sh->device_attr);
 	if (err) {
 		DRV_LOG(DEBUG, "mlx5_os_get_dev_attr() failed");
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 4c8e633fb6..becd8722de 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -136,7 +136,8 @@ struct mlx5_dev_spawn_data {
 	uint32_t phys_port; /**< Device physical port index. */
 	int pf_bond; /**< bonding device PF index. < 0 - no bonding */
 	struct mlx5_switch_info info; /**< Switch information. */
-	void *phys_dev; /**< Associated physical device. */
+	const char *phys_dev_name; /**< Name of physical device. */
+	void *ctx; /**< Associated physical device context. */
 	struct rte_eth_dev *eth_dev; /**< Associated Ethernet device. */
 	struct rte_pci_device *pci_dev; /**< Backend PCI device. */
 	struct mlx5_common_device *cdev; /**< Backend common device. */
@@ -1771,8 +1772,6 @@ void mlx5_flow_meter_rxq_flush(struct rte_eth_dev *dev);
 struct rte_pci_driver;
 int mlx5_os_get_dev_attr(void *ctx, struct mlx5_dev_attr *dev_attr);
 void mlx5_os_free_shared_dr(struct mlx5_priv *priv);
-int mlx5_os_open_device(const struct mlx5_dev_spawn_data *spawn,
-			 struct mlx5_dev_ctx_shared *sh);
 int mlx5_os_get_pdn(void *pd, uint32_t *pdn);
 int mlx5_os_net_probe(struct mlx5_common_device *cdev);
 void mlx5_os_dev_shared_handler_install(struct mlx5_dev_ctx_shared *sh);
diff --git a/drivers/net/mlx5/windows/mlx5_os.c b/drivers/net/mlx5/windows/mlx5_os.c
index 90e21479e3..1e76f63fc1 100644
--- a/drivers/net/mlx5/windows/mlx5_os.c
+++ b/drivers/net/mlx5/windows/mlx5_os.c
@@ -253,46 +253,6 @@ mlx5_os_set_nonblock_channel_fd(int fd)
 	return -ENOTSUP;
 }
 
-/**
- * Function API open device under Windows
- *
- * This function calls the Windows glue APIs to open a device.
- *
- * @param[in] spawn
- *   Pointer to the device attributes (name, port, etc).
- * @param[out] sh
- *   Pointer to shared context structure.
- *
- * @return
- *   0 on success, a positive error value otherwise.
- */
-int
-mlx5_os_open_device(const struct mlx5_dev_spawn_data *spawn,
-		 struct mlx5_dev_ctx_shared *sh)
-{
-	int err = 0;
-	struct mlx5_context *mlx5_ctx;
-
-	pthread_mutex_init(&sh->txpp.mutex, NULL);
-	/* Set numa node from pci probe */
-	sh->numa_node = spawn->pci_dev->device.numa_node;
-
-	/* Try to open device with DevX */
-	rte_errno = 0;
-	sh->ctx = mlx5_glue->open_device(spawn->phys_dev);
-	if (!sh->ctx) {
-		DRV_LOG(ERR, "open_device failed");
-		err = errno;
-		return err;
-	}
-	sh->devx = 1;
-	mlx5_ctx = (struct mlx5_context *)sh->ctx;
-	err = mlx5_glue->query_device(spawn->phys_dev, &mlx5_ctx->mlx5_dev);
-	if (err)
-		DRV_LOG(ERR, "Failed to query device context fields.");
-	return err;
-}
-
 /**
  * DV flow counter mode detect and config.
  *
@@ -909,114 +869,6 @@ mlx5_os_set_allmulti(struct rte_eth_dev *dev, int enable)
 	return -ENOTSUP;
 }
 
-/**
- * Detect if a devx_device_bdf object has identical DBDF values to the
- * rte_pci_addr found in bus/pci probing
- *
- * @param[in] devx_bdf
- *   Pointer to the devx_device_bdf structure.
- * @param[in] addr
- *   Pointer to the rte_pci_addr structure.
- *
- * @return
- *   1 on Device match, 0 on mismatch.
- */
-static int
-mlx5_match_devx_bdf_to_addr(struct devx_device_bdf *devx_bdf,
-			    struct rte_pci_addr *addr)
-{
-	if (addr->domain != (devx_bdf->bus_id >> 8) ||
-	    addr->bus != (devx_bdf->bus_id & 0xff) ||
-	    addr->devid != devx_bdf->dev_id ||
-	    addr->function != devx_bdf->fnc_id) {
-		return 0;
-	}
-	return 1;
-}
-
-/**
- * Detect if a devx_device_bdf object matches the rte_pci_addr
- * found in bus/pci probing
- * Compare both the Native/PF BDF and the raw_bdf representing a VF BDF.
- *
- * @param[in] devx_bdf
- *   Pointer to the devx_device_bdf structure.
- * @param[in] addr
- *   Pointer to the rte_pci_addr structure.
- *
- * @return
- *   1 on Device match, 0 on mismatch, rte_errno code on failure.
- */
-static int
-mlx5_match_devx_devices_to_addr(struct devx_device_bdf *devx_bdf,
-				struct rte_pci_addr *addr)
-{
-	int err;
-	struct devx_device mlx5_dev;
-
-	if (mlx5_match_devx_bdf_to_addr(devx_bdf, addr))
-		return 1;
-	/*
-	 * Didn't match on Native/PF BDF, could still match a VF BDF,
-	 * check it next.
-	 */
-	err = mlx5_glue->query_device(devx_bdf, &mlx5_dev);
-	if (err) {
-		DRV_LOG(ERR, "query_device failed");
-		rte_errno = err;
-		return rte_errno;
-	}
-	if (mlx5_match_devx_bdf_to_addr(&mlx5_dev.raw_bdf, addr))
-		return 1;
-	return 0;
-}
-
-/**
- * Look for DevX device that match to given rte_device.
- *
- * @param dev
- *   Pointer to the generic device.
- * @param orig_devx_list
- *   Pointer to head of DevX devices list.
- * @param n
- *   Number of devices in given DevX devices list.
- *
- * @return
- *   A device match on success, NULL otherwise and rte_errno is set.
- */
-static struct devx_device_bdf *
-mlx5_os_get_devx_device(struct rte_device *dev,
-			struct devx_device_bdf *orig_devx_list, int n)
-{
-	struct devx_device_bdf *devx_list = orig_devx_list;
-	struct devx_device_bdf *devx_match = NULL;
-	struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev);
-	struct rte_pci_addr *addr = &pci_dev->addr;
-
-	while (n-- > 0) {
-		int ret = mlx5_match_devx_devices_to_addr(devx_list, addr);
-		if (!ret) {
-			devx_list++;
-			continue;
-		}
-		if (ret != 1) {
-			rte_errno = ret;
-			return NULL;
-		}
-		devx_match = devx_list;
-		break;
-	}
-	if (devx_match == NULL) {
-		/* No device matches, just complain and bail out. */
-		DRV_LOG(WARNING,
-			"No DevX device matches PCI device " PCI_PRI_FMT ","
-			" is DevX Configured?",
-			addr->domain, addr->bus, addr->devid, addr->function);
-		rte_errno = ENOENT;
-	}
-	return devx_match;
-}
-
 /**
  * DPDK callback to register a PCI device.
  *
@@ -1032,8 +884,6 @@ int
 mlx5_os_net_probe(struct mlx5_common_device *cdev)
 {
 	struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(cdev->dev);
-	struct devx_device_bdf *devx_list;
-	struct devx_device_bdf *devx_bdf_match;
 	struct mlx5_dev_spawn_data spawn = {
 		.pf_bond = -1,
 		.max_port = 1,
@@ -1058,33 +908,28 @@ mlx5_os_net_probe(struct mlx5_common_device *cdev)
 		.dv_flow_en = 1,
 		.log_hp_size = MLX5_ARG_UNSET,
 	};
+	void *ctx;
 	int ret;
-	int n;
 	uint32_t restore;
 
 	if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
 		DRV_LOG(ERR, "Secondary process is not supported on Windows.");
 		return -ENOTSUP;
 	}
+	ret = mlx5_os_open_device(cdev, &ctx);
+	if (ret) {
+		DRV_LOG(ERR, "Fail to open DevX device %s", cdev->dev->name);
+		return -rte_errno;
+	}
 	ret = mlx5_init_once();
 	if (ret) {
 		DRV_LOG(ERR, "unable to init PMD global data: %s",
 			strerror(rte_errno));
+		claim_zero(mlx5_glue->close_device(ctx));
 		return -rte_errno;
 	}
-	errno = 0;
-	devx_list = mlx5_glue->get_device_list(&n);
-	if (devx_list == NULL) {
-		rte_errno = errno ? errno : ENOSYS;
-		DRV_LOG(ERR, "Cannot list devices, is DevX enabled?");
-		return -rte_errno;
-	}
-	devx_bdf_match = mlx5_os_get_devx_device(cdev->dev, devx_list, n);
-	if (devx_bdf_match == NULL) {
-		ret = -rte_errno;
-		goto exit;
-	}
-	spawn.phys_dev = devx_bdf_match;
+	spawn.ctx = ctx;
+	spawn.phys_dev_name = mlx5_os_get_ctx_device_name(ctx);
 	/* Device specific configuration. */
 	switch (pci_dev->id.device_id) {
 	case PCI_DEVICE_ID_MELLANOX_CONNECTX4VF:
@@ -1102,17 +947,15 @@ mlx5_os_net_probe(struct mlx5_common_device *cdev)
 	}
 	spawn.eth_dev = mlx5_dev_spawn(cdev->dev, &spawn, &dev_config);
 	if (!spawn.eth_dev) {
-		ret = -rte_errno;
-		goto exit;
+		claim_zero(mlx5_glue->close_device(ctx));
+		return -rte_errno;
 	}
 	restore = spawn.eth_dev->data->dev_flags;
 	rte_eth_copy_pci_info(spawn.eth_dev, pci_dev);
 	/* Restore non-PCI flags cleared by the above call. */
 	spawn.eth_dev->data->dev_flags |= restore;
 	rte_eth_dev_probing_finish(spawn.eth_dev);
-exit:
-	mlx5_glue->free_device_list(devx_list);
-	return ret;
+	return 0;
 }
 
 /**
