[20/20] common/mlx5: refactor devargs management

Message ID 20220127153950.812953-21-michaelba@nvidia.com (mailing list archive)
State Superseded, archived
Delegated to: Raslan Darawsheh
Headers
Series mlx5: refactor devargs management |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation warning apply issues

Commit Message

Michael Baum Jan. 27, 2022, 3:39 p.m. UTC
Improve the devargs handling in two aspects:
 - Parse the devargs string only once.
 - Return error and report for unknown keys.

The common driver parses once the devargs string into a dictionary, then
provides it to all the drivers' probe. Each driver updates within it
which keys it has used, then common driver receives the updated
dictionary and reports about unknown devargs.

Signed-off-by: Michael Baum <michaelba@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>
---
 drivers/common/mlx5/mlx5_common.c     | 255 +++++++++++++++++++++-----
 drivers/common/mlx5/mlx5_common.h     |  36 +++-
 drivers/common/mlx5/version.map       |   2 +
 drivers/compress/mlx5/mlx5_compress.c |  38 ++--
 drivers/crypto/mlx5/mlx5_crypto.c     |  39 ++--
 drivers/net/mlx5/linux/mlx5_os.c      |  47 +++--
 drivers/net/mlx5/mlx5.c               | 212 ++++++++++++++-------
 drivers/net/mlx5/mlx5.h               |  14 +-
 drivers/net/mlx5/windows/mlx5_os.c    |  18 +-
 drivers/regex/mlx5/mlx5_regex.c       |   3 +-
 drivers/vdpa/mlx5/mlx5_vdpa.c         |  32 ++--
 11 files changed, 498 insertions(+), 198 deletions(-)
  

Patch

diff --git a/drivers/common/mlx5/mlx5_common.c b/drivers/common/mlx5/mlx5_common.c
index f74d27e74d..96906d3f39 100644
--- a/drivers/common/mlx5/mlx5_common.c
+++ b/drivers/common/mlx5/mlx5_common.c
@@ -21,6 +21,24 @@ 
 
 uint8_t haswell_broadwell_cpu;
 
+/* Driver type key for new device global syntax. */
+#define MLX5_DRIVER_KEY "driver"
+
+/* Enable extending memsegs when creating a MR. */
+#define MLX5_MR_EXT_MEMSEG_EN "mr_ext_memseg_en"
+
+/* Device parameter to configure implicit registration of mempool memory. */
+#define MLX5_MR_MEMPOOL_REG_EN "mr_mempool_reg_en"
+
+/* The default memory allocator used in PMD. */
+#define MLX5_SYS_MEM_EN "sys_mem_en"
+
+/*
+ * Device parameter to force doorbell register mapping
+ * to non-cahed region eliminating the extra write memory barrier.
+ */
+#define MLX5_TX_DB_NC "tx_db_nc"
+
 /* In case this is an x86_64 intel processor to check if
  * we should use relaxed ordering.
  */
@@ -92,6 +110,122 @@  driver_get(uint32_t class)
 	return NULL;
 }
 
+int
+mlx5_kvargs_process(struct mlx5_kvargs_ctrl *mkvlist, const char *const keys[],
+		    arg_handler_t handler, void *opaque_arg)
+{
+	const struct rte_kvargs_pair *pair;
+	uint32_t i, j;
+
+	MLX5_ASSERT(mkvlist && mkvlist->kvlist);
+	/* Process parameters. */
+	for (i = 0; i < mkvlist->kvlist->count; i++) {
+		pair = &mkvlist->kvlist->pairs[i];
+		for (j = 0; keys[j] != NULL; ++j) {
+			if (strcmp(pair->key, keys[j]) != 0)
+				continue;
+			if ((*handler)(pair->key, pair->value, opaque_arg) < 0)
+				return -1;
+			mkvlist->is_used[i] = true;
+			break;
+		}
+	}
+	return 0;
+}
+
+/**
+ * Prepare a mlx5 kvargs control.
+ *
+ * @param[out] mkvlist
+ *   Pointer to mlx5 kvargs control.
+ * @param[in] devargs
+ *   The input string containing the key/value associations.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+mlx5_kvargs_prepare(struct mlx5_kvargs_ctrl *mkvlist,
+		    const struct rte_devargs *devargs)
+{
+	struct rte_kvargs *kvlist;
+	uint32_t i;
+
+	if (devargs == NULL)
+		return 0;
+	kvlist = rte_kvargs_parse(devargs->args, NULL);
+	if (kvlist == NULL) {
+		rte_errno = EINVAL;
+		return -rte_errno;
+	}
+	/*
+	 * rte_kvargs_parse enable key without value, in mlx5 PMDs we disable
+	 * this syntax.
+	 */
+	for (i = 0; i < kvlist->count; i++) {
+		const struct rte_kvargs_pair *pair = &kvlist->pairs[i];
+		if (pair->value == NULL || *(pair->value) == '\0') {
+			DRV_LOG(ERR, "Key %s is missing value.", pair->key);
+			rte_kvargs_free(kvlist);
+			rte_errno = EINVAL;
+			return -rte_errno;
+		}
+	}
+	/* Makes sure all devargs used array is false. */
+	memset(mkvlist, 0, sizeof(*mkvlist));
+	mkvlist->kvlist = kvlist;
+	DRV_LOG(DEBUG, "Parse successfully %u devargs.",
+		mkvlist->kvlist->count);
+	return 0;
+}
+
+/**
+ * Release a mlx5 kvargs control.
+ *
+ * @param[out] mkvlist
+ *   Pointer to mlx5 kvargs control.
+ */
+static void
+mlx5_kvargs_release(struct mlx5_kvargs_ctrl *mkvlist)
+{
+	if (mkvlist == NULL)
+		return;
+	rte_kvargs_free(mkvlist->kvlist);
+	memset(mkvlist, 0, sizeof(*mkvlist));
+}
+
+/**
+ * Validate device arguments list.
+ * It report about the first unknown parameter.
+ *
+ * @param[in] mkvlist
+ *   Pointer to mlx5 kvargs control.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+mlx5_kvargs_validate(struct mlx5_kvargs_ctrl *mkvlist)
+{
+	uint32_t i;
+
+	/* Secondary process should not handle devargs. */
+	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+		return 0;
+	if (mkvlist == NULL)
+		return 0;
+	for (i = 0; i < mkvlist->kvlist->count; i++) {
+		if (mkvlist->is_used[i] == 0) {
+			DRV_LOG(ERR, "Key \"%s\" "
+				"is unknown for the provided classes.",
+				mkvlist->kvlist->pairs[i].key);
+			rte_errno = EINVAL;
+			return -rte_errno;
+		}
+	}
+	return 0;
+}
+
 /**
  * Verify and store value for devargs.
  *
@@ -111,11 +245,9 @@  mlx5_common_args_check_handler(const char *key, const char *val, void *opaque)
 	struct mlx5_common_dev_config *config = opaque;
 	signed long tmp;
 
-	if (val == NULL || *val == '\0') {
-		DRV_LOG(ERR, "Key %s is missing value.", key);
-		rte_errno = EINVAL;
-		return -rte_errno;
-	}
+	if (strcmp(MLX5_DRIVER_KEY, key) == 0 ||
+	    strcmp(RTE_DEVARGS_KEY_CLASS, key) == 0)
+		return 0;
 	errno = 0;
 	tmp = strtol(val, NULL, 0);
 	if (errno) {
@@ -123,7 +255,7 @@  mlx5_common_args_check_handler(const char *key, const char *val, void *opaque)
 		DRV_LOG(WARNING, "%s: \"%s\" is an invalid integer.", key, val);
 		return -rte_errno;
 	}
-	if (strcmp(key, "tx_db_nc") == 0) {
+	if (strcmp(key, MLX5_TX_DB_NC) == 0) {
 		if (tmp != MLX5_TXDB_CACHED &&
 		    tmp != MLX5_TXDB_NCACHED &&
 		    tmp != MLX5_TXDB_HEURISTIC) {
@@ -132,11 +264,11 @@  mlx5_common_args_check_handler(const char *key, const char *val, void *opaque)
 			return -rte_errno;
 		}
 		config->dbnc = tmp;
-	} else if (strcmp(key, "mr_ext_memseg_en") == 0) {
+	} else if (strcmp(key, MLX5_MR_EXT_MEMSEG_EN) == 0) {
 		config->mr_ext_memseg_en = !!tmp;
-	} else if (strcmp(key, "mr_mempool_reg_en") == 0) {
+	} else if (strcmp(key, MLX5_MR_MEMPOOL_REG_EN) == 0) {
 		config->mr_mempool_reg_en = !!tmp;
-	} else if (strcmp(key, "sys_mem_en") == 0) {
+	} else if (strcmp(key, MLX5_SYS_MEM_EN) == 0) {
 		config->sys_mem_en = !!tmp;
 	}
 	return 0;
@@ -154,29 +286,34 @@  mlx5_common_args_check_handler(const char *key, const char *val, void *opaque)
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 static int
-mlx5_common_config_get(struct rte_devargs *devargs,
+mlx5_common_config_get(struct mlx5_kvargs_ctrl *mkvlist,
 		       struct mlx5_common_dev_config *config)
 {
-	struct rte_kvargs *kvlist;
+	const char **params = (const char *[]){
+		RTE_DEVARGS_KEY_CLASS,
+		MLX5_DRIVER_KEY,
+		MLX5_TX_DB_NC,
+		MLX5_MR_EXT_MEMSEG_EN,
+		MLX5_SYS_MEM_EN,
+		MLX5_MR_MEMPOOL_REG_EN,
+		NULL,
+	};
 	int ret = 0;
 
+	if (mkvlist == NULL)
+		return 0;
 	/* Set defaults. */
 	config->mr_ext_memseg_en = 1;
 	config->mr_mempool_reg_en = 1;
 	config->sys_mem_en = 0;
 	config->dbnc = MLX5_ARG_UNSET;
