diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 07c6add..4f6274d 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -597,6 +597,80 @@ struct mlx5_flow_id_pool *
 		mlx5_ipool_destroy(sh->ipool[i]);
 }
 
+bool
+mlx5_flex_parser_ecpri_exist(struct rte_eth_dev *dev)
+{
+	struct mlx5_priv *priv = dev->data->dev_private;
+	struct mlx5_flex_parser_profiles *prf =
+				&priv->sh->fp[MLX5_FLEX_PARSER_ECPRI_0];
+
+	return !!prf->obj;
+}
+
+int
+mlx5_flex_parser_ecpri_alloc(struct rte_eth_dev *dev)
+{
+	struct mlx5_priv *priv = dev->data->dev_private;
+	struct mlx5_flex_parser_profiles *prf =
+				&priv->sh->fp[MLX5_FLEX_PARSER_ECPRI_0];
+	struct mlx5_devx_graph_node_attr node = {
+		.modify_field_select = 0,
+	};
+	uint32_t ids[8];
+	int ret;
+
+	node.header_length_mode = MLX5_GRAPH_NODE_LEN_FIXED;
+	/* 8 bytes now: 4B common header + 4B message body header. */
+	node.header_length_base_value = 0x8;
+	/* After MAC layer: Ether / VLAN. */
+	node.in[0].arc_parse_graph_node = 0x2;
+	/* Type of compared condition should be 0xAEFE in the L2 layer. */
+	node.in[0].compare_condition_value = RTE_ETHER_TYPE_ECPRI;
+	/* Sample #0: type in common header. */
+	node.sample[0].flow_match_sample_en = 1;
+	/* Fixed offset. */
+	node.sample[0].flow_match_sample_offset_mode = 0x0;
+	/* Only the 2nd byte will be used. */
+	node.sample[0].flow_match_sample_field_base_offset = 0x0;
+	/* Sample #1: message payload. */
+	node.sample[1].flow_match_sample_en = 1;
+	/* Fixed offset. */
+	node.sample[1].flow_match_sample_offset_mode = 0x0;
+	/* Only the first two bytes will be used. */
+	node.sample[1].flow_match_sample_field_base_offset = 0x4;
+	prf->obj = mlx5_devx_cmd_create_flex_parser(priv->sh->ctx, &node);
+	if (!prf->obj) {
+		DRV_LOG(ERR, "Failed to create flex parser node object.");
+		return (rte_errno == 0) ? -ENODEV : -rte_errno;
+	}
+	prf->num = 2;
+	ret = mlx5_devx_cmd_query_parse_samples(prf->obj, ids, prf->num);
+	if (ret) {
+		DRV_LOG(ERR, "Failed to query sample IDs.");
+		return (rte_errno == 0) ? -ENODEV : -rte_errno;
+	}
+	prf->offset[0] = 0x0;
+	prf->offset[1] = 0x4;
+	prf->ids[0] = ids[0];
+	prf->ids[1] = ids[1];
+	return 0;
+}
+
+static void
+mlx5_flex_parser_ecpri_release(struct rte_eth_dev *dev)
+{
+	struct mlx5_priv *priv = dev->data->dev_private;
+
+	struct mlx5_flex_parser_profiles *prf =
+				&priv->sh->fp[MLX5_FLEX_PARSER_ECPRI_0];
+
+	if (prf->obj)
+		mlx5_devx_cmd_destroy(prf->obj);
+	prf->obj = NULL;
+	return;
+}
+
+
 /**
  * Allocate shared device context. If there is multiport device the
  * master and representors will share this context, if there is single
@@ -1158,6 +1232,8 @@ struct mlx5_dev_ctx_shared *
 	rte_wmb();
 	/* Disable datapath on secondary process. */
 	mlx5_mp_req_stop_rxtx(dev);
+	/* Free the eCPRI flex parser resource. */
+	mlx5_flex_parser_ecpri_release(dev);
 	if (priv->rxqs != NULL) {
 		/* XXX race condition if mlx5_rx_burst() is still running. */
 		usleep(1000);
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 07cbaf4..42a8bd5 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -734,6 +734,8 @@ int mlx5_dev_check_sibling_config(struct mlx5_priv *priv,
 int mlx5_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu);
 int mlx5_hairpin_cap_get(struct rte_eth_dev *dev,
 			 struct rte_eth_hairpin_cap *cap);
+bool mlx5_flex_parser_ecpri_exist(struct rte_eth_dev *dev);
+int mlx5_flex_parser_ecpri_alloc(struct rte_eth_dev *dev);
 
 /* mlx5_ethdev.c */
 
@@ -957,4 +959,5 @@ int mlx5_os_read_dev_stat(struct mlx5_priv *priv,
 void mlx5_os_stats_init(struct rte_eth_dev *dev);
 void mlx5_os_set_reg_mr_cb(mlx5_reg_mr_t *reg_mr_cb,
 			   mlx5_dereg_mr_t *dereg_mr_cb);
+
 #endif /* RTE_PMD_MLX5_H_ */
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 523d778..987c635 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -4779,34 +4779,6 @@ struct field_modify_info modify_tcp[] = {
 				  cnt, next);
 }
 
-static inline bool
-flow_dv_flex_parser_ecpri_exist(struct rte_eth_dev *dev)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	struct mlx5_flex_parser_profiles *prf =
-				&priv->sh->fp[MLX5_FLEX_PARSER_ECPRI_0];
-
-	return !!prf->obj;
-}
-
-
-static int
-flow_dv_flex_parser_ecpri_alloc(struct rte_eth_dev *dev)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	struct mlx5_flex_parser_profiles *prf =
-				&priv->sh->fp[MLX5_FLEX_PARSER_ECPRI_0];
-
-	return 0;
-}
-
-static void
-flow_dv_flex_parser_ecpri_release(struct rte_eth_dev *dev)
-{
-	(void)dev;
-	return;
-}
-
 /**
  * Verify the @p attributes will be correctly understood by the NIC and store
  * them in the @p flow if everything is correct.
@@ -8688,11 +8660,12 @@ struct field_modify_info modify_tcp[] = {
 			last_item = MLX5_FLOW_LAYER_GTP;
 			break;
 		case RTE_FLOW_ITEM_TYPE_ECPRI:
-			if (!flow_dv_flex_parser_ecpri_exist(dev)) {
-				ret = flow_dv_flex_parser_ecpri_alloc(dev);
+			if (!mlx5_flex_parser_ecpri_exist(dev)) {
+				/* Create it only the first time to be used. */
+				ret = mlx5_flex_parser_ecpri_alloc(dev);
 				if (ret)
 					return rte_flow_error_set
-						(error, ret,
+						(error, -ret,
 						RTE_FLOW_ERROR_TYPE_ITEM,
 						NULL,
 						"cannot create eCPRI parser");
