[RFC,2/3] common/mlx5: add shared PD support

Message ID 20220102070638.2211160-3-michaelba@nvidia.com (mailing list archive)
State RFC, archived
Delegated to: Raslan Darawsheh
Headers
Series net/mlx5: add external RxQ support |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Michael Baum Jan. 2, 2022, 7:06 a.m. UTC
  From: Michael Baum <michaelba@nvidia.com>

Add option to probe common device using import CTX/PD functions instead
of create functions.
This option requires accepting the context FD and the PD handle as
devargs.

Signed-off-by: Michael Baum <michaelba@nvidia.com>
---
 drivers/common/mlx5/linux/mlx5_common_os.c   | 160 +++++++++++++++++--
 drivers/common/mlx5/linux/mlx5_common_os.h   |   6 -
 drivers/common/mlx5/mlx5_common.c            |  32 ++--
 drivers/common/mlx5/mlx5_common.h            |   6 +-
 drivers/common/mlx5/windows/mlx5_common_os.c |  29 +++-
 drivers/common/mlx5/windows/mlx5_common_os.h |   1 -
 6 files changed, 196 insertions(+), 38 deletions(-)
  

Patch

diff --git a/drivers/common/mlx5/linux/mlx5_common_os.c b/drivers/common/mlx5/linux/mlx5_common_os.c
index 0d3e24e04e..a8226e987f 100644
--- a/drivers/common/mlx5/linux/mlx5_common_os.c
+++ b/drivers/common/mlx5/linux/mlx5_common_os.c
@@ -416,7 +416,7 @@  mlx5_glue_constructor(void)
  * @return
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
-int
+static int
 mlx5_os_pd_create(struct mlx5_common_device *cdev)
 {
 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
@@ -450,6 +450,65 @@  mlx5_os_pd_create(struct mlx5_common_device *cdev)
 #endif /* HAVE_IBV_FLOW_DV_SUPPORT */
 }
 