-	if (devargs == NULL)
-		return 0;
-	kvlist = rte_kvargs_parse(devargs->args, NULL);
-	if (kvlist == NULL) {
+	/* Process common parameters. */
+	ret = mlx5_kvargs_process(mkvlist, params,
+				  mlx5_common_args_check_handler, config);
+	if (ret) {
 		rte_errno = EINVAL;
-		return -rte_errno;
-	}
-	ret = rte_kvargs_process(kvlist, NULL, mlx5_common_args_check_handler,
-				 config);
-	if (ret)
 		ret = -rte_errno;
-	rte_kvargs_free(kvlist);
+	}
 	DRV_LOG(DEBUG, "mr_ext_memseg_en is %u.", config->mr_ext_memseg_en);
 	DRV_LOG(DEBUG, "mr_mempool_reg_en is %u.", config->mr_mempool_reg_en);
 	DRV_LOG(DEBUG, "sys_mem_en is %u.", config->sys_mem_en);
@@ -225,9 +362,9 @@  devargs_class_handler(__rte_unused const char *key,
 }
 
 static int
-parse_class_options(const struct rte_devargs *devargs)
+parse_class_options(const struct rte_devargs *devargs,
+		    struct mlx5_kvargs_ctrl *mkvlist)
 {
-	struct rte_kvargs *kvlist;
 	int ret = 0;
 
 	if (devargs == NULL)
@@ -236,12 +373,8 @@  parse_class_options(const struct rte_devargs *devargs)
 		/* Global syntax, only one class type. */
 		return class_name_to_value(devargs->cls->name);
 	/* Legacy devargs support multiple classes. */
-	kvlist = rte_kvargs_parse(devargs->args, NULL);
-	if (kvlist == NULL)
-		return 0;
-	rte_kvargs_process(kvlist, RTE_DEVARGS_KEY_CLASS,
+	rte_kvargs_process(mkvlist->kvlist, RTE_DEVARGS_KEY_CLASS,
 			   devargs_class_handler, &ret);
-	rte_kvargs_free(kvlist);
 	return ret;
 }
 
@@ -564,7 +697,8 @@  mlx5_common_dev_release(struct mlx5_common_device *cdev)
 }
 
 static struct mlx5_common_device *
