diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 6705236..ebe748b 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -2295,7 +2295,25 @@ struct mlx5_flow_id_pool *
 #if defined(HAVE_MLX5DV_DR) && defined(HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER)
 		if (config.hca_attr.qos.sup && config.hca_attr.qos.srtcm_sup &&
 		    config.dv_flow_en) {
-			priv->mtr_en = 1;
+			uint8_t reg_c_mask =
+				config.hca_attr.qos.flow_meter_reg_c_ids;
+			/*
+			 * Meter needs two REG_C's for color match and pre-sfx
+			 * flow match. Here get the REG_C for color match.
+			 * REG_C_0 and REG_C_1 is reserved for metadata feature.
+			 */
+			reg_c_mask &= 0xfc;
+			if (__builtin_popcount(reg_c_mask) < 1) {
+				priv->mtr_en = 0;
+				DRV_LOG(WARNING, "No available register for"
+					" meter.");
+			} else {
+				priv->mtr_color_reg = ffs(reg_c_mask) - 1 +
+						      REG_C_0;
+				priv->mtr_en = 1;
+				DRV_LOG(DEBUG, "The REG_C meter uses is %d",
+					priv->mtr_color_reg);
+			}
 		}
 #endif
 	}
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 7ed69a7..650f2d1 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -750,6 +750,8 @@ struct mlx5_priv {
 	struct mlx5_flow_id_pool *qrss_id_pool;
 	struct mlx5_shtable_bucket mreg_cp_tbl[MLX5_FLOW_MREG_HTABLE_SZ];
 	/* Hash table of Rx metadata register copy table. */
+	uint8_t mtr_sfx_reg; /* Meter prefix-suffix flow match REG_C. */
+	uint8_t mtr_color_reg; /* Meter color match REG_C. */
 #ifndef RTE_ARCH_64
 	rte_spinlock_t uar_lock_cq; /* CQs share a common distinct UAR */
 	rte_spinlock_t uar_lock[MLX5_UAR_PAGE_NUM_MAX];
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 7e97b0b..e569b90 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -340,6 +340,7 @@ enum modify_reg
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_dev_config *config = &priv->config;
+	enum modify_reg start_reg;
 
 	switch (feature) {
 	case MLX5_HAIRPIN_RX:
@@ -371,21 +372,53 @@ enum modify_reg
 		}
 		break;
 	case MLX5_COPY_MARK:
-		return REG_C_2;
+	case MLX5_MTR_SFX:
+		/*
+		 * Metadata COPY_MARK register using is in meter suffix sub
+		 * flow while with meter. It's safe to share the same register.
+		 */
+		return priv->mtr_color_reg != REG_C_2 ? REG_C_2 : REG_C_3;
+	case MLX5_MTR_COLOR:
+		RTE_ASSERT(priv->mtr_color_reg < 8);
+		return priv->mtr_color_reg;
 	case MLX5_APP_TAG:
 		/*
-		 * Suppose engaging reg_c_2 .. reg_c_7 registers.
-		 * reg_c_2 is reserved for coloring by meters.
+		 * If meter is enable, it will engage two registers for color
+		 * match and flow match. If meter color match is not using the
+		 * REG_C_2, need to skip the REG_C_x be used by meter color
+		 * match.
+		 * If meter is disable, free to use all available registers.
 		 */
-		if (id > (REG_C_7 - REG_C_3))
+		if (priv->mtr_color_reg != REG_NONE)
+			start_reg = priv->mtr_color_reg != REG_C_2 ? REG_C_3 :
+				    REG_C_4;
+		else
+			start_reg = REG_C_2;
+		if (id > (REG_C_7 - start_reg))
 			return rte_flow_error_set(error, EINVAL,
 						  RTE_FLOW_ERROR_TYPE_ITEM,
 						  NULL, "invalid tag id");
-		if (config->flow_mreg_c[id + REG_C_3 - REG_C_0] == REG_NONE)
+		if (config->flow_mreg_c[id + start_reg - REG_C_0] == REG_NONE)
+			return rte_flow_error_set(error, ENOTSUP,
+						  RTE_FLOW_ERROR_TYPE_ITEM,
+						  NULL, "unsupported tag id");
+		/*
+		 * This case means meter is using the REG_C_x great than 2.
+		 * Take care not to conflict with meter color REG_C_x.
+		 * If the available index REG_C_y >= REG_C_x, skip the
+		 * color register.
+		 */
+		if (start_reg == REG_C_3 && config->flow_mreg_c
+		    [id + REG_C_3 - REG_C_0] >= priv->mtr_color_reg) {
+			if (config->flow_mreg_c[id + 1 + REG_C_3 - REG_C_0] !=
+			    REG_NONE)
+				return config->flow_mreg_c
+						[id + 1 + REG_C_3 - REG_C_0];
 			return rte_flow_error_set(error, ENOTSUP,
 						  RTE_FLOW_ERROR_TYPE_ITEM,
 						  NULL, "unsupported tag id");
-		return config->flow_mreg_c[id + REG_C_3 - REG_C_0];
+		}
+		return config->flow_mreg_c[id + start_reg - REG_C_0];
 	}
 	assert(false);
 	return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 1fa5fb9..1ca7dd9 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -74,6 +74,8 @@ enum mlx5_feature_name {
 	MLX5_FLOW_MARK,
 	MLX5_APP_TAG,
 	MLX5_COPY_MARK,
+	MLX5_MTR_COLOR,
+	MLX5_MTR_SFX,
 };
 
 /* Pattern outer Layer bits. */