+/**
+ * Import Protection Domain object according to given pdn.
+ *
+ * @param[out] cdev
+ *   Pointer to the mlx5 device.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+mlx5_os_pd_import(struct mlx5_common_device *cdev)
+{
+	struct mlx5_common_dev_config *config = &cdev->config;
+
+	cdev->pd = mlx5_glue->import_pd(cdev->ctx, config->pd_handle);
+	if (cdev->pd == NULL) {
+		DRV_LOG(ERR, "Failed to import PD.");
+		return errno ? -errno : -ENOMEM;
+	}
+	cdev->pdn = config->pd_handle;
+	return 0;
+}
+
+/**
+ * Prepare Protection Domain object and extract its pdn using DV API.
+ *
+ * @param[out] cdev
+ *   Pointer to the mlx5 device.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+int
+mlx5_os_pd_prepare(struct mlx5_common_device *cdev)
+{
+	if (cdev->config.pd_handle == MLX5_ARG_UNSET)
+		return mlx5_os_pd_create(cdev);
+	else
+		return mlx5_os_pd_import(cdev);
+}
+
+/**
+ * Release Protection Domain object.
+ *
+ * @param[out] cdev
+ *   Pointer to the mlx5 device.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise.
+ */
+int
+mlx5_os_pd_release(struct mlx5_common_device *cdev)
+{
+	if (cdev->config.pd_handle == MLX5_ARG_UNSET)
+		return mlx5_glue->dealloc_pd(cdev->pd);
+	mlx5_glue->unimport_pd(cdev->pd);
+	return 0;
+}
+
 static struct ibv_device *
 mlx5_os_get_ibv_device(const struct rte_pci_addr *addr)
 {
@@ -648,28 +707,28 @@  mlx5_restore_doorbell_mapping_env(int value)
 /**
  * Function API to open IB device.
  *
- *
  * @param cdev
  *   Pointer to the mlx5 device.
  * @param classes
  *   Chosen classes come from device arguments.
  *
  * @return
- *   0 on success, a negative errno value otherwise and rte_errno is set.
+ *   Pointer to ibv_context on success, NULL otherwise and rte_errno is set.
  */
-int
-mlx5_os_open_device(struct mlx5_common_device *cdev, uint32_t classes)
+static struct ibv_context *
+mlx5_open_device(struct mlx5_common_device *cdev, uint32_t classes)
 {
 	struct ibv_device *ibv;
 	struct ibv_context *ctx = NULL;
 	int dbmap_env;
 
+	MLX5_ASSERT(cdev->config.device_fd == MLX5_ARG_UNSET);
 	if (classes & MLX5_CLASS_VDPA)
 		ibv = mlx5_vdpa_get_ibv_dev(cdev->dev);
 	else
 		ibv = mlx5_os_get_ibv_dev(cdev->dev);
 	if (!ibv)
-		return -rte_errno;
+		return NULL;
 	DRV_LOG(INFO, "Dev information matches for device \"%s\".", ibv->name);
 	/*
 	 * Configure environment variable "MLX5_BF_SHUT_UP" before the device
@@ -682,29 +741,104 @@  mlx5_os_open_device(struct mlx5_common_device *cdev, uint32_t classes)
 	ctx = mlx5_glue->dv_open_device(ibv);
 	if (ctx) {
 		cdev->config.devx = 1;
-		DRV_LOG(DEBUG, "DevX is supported.");
 	} else if (classes == MLX5_CLASS_ETH) {
 		/* The environment variable is still configured. */
 		ctx = mlx5_glue->open_device(ibv);
 		if (ctx == NULL)
 			goto error;
-		DRV_LOG(DEBUG, "DevX is NOT supported.");
 	} else {
 		goto error;
 	}
 	/* 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);
-	cdev->ctx = ctx;
-	return 0;
+	return ctx;
 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;
+	return NULL;
 }
+
+/**
+ * Function API to import IB device.
+ *
+ * @param cdev
+ *   Pointer to the mlx5 device.
+ *
+ * @return
+ *   Pointer to ibv_context on success, NULL otherwise and rte_errno is set.
+ */
+static struct ibv_context *
+mlx5_import_device(struct mlx5_common_device *cdev)
+{
+	struct ibv_context *ctx = NULL;
+
+	MLX5_ASSERT(cdev->config.device_fd != MLX5_ARG_UNSET);
+	ctx = mlx5_glue->import_device(cdev->config.device_fd);
+	if (!ctx) {
+		DRV_LOG(ERR, "Failed to import device for fd=%d.",
+			cdev->config.device_fd);
+		rte_errno = errno;
+	}
+	return ctx;
+}
+
+/**
+ * Function API to prepare IB device.
+ *
+ * @param cdev
+ *   Pointer to the mlx5 device.
+ * @param classes
+ *   Chosen classes come from device arguments.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+int
+mlx5_os_open_device(struct mlx5_common_device *cdev, uint32_t classes)
+{
+
+	struct ibv_context *ctx = NULL;
+
+	if (cdev->config.device_fd == MLX5_ARG_UNSET)
+		ctx = mlx5_open_device(cdev, classes);
+	else
+		ctx = mlx5_import_device(cdev);
+	if (ctx == NULL)
+		return -rte_errno;
+	/* Hint libmlx5 to use PMD allocator for data plane resources */
+	mlx5_set_context_attr(cdev->dev, ctx);
+	cdev->ctx = ctx;
+	return 0;
+}
+
+/**
+ * Query HCA attributes.
+ * For remote context, it is check if DevX is supported.
+ *
+ * @param cdev
+ *   Pointer to mlx5 device structure.
+ *
+ * @return
+ *   0 on success, a negative value otherwise.
+ */
+int
+mlx5_os_query_hca_attr(struct mlx5_common_device *cdev)
+{
+	int ret;
+
+	ret = mlx5_devx_cmd_query_hca_attr(cdev->ctx, &cdev->config.hca_attr);
+	if (ret) {
+		if (cdev->config.device_fd == MLX5_ARG_UNSET) {
+			rte_errno = ENOTSUP;
+			return -rte_errno;
+		}
+		cdev->config.devx = 0;
+	}
+	return 0;
+}
+
 int
 mlx5_get_device_guid(const struct rte_pci_addr *dev, uint8_t *guid, size_t len)
 {
diff --git a/drivers/common/mlx5/linux/mlx5_common_os.h b/drivers/common/mlx5/linux/mlx5_common_os.h
index 83066e752d..246e8b2784 100644
--- a/drivers/common/mlx5/linux/mlx5_common_os.h
+++ b/drivers/common/mlx5/linux/mlx5_common_os.h
@@ -203,12 +203,6 @@  mlx5_os_get_devx_uar_page_id(void *uar)
 #endif
 }
 