-mlx5_common_dev_create(struct rte_device *eal_dev, uint32_t classes)
+mlx5_common_dev_create(struct rte_device *eal_dev, uint32_t classes,
+		       struct mlx5_kvargs_ctrl *mkvlist)
 {
 	struct mlx5_common_device *cdev;
 	int ret;
@@ -579,7 +713,7 @@  mlx5_common_dev_create(struct rte_device *eal_dev, uint32_t classes)
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		goto exit;
 	/* Parse device parameters. */
-	ret = mlx5_common_config_get(eal_dev->devargs, &cdev->config);
+	ret = mlx5_common_config_get(mkvlist, &cdev->config);
 	if (ret < 0) {
 		DRV_LOG(ERR, "Failed to process device arguments: %s",
 			strerror(rte_errno));
@@ -624,12 +758,15 @@  mlx5_common_dev_create(struct rte_device *eal_dev, uint32_t classes)
  *
  * @param cdev
  *   Pointer to mlx5 device structure.
+ * @param mkvlist
+ *   Pointer to mlx5 kvargs control, can be NULL if there is no devargs.
  *
  * @return
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 static int
-mlx5_common_probe_again_args_validate(struct mlx5_common_device *cdev)
+mlx5_common_probe_again_args_validate(struct mlx5_common_device *cdev,
+				      struct mlx5_kvargs_ctrl *mkvlist)
 {
 	struct mlx5_common_dev_config *config;
 	int ret;
@@ -638,7 +775,7 @@  mlx5_common_probe_again_args_validate(struct mlx5_common_device *cdev)
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return 0;
 	/* Probe again doesn't have to generate devargs. */
-	if (cdev->dev->devargs == NULL)
+	if (mkvlist == NULL)
 		return 0;
 	config = mlx5_malloc(MLX5_MEM_ZERO | MLX5_MEM_RTE,
 			     sizeof(struct mlx5_common_dev_config),
@@ -651,7 +788,7 @@  mlx5_common_probe_again_args_validate(struct mlx5_common_device *cdev)
 	 * Creates a temporary common configure structure according to new
 	 * devargs attached in probing again.
 	 */
-	ret = mlx5_common_config_get(cdev->dev->devargs, config);
+	ret = mlx5_common_config_get(mkvlist, config);
 	if (ret) {
 		DRV_LOG(ERR, "Failed to process device configure: %s",
 			strerror(rte_errno));
@@ -719,7 +856,8 @@  drivers_remove(struct mlx5_common_device *cdev, uint32_t enabled_classes)
 }
 
 static int
-drivers_probe(struct mlx5_common_device *cdev, uint32_t user_classes)
+drivers_probe(struct mlx5_common_device *cdev, uint32_t user_classes,
+	      struct mlx5_kvargs_ctrl *mkvlist)
 {
 	struct mlx5_class_driver *driver;
 	uint32_t enabled_classes = 0;
@@ -738,7 +876,7 @@  drivers_probe(struct mlx5_common_device *cdev, uint32_t user_classes)
 			ret = -EEXIST;
 			goto probe_err;
 		}
-		ret = driver->probe(cdev);
+		ret = driver->probe(cdev, mkvlist);
 		if (ret < 0) {
 			DRV_LOG(ERR, "Failed to load driver %s",
 				driver->name);
@@ -764,17 +902,27 @@  int
 mlx5_common_dev_probe(struct rte_device *eal_dev)
 {
 	struct mlx5_common_device *cdev;
+	struct mlx5_kvargs_ctrl mkvlist;
+	struct mlx5_kvargs_ctrl *mkvlist_p = NULL;
 	uint32_t classes = 0;
 	bool new_device = false;
 	int ret;
 
 	DRV_LOG(INFO, "probe device \"%s\".", eal_dev->name);
-	ret = parse_class_options(eal_dev->devargs);
+	if (eal_dev->devargs != NULL)
+		mkvlist_p = &mkvlist;
+	ret = mlx5_kvargs_prepare(mkvlist_p, eal_dev->devargs);
 	if (ret < 0) {
-		DRV_LOG(ERR, "Unsupported mlx5 class type: %s",
+		DRV_LOG(ERR, "Unsupported device arguments: %s",
 			eal_dev->devargs->args);
 		return ret;
 	}
+	ret = parse_class_options(eal_dev->devargs, mkvlist_p);
+	if (ret < 0) {
+		DRV_LOG(ERR, "Unsupported mlx5 class type: %s",
+			eal_dev->devargs->args);
+		goto class_err;
+	}
 	classes = ret;
 	if (classes == 0)
 		/* Default to net class. */
@@ -792,18 +940,20 @@  mlx5_common_dev_probe(struct rte_device *eal_dev)
 	cdev = to_mlx5_device(eal_dev);
 	if (!cdev) {
 		/* It isn't probing again, creates a new device. */
-		cdev = mlx5_common_dev_create(eal_dev, classes);
-		if (!cdev)
-			return -ENOMEM;
+		cdev = mlx5_common_dev_create(eal_dev, classes, mkvlist_p);
+		if (!cdev) {
+			ret = -ENOMEM;
+			goto class_err;
+		}
 		new_device = true;
 	} else {
 		/* It is probing again, validate common devargs match. */
-		ret = mlx5_common_probe_again_args_validate(cdev);
+		ret = mlx5_common_probe_again_args_validate(cdev, mkvlist_p);
 		if (ret) {
 			DRV_LOG(ERR,
 				"Probe again parameters aren't compatible : %s",
 				strerror(rte_errno));
-			return ret;
+			goto class_err;
 		}
 	}
 	/*
@@ -816,13 +966,30 @@  mlx5_common_dev_probe(struct rte_device *eal_dev)
 		DRV_LOG(ERR, "Unsupported mlx5 classes combination.");
 		goto class_err;
 	}
-	ret = drivers_probe(cdev, classes);
+	ret = drivers_probe(cdev, classes, mkvlist_p);
+	if (ret)
+		goto class_err;
+	/*
+	 * Validate that all devargs have been used, unused key -> unknown Key.
+	 * When probe again validate is failed, the added drivers aren't removed
+	 * here but when device is released.
+	 */
+	ret = mlx5_kvargs_validate(mkvlist_p);
 	if (ret)
 		goto class_err;
+	mlx5_kvargs_release(mkvlist_p);
 	return 0;
 class_err:
-	if (new_device)
+	if (new_device) {
+		/*
+		 * For new device, classes_loaded is always 0 before
+		 * drivers_probe function.
+		 */
+		if (cdev->classes_loaded)
+			drivers_remove(cdev, cdev->classes_loaded);
 		mlx5_common_dev_release(cdev);
+	}
+	mlx5_kvargs_release(mkvlist_p);
 	return ret;
 }
 
diff --git a/drivers/common/mlx5/mlx5_common.h b/drivers/common/mlx5/mlx5_common.h
index 80f59c81fb..49bcea1d91 100644
--- a/drivers/common/mlx5/mlx5_common.h
+++ b/drivers/common/mlx5/mlx5_common.h
@@ -281,6 +281,37 @@  struct mlx5_klm {
 	uint64_t address;
 };
 
+/** Control for key/values list. */
+struct mlx5_kvargs_ctrl {
+	struct rte_kvargs *kvlist; /* Structure containing list of key/values.*/
+	bool is_used[RTE_KVARGS_MAX]; /* Indicator which devargs were used. */
+};
+
+/**
+ * Call a handler function for each key/value in the list of keys.
+ *
+ * For each key/value association that matches the given key, calls the
+ * handler function with the for a given arg_name passing the value on the
+ * dictionary for that key and a given extra argument.
+ *
+ * @param mkvlist
+ *   The mlx5_kvargs structure.
+ * @param keys
+ *   A list of keys to process (table of const char *, the last must be NULL).
+ * @param handler
+ *   The function to call for each matching key.
+ * @param opaque_arg
+ *   A pointer passed unchanged to the handler.
+ *
+ * @return
+ *   - 0 on success
+ *   - Negative on error
+ */
+__rte_internal
+int
+mlx5_kvargs_process(struct mlx5_kvargs_ctrl *mkvlist, const char *const keys[],
+		    arg_handler_t handler, void *opaque_arg);
+
 /* All UAR arguments using doorbell register in datapath. */
 struct mlx5_uar_data {
 	uint64_t *db;
@@ -437,12 +468,13 @@  struct mlx5_common_device {
 /**
  * Initialization function for the driver called during device probing.
  */
-typedef int (mlx5_class_driver_probe_t)(struct mlx5_common_device *dev);
+typedef int (mlx5_class_driver_probe_t)(struct mlx5_common_device *cdev,
+					struct mlx5_kvargs_ctrl *mkvlist);
 
 /**
  * Uninitialization function for the driver called during hot-unplugging.
  */
-typedef int (mlx5_class_driver_remove_t)(struct mlx5_common_device *dev);
+typedef int (mlx5_class_driver_remove_t)(struct mlx5_common_device *cdev);
 
 /** Device already probed can be probed again to check for new ports. */
 #define MLX5_DRV_PROBE_AGAIN 0x0004
diff --git a/drivers/common/mlx5/version.map b/drivers/common/mlx5/version.map
index 59ab434631..1c6153c576 100644
--- a/drivers/common/mlx5/version.map
+++ b/drivers/common/mlx5/version.map
@@ -85,6 +85,8 @@  INTERNAL {
 
 	mlx5_glue;
 
+	mlx5_kvargs_process;
+
 	mlx5_list_create;
 	mlx5_list_register;
 	mlx5_list_unregister;
diff --git a/drivers/compress/mlx5/mlx5_compress.c b/drivers/compress/mlx5/mlx5_compress.c
index 82b871bd86..3fc7f4c434 100644
--- a/drivers/compress/mlx5/mlx5_compress.c
+++ b/drivers/compress/mlx5/mlx5_compress.c
@@ -657,41 +657,36 @@  mlx5_compress_args_check_handler(const char *key, const char *val, void *opaque)
 		errno = 0;
 		devarg_prms->log_block_sz = (uint32_t)strtoul(val, NULL, 10);
 		if (errno) {
-			DRV_LOG(WARNING, "%s: \"%s\" is an invalid integer."
-				, key, val);
+			DRV_LOG(WARNING, "%s: \"%s\" is an invalid integer.",
+				key, val);
 			return -errno;
 		}
-		return 0;
 	}
 	return 0;
 }
 
 static int
-mlx5_compress_handle_devargs(struct rte_devargs *devargs,
-			  struct mlx5_compress_devarg_params *devarg_prms,
-			  struct mlx5_hca_attr *att)
+mlx5_compress_handle_devargs(struct mlx5_kvargs_ctrl *mkvlist,
+			     struct mlx5_compress_devarg_params *devarg_prms,
+			     struct mlx5_hca_attr *att)
 {
-	struct rte_kvargs *kvlist;
+	const char **params = (const char *[]){
+		"log-block-size",
+		NULL,
+	};
 
 	devarg_prms->log_block_sz = MLX5_GGA_COMP_LOG_BLOCK_SIZE_MAX;
-	if (devargs == NULL)
+	if (mkvlist == NULL)
 		return 0;
-	kvlist = rte_kvargs_parse(devargs->args, NULL);
-	if (kvlist == NULL) {
-		DRV_LOG(ERR, "Failed to parse devargs.");
-		rte_errno = EINVAL;
-		return -1;
-	}
-	if (rte_kvargs_process(kvlist, NULL, mlx5_compress_args_check_handler,
-			   devarg_prms) != 0) {
+	if (mlx5_kvargs_process(mkvlist, params,
+				mlx5_compress_args_check_handler,
+				devarg_prms) != 0) {
 		DRV_LOG(ERR, "Devargs handler function Failed.");
-		rte_kvargs_free(kvlist);
 		rte_errno = EINVAL;
 		return -1;
 	}
-	rte_kvargs_free(kvlist);
 	if (devarg_prms->log_block_sz > MLX5_GGA_COMP_LOG_BLOCK_SIZE_MAX ||
-		devarg_prms->log_block_sz < att->compress_min_block_size) {
+	    devarg_prms->log_block_sz < att->compress_min_block_size) {
 		DRV_LOG(WARNING, "Log block size provided is out of range("
 			"%u); default it to %u.",
 			devarg_prms->log_block_sz,
@@ -702,7 +697,8 @@  mlx5_compress_handle_devargs(struct rte_devargs *devargs,
 }
 
 static int
-mlx5_compress_dev_probe(struct mlx5_common_device *cdev)
+mlx5_compress_dev_probe(struct mlx5_common_device *cdev,
+			struct mlx5_kvargs_ctrl *mkvlist)
 {
 	struct rte_compressdev *compressdev;
 	struct mlx5_compress_priv *priv;
@@ -726,7 +722,7 @@  mlx5_compress_dev_probe(struct mlx5_common_device *cdev)
 		rte_errno = ENOTSUP;
 		return -ENOTSUP;
 	}
-	mlx5_compress_handle_devargs(cdev->dev->devargs, &devarg_prms, attr);
+	mlx5_compress_handle_devargs(mkvlist, &devarg_prms, attr);
 	compressdev = rte_compressdev_pmd_create(ibdev_name, cdev->dev,
 						 sizeof(*priv), &init_params);
 	if (compressdev == NULL) {
diff --git a/drivers/crypto/mlx5/mlx5_crypto.c b/drivers/crypto/mlx5/mlx5_crypto.c
index 421c23748a..e14f867797 100644
--- a/drivers/crypto/mlx5/mlx5_crypto.c
+++ b/drivers/crypto/mlx5/mlx5_crypto.c
@@ -722,8 +722,6 @@  mlx5_crypto_args_check_handler(const char *key, const char *val, void *opaque)
 	int ret;
 	int i;
 
-	if (strcmp(key, "class") == 0)
-		return 0;
 	if (strcmp(key, "wcs_file") == 0) {
 		file = fopen(val, "rb");
 		if (file == NULL) {
@@ -763,48 +761,44 @@  mlx5_crypto_args_check_handler(const char *key, const char *val, void *opaque)
 		attr->credential_pointer = (uint32_t)tmp;
 	} else if (strcmp(key, "keytag") == 0) {
 		devarg_prms->keytag = tmp;
-	} else {
-		DRV_LOG(WARNING, "Invalid key %s.", key);
 	}
 	return 0;
 }
 
 static int
-mlx5_crypto_parse_devargs(struct rte_devargs *devargs,
+mlx5_crypto_parse_devargs(struct mlx5_kvargs_ctrl *mkvlist,
 			  struct mlx5_crypto_devarg_params *devarg_prms)
 {
 	struct mlx5_devx_crypto_login_attr *attr = &devarg_prms->login_attr;
-	struct rte_kvargs *kvlist;
+	const char **params = (const char *[]){
+		"credential_id",
+		"import_kek_id",
+		"keytag",
+		"max_segs_num",
+		"wcs_file",
+		NULL,
+	};
 
 	/* Default values. */
 	attr->credential_pointer = 0;
 	attr->session_import_kek_ptr = 0;
 	devarg_prms->keytag = 0;
 	devarg_prms->max_segs_num = 8;
-	if (devargs == NULL) {
+	if (mkvlist == NULL) {
 		DRV_LOG(ERR,
-	"No login devargs in order to enable crypto operations in the device.");
-		rte_errno = EINVAL;
-		return -1;
-	}
-	kvlist = rte_kvargs_parse(devargs->args, NULL);
-	if (kvlist == NULL) {
-		DRV_LOG(ERR, "Failed to parse devargs.");
+			"No login devargs in order to enable crypto operations in the device.");
 		rte_errno = EINVAL;
 		return -1;
 	}
-	if (rte_kvargs_process(kvlist, NULL, mlx5_crypto_args_check_handler,
-			   devarg_prms) != 0) {
+	if (mlx5_kvargs_process(mkvlist, params, mlx5_crypto_args_check_handler,
+				devarg_prms) != 0) {
 		DRV_LOG(ERR, "Devargs handler function Failed.");
-		rte_kvargs_free(kvlist);
 		rte_errno = EINVAL;
 		return -1;
 	}
-	rte_kvargs_free(kvlist);
 	if (devarg_prms->login_devarg == false) {
 		DRV_LOG(ERR,
-	"No login credential devarg in order to enable crypto operations "
-	"in the device.");
+			"No login credential devarg in order to enable crypto operations in the device.");
 		rte_errno = EINVAL;
 		return -1;
 	}
@@ -887,7 +881,8 @@  mlx5_crypto_configure_wqe_size(struct mlx5_crypto_priv *priv,
 }
 
 static int
-mlx5_crypto_dev_probe(struct mlx5_common_device *cdev)
+mlx5_crypto_dev_probe(struct mlx5_common_device *cdev,
+		      struct mlx5_kvargs_ctrl *mkvlist)
 {
 	struct rte_cryptodev *crypto_dev;
 	struct mlx5_devx_obj *login;
@@ -914,7 +909,7 @@  mlx5_crypto_dev_probe(struct mlx5_common_device *cdev)
 		rte_errno = ENOTSUP;
 		return -ENOTSUP;
 	}
-	ret = mlx5_crypto_parse_devargs(cdev->dev->devargs, &devarg_prms);
+	ret = mlx5_crypto_parse_devargs(mkvlist, &devarg_prms);
 	if (ret) {
 		DRV_LOG(ERR, "Failed to parse devargs.");
 		return -rte_errno;
diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c
index 6979385782..b2172ed1fd 100644
--- a/drivers/net/mlx5/linux/mlx5_os.c
+++ b/drivers/net/mlx5/linux/mlx5_os.c
@@ -1001,6 +1001,8 @@  mlx5_representor_match(struct mlx5_dev_spawn_data *spawn,
  *   Verbs device parameters (name, port, switch_info) to spawn.
  * @param eth_da
  *   Device arguments.
+ * @param mkvlist
+ *   Pointer to mlx5 kvargs control, can be NULL if there is no devargs.
  *
  * @return
  *   A valid Ethernet device object on success, NULL otherwise and rte_errno
@@ -1012,7 +1014,8 @@  mlx5_representor_match(struct mlx5_dev_spawn_data *spawn,
 static struct rte_eth_dev *
 mlx5_dev_spawn(struct rte_device *dpdk_dev,
 	       struct mlx5_dev_spawn_data *spawn,
-	       struct rte_eth_devargs *eth_da)
+	       struct rte_eth_devargs *eth_da,
+	       struct mlx5_kvargs_ctrl *mkvlist)
 {
 	const struct mlx5_switch_info *switch_info = &spawn->info;
 	struct mlx5_dev_ctx_shared *sh = NULL;
@@ -1062,6 +1065,12 @@  mlx5_dev_spawn(struct rte_device *dpdk_dev,
 		DRV_LOG(WARNING, "device name overflow %s", name);
 	/* check if the device is already spawned */
 	if (rte_eth_dev_get_port_by_name(name, &port_id) == 0) {
+		/*
+		 * When device is already spawned, its devargs should be set
+		 * as used. otherwise, mlx5_kvargs_validate() will fail.
+		 */
+		if (mkvlist)
+			mlx5_port_args_set_used(name, port_id, mkvlist);
 		rte_errno = EEXIST;
 		return NULL;
 	}
@@ -1103,7 +1112,7 @@  mlx5_dev_spawn(struct rte_device *dpdk_dev,
 		mlx5_dev_close(eth_dev);
 		return NULL;
 	}
-	sh = mlx5_alloc_shared_dev_ctx(spawn);
+	sh = mlx5_alloc_shared_dev_ctx(spawn, mkvlist);
 	if (!sh)
 		return NULL;
 	nl_rdma = mlx5_nl_init(NETLINK_RDMA);
@@ -1354,7 +1363,7 @@  mlx5_dev_spawn(struct rte_device *dpdk_dev,
 #endif
 	}
 	/* Process parameters and store port configuration on priv structure. */
-	err = mlx5_port_args_config(priv, dpdk_dev->devargs, &priv->config);
+	err = mlx5_port_args_config(priv, mkvlist, &priv->config);
 	if (err) {
 		err = rte_errno;
 		DRV_LOG(ERR, "Failed to process port configure: %s",
@@ -1840,6 +1849,8 @@  mlx5_device_bond_pci_match(const char *ibdev_name,
  *   Requested ethdev device argument.
  * @param[in] owner_id
  *   Requested owner PF port ID within bonding device, default to 0.
+ * @param[in, out] mkvlist
+ *   Pointer to mlx5 kvargs control, can be NULL if there is no devargs.
  *
  * @return
  *   0 on success, a negative errno value otherwise and rte_errno is set.
@@ -1847,7 +1858,7 @@  mlx5_device_bond_pci_match(const char *ibdev_name,
 static int
 mlx5_os_pci_probe_pf(struct mlx5_common_device *cdev,
 		     struct rte_eth_devargs *req_eth_da,
-		     uint16_t owner_id)
+		     uint16_t owner_id, struct mlx5_kvargs_ctrl *mkvlist)
 {
 	struct ibv_device **ibv_list;
 	/*
@@ -2217,7 +2228,8 @@  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);
+		list[i].eth_dev = mlx5_dev_spawn(cdev->dev, &list[i], &eth_da,
+						 mkvlist);
 		if (!list[i].eth_dev) {
 			if (rte_errno != EBUSY && rte_errno != EEXIST)
 				break;
@@ -2329,12 +2341,15 @@  mlx5_os_parse_eth_devargs(struct rte_device *dev,
  *
  * @param[in] cdev
  *   Pointer to common mlx5 device structure.
+ * @param[in, out] mkvlist
+ *   Pointer to mlx5 kvargs control, can be NULL if there is no devargs.
  *
  * @return
  *   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,
+		  struct mlx5_kvargs_ctrl *mkvlist)
 {
 	struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(cdev->dev);
 	struct rte_eth_devargs eth_da = { .nb_ports = 0 };
@@ -2349,7 +2364,7 @@  mlx5_os_pci_probe(struct mlx5_common_device *cdev)
 		/* 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,
-						   eth_da.ports[p]);
+						   eth_da.ports[p], mkvlist);
 			if (ret)
 				break;
 		}
@@ -2362,14 +2377,15 @@  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, &eth_da, 0, mkvlist);
 	}
 	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,
+			struct mlx5_kvargs_ctrl *mkvlist)
 {
 	struct rte_eth_devargs eth_da = { .nb_ports = 0 };
 	struct mlx5_dev_spawn_data spawn = { .pf_bond = -1 };
@@ -2394,7 +2410,7 @@  mlx5_os_auxiliary_probe(struct mlx5_common_device *cdev)
 	spawn.ifindex = ret;
 	spawn.cdev = cdev;
 	/* Spawn device. */
-	eth_dev = mlx5_dev_spawn(dev, &spawn, &eth_da);
+	eth_dev = mlx5_dev_spawn(dev, &spawn, &eth_da, mkvlist);
 	if (eth_dev == NULL)
 		return -rte_errno;
 	/* Post create. */
@@ -2415,12 +2431,15 @@  mlx5_os_auxiliary_probe(struct mlx5_common_device *cdev)
  *
  * @param[in] cdev
  *   Pointer to the common mlx5 device.
+ * @param[in, out] mkvlist
+ *   Pointer to mlx5 kvargs control, can be NULL if there is no devargs.
  *
  * @return
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 int
-mlx5_os_net_probe(struct mlx5_common_device *cdev)
+mlx5_os_net_probe(struct mlx5_common_device *cdev,
+		  struct mlx5_kvargs_ctrl *mkvlist)
 {
 	int ret;
 
@@ -2432,16 +2451,16 @@  mlx5_os_net_probe(struct mlx5_common_device *cdev)
 			strerror(rte_errno));
 		return -rte_errno;
 	}
-	ret = mlx5_probe_again_args_validate(cdev);
+	ret = mlx5_probe_again_args_validate(cdev, mkvlist);
 	if (ret) {
 		DRV_LOG(ERR, "Probe again parameters are not compatible : %s",
 			strerror(rte_errno));
 		return -rte_errno;
 	}
 	if (mlx5_dev_is_pci(cdev->dev))
-		return mlx5_os_pci_probe(cdev);
+		return mlx5_os_pci_probe(cdev, mkvlist);
 	else
-		return mlx5_os_auxiliary_probe(cdev);
+		return mlx5_os_auxiliary_probe(cdev, mkvlist);
 }
 
 /**
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index b3601155d7..a59a46bb27 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -43,9 +43,6 @@ 
 
 #define MLX5_ETH_DRIVER_NAME mlx5_eth
 
-/* Driver type key for new device global syntax. */
-#define MLX5_DRIVER_KEY "driver"
-
 /* Device parameter to enable RX completion queue compression. */
 #define MLX5_RXQ_CQE_COMP_EN "rxq_cqe_comp_en"
 
@@ -94,12 +91,6 @@ 
 /* Device parameter to enable multi-packet send WQEs. */
 #define MLX5_TXQ_MPW_EN "txq_mpw_en"
 
-/*
- * Device parameter to force doorbell register mapping
- * to non-cahed region eliminating the extra write memory barrier.
- */
-#define MLX5_TX_DB_NC "tx_db_nc"
-
 /*
  * Device parameter to include 2 dsegs in the title WQEBB.
  * Deprecated, ignored.
@@ -152,9 +143,6 @@ 
 /* Activate Netlink support in VF mode. */
 #define MLX5_VF_NL_EN "vf_nl_en"
 
-/* Enable extending memsegs when creating a MR. */
-#define MLX5_MR_EXT_MEMSEG_EN "mr_ext_memseg_en"
-
 /* Select port representors to instantiate. */
 #define MLX5_REPRESENTOR "representor"
 
@@ -173,17 +161,12 @@ 
 /* Flow memory reclaim mode. */
 #define MLX5_RECLAIM_MEM "reclaim_mem_mode"
 
-/* The default memory allocator used in PMD. */
-#define MLX5_SYS_MEM_EN "sys_mem_en"
 /* Decap will be used or not. */
 #define MLX5_DECAP_EN "decap_en"
 
 /* Device parameter to configure allow or prevent duplicate rules pattern. */
 #define MLX5_ALLOW_DUPLICATE_PATTERN "allow_duplicate_pattern"
 
-/* Device parameter to configure implicit registration of mempool memory. */
-#define MLX5_MR_MEMPOOL_REG_EN "mr_mempool_reg_en"
-
 /* Device parameter to configure the delay drop when creating Rxqs. */
 #define MLX5_DELAY_DROP "delay_drop"
 
@@ -1255,8 +1238,8 @@  mlx5_dev_args_check_handler(const char *key, const char *val, void *opaque)
  *
  * @param sh
  *   Pointer to shared device context.
- * @param devargs
- *   Device arguments structure.
+ * @param mkvlist
+ *   Pointer to mlx5 kvargs control, can be NULL if there is no devargs.
  * @param config
  *   Pointer to shared device configuration structure.
  *
@@ -1265,10 +1248,23 @@  mlx5_dev_args_check_handler(const char *key, const char *val, void *opaque)
  */
 static int
 mlx5_shared_dev_ctx_args_config(struct mlx5_dev_ctx_shared *sh,
-				struct rte_devargs *devargs,
+				struct mlx5_kvargs_ctrl *mkvlist,
 				struct mlx5_sh_config *config)
 {
-	struct rte_kvargs *kvlist;
+	const char **params = (const char *[]){
+		MLX5_TX_PP,
+		MLX5_TX_SKEW,
+		MLX5_L3_VXLAN_EN,
+		MLX5_VF_NL_EN,
+		MLX5_DV_ESW_EN,
+		MLX5_DV_FLOW_EN,
+		MLX5_DV_XMETA_EN,
+		MLX5_LACP_BY_USER,
+		MLX5_RECLAIM_MEM,
+		MLX5_DECAP_EN,
+		MLX5_ALLOW_DUPLICATE_PATTERN,
+		NULL,
+	};
 	int ret = 0;
 
 	/* Default configuration. */
@@ -1278,19 +1274,10 @@  mlx5_shared_dev_ctx_args_config(struct mlx5_dev_ctx_shared *sh,
 	config->dv_flow_en = 1;
 	config->decap_en = 1;
 	config->allow_duplicate_pattern = 1;
-	/* Parse device parameters. */
-	if (devargs != NULL) {
-		kvlist = rte_kvargs_parse(devargs->args, NULL);
-		if (kvlist == NULL) {
-			DRV_LOG(ERR,
-				"Failed to parse shared device arguments.");
-			rte_errno = EINVAL;
-			return -rte_errno;
-		}
+	if (mkvlist != NULL) {
 		/* Process parameters. */
-		ret = rte_kvargs_process(kvlist, NULL,
-					 mlx5_dev_args_check_handler, config);
-		rte_kvargs_free(kvlist);
+		ret = mlx5_kvargs_process(mkvlist, params,
+					  mlx5_dev_args_check_handler, config);
 		if (ret) {
 			DRV_LOG(ERR, "Failed to process device arguments: %s",
 				strerror(rte_errno));
@@ -1398,13 +1385,16 @@  mlx5_rt_timestamp_config(struct mlx5_dev_ctx_shared *sh,
  *
  * @param[in] spawn
  *   Pointer to the device attributes (name, port, etc).
+ * @param mkvlist
+ *   Pointer to mlx5 kvargs control, can be NULL if there is no devargs.
  *
  * @return
  *   Pointer to mlx5_dev_ctx_shared object on success,
  *   otherwise NULL and rte_errno is set.
  */
 struct mlx5_dev_ctx_shared *
-mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn)
+mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn,
+			  struct mlx5_kvargs_ctrl *mkvlist)
 {
 	struct mlx5_dev_ctx_shared *sh;
 	int err = 0;
@@ -1443,8 +1433,7 @@  mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn)
 		DRV_LOG(ERR, "Fail to configure device capabilities.");
 		goto error;
 	}
-	err = mlx5_shared_dev_ctx_args_config(sh, sh->cdev->dev->devargs,
-					      &sh->config);
+	err = mlx5_shared_dev_ctx_args_config(sh, mkvlist, &sh->config);
 	if (err) {
 		DRV_LOG(ERR, "Failed to process device configure: %s",
 			strerror(rte_errno));
@@ -2107,15 +2096,7 @@  mlx5_port_args_check_handler(const char *key, const char *val, void *opaque)
 	signed long tmp;
 
 	/* No-op, port representors are processed in mlx5_dev_spawn(). */
-	if (!strcmp(MLX5_DRIVER_KEY, key) || !strcmp(MLX5_REPRESENTOR, key) ||
-	    !strcmp(MLX5_SYS_MEM_EN, key) || !strcmp(MLX5_TX_DB_NC, key) ||
-	    !strcmp(MLX5_MR_MEMPOOL_REG_EN, key) || !strcmp(MLX5_TX_PP, key) ||
-	    !strcmp(MLX5_MR_EXT_MEMSEG_EN, key) || !strcmp(MLX5_TX_SKEW, key) ||
-	    !strcmp(MLX5_RECLAIM_MEM, key) || !strcmp(MLX5_DECAP_EN, key) ||
-	    !strcmp(MLX5_ALLOW_DUPLICATE_PATTERN, key) ||
-	    !strcmp(MLX5_L3_VXLAN_EN, key) || !strcmp(MLX5_VF_NL_EN, key) ||
-	    !strcmp(MLX5_DV_ESW_EN, key) || !strcmp(MLX5_DV_FLOW_EN, key) ||
-	    !strcmp(MLX5_DV_XMETA_EN, key) || !strcmp(MLX5_LACP_BY_USER, key))
+	if (!strcmp(MLX5_REPRESENTOR, key))
 		return 0;
 	errno = 0;
 	tmp = strtol(val, NULL, 0);
@@ -2181,17 +2162,11 @@  mlx5_port_args_check_handler(const char *key, const char *val, void *opaque)
 		config->max_dump_files_num = tmp;
 	} else if (strcmp(MLX5_LRO_TIMEOUT_USEC, key) == 0) {
 		config->lro_timeout = tmp;
-	} else if (strcmp(RTE_DEVARGS_KEY_CLASS, key) == 0) {
-		DRV_LOG(DEBUG, "class argument is %s.", val);
 	} else if (strcmp(MLX5_HP_BUF_SIZE, key) == 0) {
 		config->log_hp_size = tmp;
 	} else if (strcmp(MLX5_DELAY_DROP, key) == 0) {
 		config->std_delay_drop = !!(tmp & MLX5_DELAY_DROP_STANDARD);
 		config->hp_delay_drop = !!(tmp & MLX5_DELAY_DROP_HAIRPIN);
-	} else {
-		DRV_LOG(WARNING,
-			"%s: unknown parameter, maybe it's for another class.",
-			key);
 	}
 	return 0;
 }
@@ -2201,8 +2176,8 @@  mlx5_port_args_check_handler(const char *key, const char *val, void *opaque)
  *
  * @param priv
  *   Pointer to shared device context.
- * @param devargs
- *   Device arguments structure.
+ * @param mkvlist
+ *   Pointer to mlx5 kvargs control, can be NULL if there is no devargs.
  * @param config
  *   Pointer to port configuration structure.
  *
@@ -2210,13 +2185,38 @@  mlx5_port_args_check_handler(const char *key, const char *val, void *opaque)
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 int
-mlx5_port_args_config(struct mlx5_priv *priv, struct rte_devargs *devargs,
+mlx5_port_args_config(struct mlx5_priv *priv, struct mlx5_kvargs_ctrl *mkvlist,
 		      struct mlx5_port_config *config)
 {
-	struct rte_kvargs *kvlist;
 	struct mlx5_hca_attr *hca_attr = &priv->sh->cdev->config.hca_attr;
 	struct mlx5_dev_cap *dev_cap = &priv->sh->dev_cap;
 	bool devx = priv->sh->cdev->config.devx;
+	const char **params = (const char *[]){
+		MLX5_RXQ_CQE_COMP_EN,
+		MLX5_RXQ_PKT_PAD_EN,
+		MLX5_RX_MPRQ_EN,
+		MLX5_RX_MPRQ_LOG_STRIDE_NUM,
+		MLX5_RX_MPRQ_LOG_STRIDE_SIZE,
+		MLX5_RX_MPRQ_MAX_MEMCPY_LEN,
+		MLX5_RXQS_MIN_MPRQ,
+		MLX5_TXQ_INLINE,
+		MLX5_TXQ_INLINE_MIN,
+		MLX5_TXQ_INLINE_MAX,
+		MLX5_TXQ_INLINE_MPW,
+		MLX5_TXQS_MIN_INLINE,
+		MLX5_TXQS_MAX_VEC,
+		MLX5_TXQ_MPW_EN,
+		MLX5_TXQ_MPW_HDR_DSEG_EN,
+		MLX5_TXQ_MAX_INLINE_LEN,
+		MLX5_TX_VEC_EN,
+		MLX5_RX_VEC_EN,
+		MLX5_REPRESENTOR,
+		MLX5_MAX_DUMP_FILES_NUM,
+		MLX5_LRO_TIMEOUT_USEC,
+		MLX5_HP_BUF_SIZE,
+		MLX5_DELAY_DROP,
+		NULL,
+	};
 	int ret = 0;
 
 	/* Default configuration. */
@@ -2234,19 +2234,10 @@  mlx5_port_args_config(struct mlx5_priv *priv, struct rte_devargs *devargs,
 	config->log_hp_size = MLX5_ARG_UNSET;
 	config->std_delay_drop = 0;
 	config->hp_delay_drop = 0;
-	/* Parse device parameters. */
-	if (devargs != NULL) {
-		kvlist = rte_kvargs_parse(devargs->args, NULL);
-		if (kvlist == NULL) {
-			DRV_LOG(ERR,
-				"Failed to parse device arguments.");
-			rte_errno = EINVAL;
-			return -rte_errno;
-		}
+	if (mkvlist != NULL) {
 		/* Process parameters. */
-		ret = rte_kvargs_process(kvlist, NULL,
-					 mlx5_port_args_check_handler, config);
-		rte_kvargs_free(kvlist);
+		ret = mlx5_kvargs_process(mkvlist, params,
+					  mlx5_port_args_check_handler, config);
 		if (ret) {
 			DRV_LOG(ERR, "Failed to process port arguments: %s",
 				strerror(rte_errno));
@@ -2349,6 +2340,85 @@  mlx5_port_args_config(struct mlx5_priv *priv, struct rte_devargs *devargs,
 	return 0;
 }
 
+/**
+ * Print the key for device argument.
+ *
+ * It is "dummy" handler whose whole purpose is to enable using
+ * mlx5_kvargs_process() function which set devargs as used.
+ *
+ * @param key
+ *   Key argument.
+ * @param val
+ *   Value associated with key, unused.
+ * @param opaque
+ *   Unused, can be NULL.
+ *
+ * @return
+ *   0 on success, function cannot fail.
+ */
+static int
+mlx5_dummy_handler(const char *key, const char *val, void *opaque)
+{
+	DRV_LOG(DEBUG, "\tKey: \"%s\" is set as used.", key);
+	RTE_SET_USED(opaque);
+	RTE_SET_USED(val);
+	return 0;
+}
+
+/**
+ * Set requested devargs as used when device is already spawned.
+ *
+ * It is necessary since it is valid to ask probe again for existing device,
+ * if its devargs don't assign as used, mlx5_kvargs_validate() will fail.
+ *
+ * @param name
+ *   Name of the existing device.
+ * @param port_id
+ *   Port identifier of the device.
+ * @param mkvlist
+ *   Pointer to mlx5 kvargs control to sign as used.
+ */
+void
+mlx5_port_args_set_used(const char *name, uint16_t port_id,
+			struct mlx5_kvargs_ctrl *mkvlist)
+{
+	const char **params = (const char *[]){
+		MLX5_RXQ_CQE_COMP_EN,
+		MLX5_RXQ_PKT_PAD_EN,
+		MLX5_RX_MPRQ_EN,
+		MLX5_RX_MPRQ_LOG_STRIDE_NUM,
+		MLX5_RX_MPRQ_LOG_STRIDE_SIZE,
+		MLX5_RX_MPRQ_MAX_MEMCPY_LEN,
+		MLX5_RXQS_MIN_MPRQ,
+		MLX5_TXQ_INLINE,
+		MLX5_TXQ_INLINE_MIN,
+		MLX5_TXQ_INLINE_MAX,
+		MLX5_TXQ_INLINE_MPW,
+		MLX5_TXQS_MIN_INLINE,
+		MLX5_TXQS_MAX_VEC,
+		MLX5_TXQ_MPW_EN,
+		MLX5_TXQ_MPW_HDR_DSEG_EN,
+		MLX5_TXQ_MAX_INLINE_LEN,
+		MLX5_TX_VEC_EN,
+		MLX5_RX_VEC_EN,
+		MLX5_REPRESENTOR,
+		MLX5_MAX_DUMP_FILES_NUM,
+		MLX5_LRO_TIMEOUT_USEC,
+		MLX5_HP_BUF_SIZE,
+		MLX5_DELAY_DROP,
+		NULL,
+	};
+
+	/* Secondary process should not handle devargs. */
+	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+		return;
+	MLX5_ASSERT(mkvlist != NULL);
+	DRV_LOG(DEBUG, "Ethernet device \"%s\" for port %u "
+		"already exists, set devargs as used:", name, port_id);
+	/* This function cannot fail with this handler. */
+	mlx5_kvargs_process(mkvlist, params, mlx5_dummy_handler, NULL);
+}
+
 /**
  * Check sibling device configurations when probing again.
  *
@@ -2357,12 +2427,15 @@  mlx5_port_args_config(struct mlx5_priv *priv, struct rte_devargs *devargs,
  *
  * @param cdev
  *   Pointer to mlx5 device structure.
+ * @param mkvlist
+ *   Pointer to mlx5 kvargs control, can be NULL if there is no devargs.
  *
  * @return
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 int
-mlx5_probe_again_args_validate(struct mlx5_common_device *cdev)
+mlx5_probe_again_args_validate(struct mlx5_common_device *cdev,
+			       struct mlx5_kvargs_ctrl *mkvlist)
 {
 	struct mlx5_dev_ctx_shared *sh = NULL;
 	struct mlx5_sh_config *config;
@@ -2391,8 +2464,7 @@  mlx5_probe_again_args_validate(struct mlx5_common_device *cdev)
 	 * Creates a temporary IB context configure structure according to new
 	 * devargs attached in probing again.
 	 */
-	ret = mlx5_shared_dev_ctx_args_config(sh, sh->cdev->dev->devargs,
-					      config);
+	ret = mlx5_shared_dev_ctx_args_config(sh, mkvlist, config);
 	if (ret) {
 		DRV_LOG(ERR, "Failed to process device configure: %s",
 			strerror(rte_errno));
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 95910aba1b..35ea3fb47c 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -1541,16 +1541,21 @@  void mlx5_age_event_prepare(struct mlx5_dev_ctx_shared *sh);
 void mlx5_rt_timestamp_config(struct mlx5_dev_ctx_shared *sh,
 			      struct mlx5_hca_attr *hca_attr);
 struct mlx5_dev_ctx_shared *
-mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn);
+mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn,
+			  struct mlx5_kvargs_ctrl *mkvlist);
 void mlx5_free_shared_dev_ctx(struct mlx5_dev_ctx_shared *sh);
 int mlx5_dev_ctx_shared_mempool_subscribe(struct rte_eth_dev *dev);
 void mlx5_free_table_hash_list(struct mlx5_priv *priv);
 int mlx5_alloc_table_hash_list(struct mlx5_priv *priv);
 void mlx5_set_min_inline(struct mlx5_priv *priv);
 void mlx5_set_metadata_mask(struct rte_eth_dev *dev);
-int mlx5_probe_again_args_validate(struct mlx5_common_device *cdev);
-int mlx5_port_args_config(struct mlx5_priv *priv, struct rte_devargs *devargs,
+int mlx5_probe_again_args_validate(struct mlx5_common_device *cdev,
+				   struct mlx5_kvargs_ctrl *mkvlist);
+int mlx5_port_args_config(struct mlx5_priv *priv,
+			  struct mlx5_kvargs_ctrl *mkvlist,
 			  struct mlx5_port_config *config);
+void mlx5_port_args_set_used(const char *name, uint16_t port_id,
+			     struct mlx5_kvargs_ctrl *mkvlist);
 bool mlx5_flex_parser_ecpri_exist(struct rte_eth_dev *dev);
 int mlx5_flex_parser_ecpri_alloc(struct rte_eth_dev *dev);
 void mlx5_flow_counter_mode_config(struct rte_eth_dev *dev);
@@ -1811,7 +1816,8 @@  void mlx5_flow_meter_rxq_flush(struct rte_eth_dev *dev);
 struct rte_pci_driver;
 int mlx5_os_capabilities_prepare(struct mlx5_dev_ctx_shared *sh);
 void mlx5_os_free_shared_dr(struct mlx5_priv *priv);
-int mlx5_os_net_probe(struct mlx5_common_device *cdev);
+int mlx5_os_net_probe(struct mlx5_common_device *cdev,
+		      struct mlx5_kvargs_ctrl *mkvlist);
 void mlx5_os_dev_shared_handler_install(struct mlx5_dev_ctx_shared *sh);
 void mlx5_os_dev_shared_handler_uninstall(struct mlx5_dev_ctx_shared *sh);
 void mlx5_os_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index);
diff --git a/drivers/net/mlx5/windows/mlx5_os.c b/drivers/net/mlx5/windows/mlx5_os.c
index f511f97494..965df80106 100644
--- a/drivers/net/mlx5/windows/mlx5_os.c
+++ b/drivers/net/mlx5/windows/mlx5_os.c
@@ -284,6 +284,8 @@  mlx5_os_set_nonblock_channel_fd(int fd)
  *   Backing DPDK device.
  * @param spawn
  *   Verbs device parameters (name, port, switch_info) to spawn.
+ * @param mkvlist
+ *   Pointer to mlx5 kvargs control, can be NULL if there is no devargs.
  *
  * @return
  *   A valid Ethernet device object on success, NULL otherwise and rte_errno
@@ -293,7 +295,8 @@  mlx5_os_set_nonblock_channel_fd(int fd)
  */
 static struct rte_eth_dev *
 mlx5_dev_spawn(struct rte_device *dpdk_dev,
-	       struct mlx5_dev_spawn_data *spawn)
+	       struct mlx5_dev_spawn_data *spawn,
+	       struct mlx5_kvargs_ctrl *mkvlist)
 {
 	const struct mlx5_switch_info *switch_info = &spawn->info;
 	struct mlx5_dev_ctx_shared *sh = NULL;
@@ -314,7 +317,7 @@  mlx5_dev_spawn(struct rte_device *dpdk_dev,
 		return NULL;
 	}
 	DRV_LOG(DEBUG, "naming Ethernet device \"%s\"", name);
-	sh = mlx5_alloc_shared_dev_ctx(spawn);
+	sh = mlx5_alloc_shared_dev_ctx(spawn, mkvlist);
 	if (!sh)
 		return NULL;
 	if (!sh->config.dv_flow_en) {
@@ -386,7 +389,7 @@  mlx5_dev_spawn(struct rte_device *dpdk_dev,
 		own_domain_id = 1;
 	}
 	/* Process parameters and store port configuration on priv structure. */
-	err = mlx5_port_args_config(priv, dpdk_dev->devargs, &priv->config);
+	err = mlx5_port_args_config(priv, mkvlist, &priv->config);
 	if (err) {
 		err = rte_errno;
 		DRV_LOG(ERR, "Failed to process port configure: %s",
@@ -770,14 +773,17 @@  mlx5_os_set_allmulti(struct rte_eth_dev *dev, int enable)
  *
  * This function spawns Ethernet devices out of a given device.
  *
- * @param[in] dev
+ * @param[in] cdev
  *   Pointer to the common device.
+ * @param[in, out] mkvlist
+ *   Pointer to mlx5 kvargs control, can be NULL if there is no devargs.
  *
  * @return
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 int
-mlx5_os_net_probe(struct mlx5_common_device *cdev)
+mlx5_os_net_probe(struct mlx5_common_device *cdev,
+		  struct mlx5_kvargs_ctrl *mkvlist)
 {
 	struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(cdev->dev);
 	struct mlx5_dev_spawn_data spawn = {
@@ -805,7 +811,7 @@  mlx5_os_net_probe(struct mlx5_common_device *cdev)
 			strerror(rte_errno));
 		return -rte_errno;
 	}
-	spawn.eth_dev = mlx5_dev_spawn(cdev->dev, &spawn);
+	spawn.eth_dev = mlx5_dev_spawn(cdev->dev, &spawn, mkvlist);
 	if (!spawn.eth_dev)
 		return -rte_errno;
 	restore = spawn.eth_dev->data->dev_flags;
diff --git a/drivers/regex/mlx5/mlx5_regex.c b/drivers/regex/mlx5/mlx5_regex.c
index e5a12fb3cc..dc2bd868ea 100644
--- a/drivers/regex/mlx5/mlx5_regex.c
+++ b/drivers/regex/mlx5/mlx5_regex.c
@@ -67,7 +67,8 @@  mlx5_regex_get_name(char *name, struct rte_device *dev)
 }
 
 static int
-mlx5_regex_dev_probe(struct mlx5_common_device *cdev)
+mlx5_regex_dev_probe(struct mlx5_common_device *cdev,
+		     struct mlx5_kvargs_ctrl *mkvlist __rte_unused)
 {
 	struct mlx5_regex_priv *priv = NULL;
 	struct mlx5_hca_attr *attr = &cdev->config.hca_attr;
diff --git a/drivers/vdpa/mlx5/mlx5_vdpa.c b/drivers/vdpa/mlx5/mlx5_vdpa.c
index b9e84dd9bf..cb3a1ac340 100644
--- a/drivers/vdpa/mlx5/mlx5_vdpa.c
+++ b/drivers/vdpa/mlx5/mlx5_vdpa.c
@@ -443,8 +443,6 @@  mlx5_vdpa_args_check_handler(const char *key, const char *val, void *opaque)
 	unsigned long tmp;
 	int n_cores = sysconf(_SC_NPROCESSORS_ONLN);
 
-	if (strcmp(key, RTE_DEVARGS_KEY_CLASS) == 0)
-		return 0;
 	errno = 0;
 	tmp = strtoul(val, NULL, 0);
 	if (errno) {
@@ -471,28 +469,33 @@  mlx5_vdpa_args_check_handler(const char *key, const char *val, void *opaque)
 		priv->hw_max_latency_us = (uint32_t)tmp;
 	} else if (strcmp(key, "hw_max_pending_comp") == 0) {
 		priv->hw_max_pending_comp = (uint32_t)tmp;
-	} else {
-		DRV_LOG(WARNING, "Invalid key %s.", key);
 	}
 	return 0;
 }
 
 static void
-mlx5_vdpa_config_get(struct rte_devargs *devargs, struct mlx5_vdpa_priv *priv)
+mlx5_vdpa_config_get(struct mlx5_kvargs_ctrl *mkvlist,
+		     struct mlx5_vdpa_priv *priv)
 {
-	struct rte_kvargs *kvlist;
+	const char **params = (const char *[]){
+		"event_core",
+		"event_mode",
+		"event_us",
+		"hw_latency_mode",
+		"hw_max_latency_us",
+		"hw_max_pending_comp",
+		"no_traffic_time",
+		NULL,
+	};
 
 	priv->event_mode = MLX5_VDPA_EVENT_MODE_FIXED_TIMER;
 	priv->event_us = 0;
 	priv->event_core = -1;
 	priv->no_traffic_max = MLX5_VDPA_DEFAULT_NO_TRAFFIC_MAX;
-	if (devargs == NULL)
-		return;
-	kvlist = rte_kvargs_parse(devargs->args, NULL);
-	if (kvlist == NULL)
+	if (mkvlist == NULL)
 		return;
-	rte_kvargs_process(kvlist, NULL, mlx5_vdpa_args_check_handler, priv);
-	rte_kvargs_free(kvlist);
+	mlx5_kvargs_process(mkvlist, params, mlx5_vdpa_args_check_handler,
+			    priv);
 	if (!priv->event_us &&
 	    priv->event_mode == MLX5_VDPA_EVENT_MODE_DYNAMIC_TIMER)
 		priv->event_us = MLX5_VDPA_DEFAULT_TIMER_STEP_US;
@@ -502,7 +505,8 @@  mlx5_vdpa_config_get(struct rte_devargs *devargs, struct mlx5_vdpa_priv *priv)
 }
 
 static int
-mlx5_vdpa_dev_probe(struct mlx5_common_device *cdev)
+mlx5_vdpa_dev_probe(struct mlx5_common_device *cdev,
+		    struct mlx5_kvargs_ctrl *mkvlist)
 {
 	struct mlx5_vdpa_priv *priv = NULL;
 	struct mlx5_hca_attr *attr = &cdev->config.hca_attr;
@@ -555,7 +559,7 @@  mlx5_vdpa_dev_probe(struct mlx5_common_device *cdev)
 		rte_errno = rte_errno ? rte_errno : EINVAL;
 		goto error;
 	}
-	mlx5_vdpa_config_get(cdev->dev->devargs, priv);
+	mlx5_vdpa_config_get(mkvlist, priv);
 	SLIST_INIT(&priv->mr_list);
 	pthread_mutex_init(&priv->vq_config_lock, NULL);
 	pthread_mutex_lock(&priv_list_lock);