diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 52a8a25..50249a9 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -169,6 +169,9 @@
 /* Flow memory reclaim mode. */
 #define MLX5_RECLAIM_MEM "reclaim_mem_mode"
 
+/* Flow priority mode. */
+#define MLX5_FLOW_PRIORITY_MODE "flow_priority_mode"
+
 /* The default memory allocator used in PMD. */
 #define MLX5_SYS_MEM_EN "sys_mem_en"
 /* Decap will be used or not. */
@@ -1580,6 +1583,8 @@ struct mlx5_dev_ctx_shared *
 		config->sys_mem_en = !!tmp;
 	} else if (strcmp(MLX5_DECAP_EN, key) == 0) {
 		config->decap_en = !!tmp;
+	} else if (strcmp(MLX5_FLOW_PRIORITY_MODE, key) == 0) {
+		config->flow_priority_mode = !!tmp;
 	} else {
 		DRV_LOG(WARNING, "%s: unknown parameter", key);
 		rte_errno = EINVAL;
@@ -1640,6 +1645,7 @@ struct mlx5_dev_ctx_shared *
 		MLX5_RECLAIM_MEM,
 		MLX5_SYS_MEM_EN,
 		MLX5_DECAP_EN,
+		MLX5_FLOW_PRIORITY_MODE,
 		NULL,
 	};
 	struct rte_kvargs *kvlist;
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 121d726..499467d 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -227,6 +227,12 @@ struct mlx5_dev_config {
 	unsigned int sys_mem_en:1; /* The default memory allocator. */
 	unsigned int decap_en:1; /* Whether decap will be used or not. */
 	unsigned int dv_miss_info:1; /* restore packet after partial hw miss */
+	unsigned int flow_priority_mode:1;
+	/* 0: the pmd will not adjust priority from user, the amount of
+	 *  priorities can reach 64K
+	 *  1: the pmd will manage 3 sub-priorities per user priority
+	 *  according to L2,L3 and L4.
+	 */
 	struct {
 		unsigned int enabled:1; /* Whether MPRQ is enabled. */
 		unsigned int stride_num_n; /* Number of strides. */
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 82e24d7..f967616 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -860,6 +860,60 @@ struct mlx5_flow_tunnel_info {
 }
 
 /**
+ * Get the max priority
+ *
+ * @param[in] dev
+ *   Pointer to the Ethernet device structure.
+ * @param[in] attributes
+ *   Pointer to device flow rule attributes.
+ *
+ * @return
+ *   The value of max priority of the flow .
+ */
+uint32_t
+mlx5_get_max_priority(struct rte_eth_dev *dev,
+			  const struct rte_flow_attr *attributes)
+{
+	struct mlx5_priv *priv = dev->data->dev_private;
+
+	if (!attributes->group || priv->config.flow_priority_mode)
+		return priv->config.flow_prio - 1;
+	return MLX5_NON_ROOT_FLOW_MAX_PRIO;
+}
+/**
+ * Calculate matcher priority of the flow
+ *
+ * @param[in] dev
+ *   Pointer to the Ethernet device structure.
+ * @param[in] attributes
+ *   Pointer to device flow rule attributes.
+ * @param[in] actions
+ *   Pointer to the list of actions.
+ * @return
+ *   The matcher priority of the flow .
+ */
+uint16_t
+mlx5_get_matcher_priority(struct rte_eth_dev *dev,
+			  const struct rte_flow_attr *attr,
+			  const struct rte_flow_action actions[],
+			  uint32_t subpriority)
+{
+	uint16_t priority = (uint16_t)attr->priority;
+	struct mlx5_priv *priv = dev->data->dev_private;
+
+	if (attr->priority == MLX5_FLOW_PRIO_RSVD)
+		priority = mlx5_get_max_priority(dev, attr);
+	if (priv->config.flow_priority_mode)
+		return mlx5_flow_adjust_priority(dev, priority, subpriority);
+	priority = MLX5_LACP_PRIO_OFFSET + priority * 3;
+	/*For default or rss flows,PMD will adjuest priority with sub-priority*/
+	if (attr->priority == MLX5_FLOW_PRIO_RSVD ||
+		flow_get_rss_action(actions) != NULL)
+		priority += subpriority;
+	return priority;
+}
+
+/**
  * Verify the @p item specifications (spec, last, mask) are compatible with the
  * NIC capabilities.
  *
@@ -3146,7 +3200,7 @@ struct mlx5_flow_tunnel_info {
  * @return
  *   Pointer to the RSS action if exist, else return NULL.
  */
-static const struct rte_flow_action_rss*
+const struct rte_flow_action_rss*
 flow_get_rss_action(const struct rte_flow_action actions[])
 {
 	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index d85dd19..eaa4b77 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -269,6 +269,12 @@ enum mlx5_feature_name {
 /* Priority reserved for default flows. */
 #define MLX5_FLOW_PRIO_RSVD ((uint32_t)-1)
 
+/*reserve priority 0 for LACP protocol packet*/
+#define MLX5_LACP_PRIO_OFFSET		(1)
+
+/* Max priority for non-root flows 16k. */
+#define MLX5_NON_ROOT_FLOW_MAX_PRIO	(16 * 1024)
+
 /*
  * Number of sub priorities.
  * For each kind of pattern matching i.e. L2, L3, L4 to have a correct
@@ -1286,6 +1292,14 @@ uint64_t mlx5_flow_hashfields_adjust(struct mlx5_flow_rss_desc *rss_desc,
 int mlx5_flow_discover_priorities(struct rte_eth_dev *dev);
 uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 				   uint32_t subpriority);
+uint32_t mlx5_get_max_priority(struct rte_eth_dev *dev,
+					const struct rte_flow_attr *attributes);
+uint16_t mlx5_get_matcher_priority(struct rte_eth_dev *dev,
+				     const struct rte_flow_attr *attr,
+				     const struct rte_flow_action actions[],
+				     uint32_t subpriority);
+const struct rte_flow_action_rss*
+flow_get_rss_action(const struct rte_flow_action actions[]);
 int mlx5_flow_get_reg_id(struct rte_eth_dev *dev,
 				     enum mlx5_feature_name feature,
 				     uint32_t id,
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index c317376..66d4d3a 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -5131,7 +5131,7 @@ struct mlx5_hlist_entry *
 			    struct rte_flow_error *error)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
-	uint32_t priority_max = priv->config.flow_prio - 1;
+	uint32_t priority_max = mlx5_get_max_priority(dev, attributes);
 	int ret = 0;
 
 #ifndef HAVE_MLX5DV_DR
@@ -9641,7 +9641,6 @@ struct mlx5_cache_entry *
 	uint64_t item_flags = 0;
 	uint64_t last_item = 0;
 	uint64_t action_flags = 0;
-	uint64_t priority = attr->priority;
 	struct mlx5_flow_dv_matcher matcher = {
 		.mask = {
 			.size = sizeof(matcher.mask.buf) -
@@ -9712,8 +9711,6 @@ struct mlx5_cache_entry *
 	dev_flow->dv.group = table;
 	if (attr->transfer)
 		mhdr_res->ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB;
-	if (priority == MLX5_FLOW_PRIO_RSVD)
-		priority = dev_conf->flow_prio - 1;
 	/* number of actions must be set to 0 in case of dirty stack. */
 	mhdr_res->actions_num = 0;
 	if (is_flow_tunnel_match_rule(dev, attr, items, actions)) {
@@ -10567,8 +10564,8 @@ struct mlx5_cache_entry *
 	/* Register matcher. */
 	matcher.crc = rte_raw_cksum((const void *)matcher.mask.buf,
 				    matcher.mask.size);
-	matcher.priority = mlx5_flow_adjust_priority(dev, priority,
-						     matcher.priority);
+	matcher.priority = mlx5_get_matcher_priority(dev, attr, actions,
+					matcher.priority);
 	/* reserved field no needs to be set to 0 here. */
 	tbl_key.domain = attr->transfer;
 	tbl_key.direction = attr->egress;
diff --git a/drivers/net/mlx5/mlx5_flow_verbs.c b/drivers/net/mlx5/mlx5_flow_verbs.c
index 59291fb..4ba9cd2 100644
--- a/drivers/net/mlx5/mlx5_flow_verbs.c
+++ b/drivers/net/mlx5/mlx5_flow_verbs.c
@@ -89,6 +89,10 @@
 		claim_zero(mlx5_glue->destroy_flow(flow));
 		priority = vprio[i];
 	}
+	if (priv->config.flow_priority_mode == 0) {
+		priority = (priority - MLX5_LACP_PRIO_OFFSET) / 3;
+		goto end;
+	}
 	switch (priority) {
 	case 8:
 		priority = RTE_DIM(priority_map_3);
@@ -103,7 +107,8 @@
 			dev->data->port_id, priority);
 		return -rte_errno;
 	}
-	DRV_LOG(INFO, "port %u flow maximum priority: %d",
+end:
+	DRV_LOG(INFO, "port %u flow maximum priority: %d for root table",
 		dev->data->port_id, priority);
 	return priority;
 }
