#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
}
{
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:
}
break;
case MLX5_COPY_MARK:
- return REG_C_3;
+ 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 != REG_NONE);
+ 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.
- * reg_c_3 is reserved for split flows TAG.
+ * 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_4))
- return rte_flow_error_set
- (error, EINVAL,
- RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
- NULL, "invalid tag id");
- if (config->flow_mreg_c[id + REG_C_4 - REG_C_0] == REG_NONE)
- return rte_flow_error_set
- (error, ENOTSUP,
- RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
- NULL, "unsupported tag id");
- return config->flow_mreg_c[id + REG_C_4 - REG_C_0];
+ 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 + 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 + start_reg - REG_C_0];
}
assert(false);
return rte_flow_error_set(error, EINVAL,