-static inline int
-mlx5_os_dealloc_pd(void *pd)
-{
-	return mlx5_glue->dealloc_pd(pd);
-}
-
 __rte_internal
 static inline void *
 mlx5_os_umem_reg(void *ctx, void *addr, size_t size, uint32_t access)
diff --git a/drivers/common/mlx5/mlx5_common.c b/drivers/common/mlx5/mlx5_common.c
index f1650f94c6..bd7f0021d5 100644
--- a/drivers/common/mlx5/mlx5_common.c
+++ b/drivers/common/mlx5/mlx5_common.c
@@ -133,6 +133,10 @@  mlx5_common_args_check_handler(const char *key, const char *val, void *opaque)
 		config->mr_mempool_reg_en = !!tmp;
 	} else if (strcmp(key, "sys_mem_en") == 0) {
 		config->sys_mem_en = !!tmp;
+	} else if (strcmp(key, "device_fd") == 0) {
+		config->device_fd = !!tmp;
+	} else if (strcmp(key, "pd_handle") == 0) {
+		config->pd_handle = !!tmp;
 	}
 	return 0;
 }
@@ -160,6 +164,8 @@  mlx5_common_config_get(struct rte_devargs *devargs,
 	config->mr_mempool_reg_en = 1;
 	config->sys_mem_en = 0;
 	config->dbnc = MLX5_ARG_UNSET;
+	config->device_fd = MLX5_ARG_UNSET;
+	config->pd_handle = MLX5_ARG_UNSET;
 	if (devargs == NULL)
 		return 0;
 	kvlist = rte_kvargs_parse(devargs->args, NULL);
@@ -492,7 +498,7 @@  static void
 mlx5_dev_hw_global_release(struct mlx5_common_device *cdev)
 {
 	if (cdev->pd != NULL) {
-		claim_zero(mlx5_os_dealloc_pd(cdev->pd));
+		claim_zero(mlx5_os_pd_release(cdev));
 		cdev->pd = NULL;
 	}
 	if (cdev->ctx != NULL) {
@@ -522,19 +528,23 @@  mlx5_dev_hw_global_prepare(struct mlx5_common_device *cdev, uint32_t classes)
 	if (ret < 0)
 		return ret;
 	/* Allocate Protection Domain object and extract its pdn. */
-	ret = mlx5_os_pd_create(cdev);
+	ret = mlx5_os_pd_prepare(cdev);
 	if (ret)
 		goto error;
-	/* All actions taken below are relevant only when DevX is supported */
-	if (cdev->config.devx == 0)
-		return 0;
-	/* Query HCA attributes. */
-	ret = mlx5_devx_cmd_query_hca_attr(cdev->ctx, &cdev->config.hca_attr);
-	if (ret) {
-		DRV_LOG(ERR, "Unable to read HCA capabilities.");
-		rte_errno = ENOTSUP;
-		goto error;
+	/*
+	 * TODO: write it again...
+	 * All actions taken below are relevant only when DevX is supported
+	 */
+	if (cdev->config.devx || cdev->config.device_fd != MLX5_ARG_UNSET) {
+		/* Query HCA attributes. */
+		ret = mlx5_os_query_hca_attr(cdev);
+		if (ret) {
+			DRV_LOG(ERR, "Unable to read HCA capabilities.");
+			rte_errno = ENOTSUP;
+			goto error;
+		}
 	}
+	DRV_LOG(DEBUG, "DevX is %ssupported.", cdev->config.devx ? "" : "NOT ");
 	return 0;
 error:
 	mlx5_dev_hw_global_release(cdev);
diff --git a/drivers/common/mlx5/mlx5_common.h b/drivers/common/mlx5/mlx5_common.h
index e8809844af..78c8a29740 100644
--- a/drivers/common/mlx5/mlx5_common.h
+++ b/drivers/common/mlx5/mlx5_common.h
@@ -414,6 +414,8 @@  void mlx5_common_init(void);
 struct mlx5_common_dev_config {
 	struct mlx5_hca_attr hca_attr; /* HCA attributes. */
 	int dbnc; /* Skip doorbell register write barrier. */
+	int device_fd; /* Device file descriptor for importation. */
+	int pd_handle; /* Protection Domain handle for importation.  */
 	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;
@@ -507,7 +509,9 @@  mlx5_devx_uar_release(struct mlx5_uar *uar);
 /* mlx5_common_os.c */
 
 int mlx5_os_open_device(struct mlx5_common_device *cdev, uint32_t classes);
-int mlx5_os_pd_create(struct mlx5_common_device *cdev);
+int mlx5_os_query_hca_attr(struct mlx5_common_device *cdev);
+int mlx5_os_pd_prepare(struct mlx5_common_device *cdev);
+int mlx5_os_pd_release(struct mlx5_common_device *cdev);
 
 /* mlx5 PMD wrapped MR struct. */
 struct mlx5_pmd_wrapped_mr {
diff --git a/drivers/common/mlx5/windows/mlx5_common_os.c b/drivers/common/mlx5/windows/mlx5_common_os.c
index 162c7476cc..d8410f57c1 100644
--- a/drivers/common/mlx5/windows/mlx5_common_os.c
+++ b/drivers/common/mlx5/windows/mlx5_common_os.c
@@ -25,21 +25,38 @@  mlx5_glue_constructor(void)
 {
 }
 
+/**
+ * Query HCA attributes.
+ *
+ * @param cdev
+ *   Pointer to mlx5 device structure.
+ *
+ * @return
+ *   0 on success, a negative value otherwise.
+ */
+int
+mlx5_os_query_hca_attr(struct mlx5_common_device *cdev)
+{
+	return mlx5_devx_cmd_query_hca_attr(cdev->ctx, &cdev->config.hca_attr);
+}
+
 /**
  * Release PD. Releases a given mlx5_pd object
  *
- * @param[in] pd
- *   Pointer to mlx5_pd.
+ * @param[in] cdev
+ *   Pointer to the mlx5 device.
  *
  * @return
  *   Zero if pd is released successfully, negative number otherwise.
  */
 int
-mlx5_os_dealloc_pd(void *pd)
+mlx5_os_pd_release(struct mlx5_common_device *cdev)
 {
+	struct mlx5_pd *pd = cdev->pd;
+
 	if (!pd)
 		return -EINVAL;
-	mlx5_devx_cmd_destroy(((struct mlx5_pd *)pd)->obj);
+	mlx5_devx_cmd_destroy(pd->obj);
 	mlx5_free(pd);
 	return 0;
 }
@@ -47,14 +64,14 @@  mlx5_os_dealloc_pd(void *pd)
 /**
  * Allocate Protection Domain object and extract its pdn using DV API.
  *
- * @param[out] dev
+ * @param[out] cdev
  *   Pointer to the mlx5 device.
  *
  * @return
  *   0 on success, a negative value otherwise.
  */
 int
-mlx5_os_pd_create(struct mlx5_common_device *cdev)
+mlx5_os_pd_prepare(struct mlx5_common_device *cdev)
 {
 	struct mlx5_pd *pd;
 
diff --git a/drivers/common/mlx5/windows/mlx5_common_os.h b/drivers/common/mlx5/windows/mlx5_common_os.h
index 3afce56cd9..a6a1b6890f 100644
--- a/drivers/common/mlx5/windows/mlx5_common_os.h
+++ b/drivers/common/mlx5/windows/mlx5_common_os.h
@@ -248,7 +248,6 @@  mlx5_os_devx_subscribe_devx_event(void *eventc,
 	return -ENOTSUP;
 }
 
-int mlx5_os_dealloc_pd(void *pd);
 __rte_internal
 void *mlx5_os_umem_reg(void *ctx, void *addr, size_t size, uint32_t access);
 __rte_internal