Existing code uses the hard-coded value REG_C_5 as input for function mlx5dv_dr_action_create_flow_hit().
This patch updates function mlx5_flow_get_reg_id() to return the selected REG_C value for ASO Flow Hit operation. The returned value is used, after reducing offset REG_C_0, as input for function mlx5dv_dr_action_create_flow_hit(). Fixes: f935ed4b645a ("net/mlx5: support flow hit action for aging") Signed-off-by: Dekel Peled <dek...@nvidia.com> Acked-by: Matan Azrad <ma...@nvidia.com> --- drivers/net/mlx5/linux/mlx5_os.c | 36 +++++++++++++++++++----------- drivers/net/mlx5/mlx5_flow.c | 1 + drivers/net/mlx5/mlx5_flow.h | 1 + drivers/net/mlx5/mlx5_flow_dv.c | 38 +++++++++++++++++++++++++------- 4 files changed, 55 insertions(+), 21 deletions(-) diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c index 4b7fff4eff..468ef3356f 100644 --- a/drivers/net/mlx5/linux/mlx5_os.c +++ b/drivers/net/mlx5/linux/mlx5_os.c @@ -1135,17 +1135,6 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev, err = -err; goto error; } -#ifdef HAVE_MLX5DV_DR_ACTION_FLOW_HIT - if (config->hca_attr.flow_hit_aso) { - sh->flow_hit_aso_en = 1; - err = mlx5_flow_aso_age_mng_init(sh); - if (err) { - err = -err; - goto error; - } - DRV_LOG(DEBUG, "Flow Hit ASO is supported."); - } -#endif /* HAVE_MLX5DV_DR_ACTION_FLOW_HIT */ /* Check relax ordering support. */ if (!haswell_broadwell_cpu) { sh->cmng.relaxed_ordering_write = @@ -1192,8 +1181,17 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev, DRV_LOG(WARNING, "No available register for" " meter."); } else { - priv->mtr_color_reg = ffs(reg_c_mask) - 1 + - REG_C_0; + /* + * The meter color register is used by the + * flow-hit feature as well. + * The flow-hit feature must use REG_C_3 + * Prefer REG_C_3 if it is available. + */ + if (reg_c_mask & (1 << (REG_C_3 - REG_C_0))) + priv->mtr_color_reg = REG_C_3; + else + priv->mtr_color_reg = ffs(reg_c_mask) + - 1 + REG_C_0; priv->mtr_en = 1; priv->mtr_reg_share = config->hca_attr.qos.flow_meter_reg_share; @@ -1202,6 +1200,18 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev, } } #endif +#ifdef HAVE_MLX5DV_DR_ACTION_FLOW_HIT + if (config->hca_attr.flow_hit_aso && + priv->mtr_color_reg == REG_C_3) { + sh->flow_hit_aso_en = 1; + err = mlx5_flow_aso_age_mng_init(sh); + if (err) { + err = -err; + goto error; + } + DRV_LOG(DEBUG, "Flow Hit ASO is supported."); + } +#endif /* HAVE_MLX5DV_DR_ACTION_FLOW_HIT */ #if defined(HAVE_MLX5DV_DR) && defined(HAVE_MLX5_DR_CREATE_ACTION_FLOW_SAMPLE) if (config->hca_attr.log_max_ft_sampler_num > 0 && config->dv_flow_en) { diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 33dbbd9eef..bd2e588187 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -777,6 +777,7 @@ mlx5_flow_get_reg_id(struct rte_eth_dev *dev, return priv->mtr_color_reg != REG_C_2 ? REG_C_2 : REG_C_3; case MLX5_MTR_COLOR: + case MLX5_ASO_FLOW_HIT: /* Both features use the same REG_C. */ MLX5_ASSERT(priv->mtr_color_reg != REG_NON); return priv->mtr_color_reg; case MLX5_COPY_MARK: diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h index afddcfc12c..0322db9adc 100644 --- a/drivers/net/mlx5/mlx5_flow.h +++ b/drivers/net/mlx5/mlx5_flow.h @@ -80,6 +80,7 @@ enum mlx5_feature_name { MLX5_COPY_MARK, MLX5_MTR_COLOR, MLX5_MTR_SFX, + MLX5_ASO_FLOW_HIT, }; /* Default queue number. */ diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c index 3d69957da7..ae8967ec58 100644 --- a/drivers/net/mlx5/mlx5_flow_dv.c +++ b/drivers/net/mlx5/mlx5_flow_dv.c @@ -9449,12 +9449,14 @@ flow_dv_age_pool_create(struct rte_eth_dev *dev, * * @param[in] dev * Pointer to the Ethernet device structure. + * @param[out] error + * Pointer to the error structure. * * @return * Index to ASO age action on success, 0 otherwise and rte_errno is set. */ static uint32_t -flow_dv_aso_age_alloc(struct rte_eth_dev *dev) +flow_dv_aso_age_alloc(struct rte_eth_dev *dev, struct rte_flow_error *error) { struct mlx5_priv *priv = dev->data->dev_private; const struct mlx5_aso_age_pool *pool; @@ -9469,7 +9471,9 @@ flow_dv_aso_age_alloc(struct rte_eth_dev *dev) LIST_REMOVE(age_free, next); } else if (!flow_dv_age_pool_create(dev, &age_free)) { rte_spinlock_unlock(&mng->free_sl); - return 0; /* 0 is an error.*/ + rte_flow_error_set(error, rte_errno, RTE_FLOW_ERROR_TYPE_ACTION, + NULL, "failed to create ASO age pool"); + return 0; /* 0 is an error. */ } rte_spinlock_unlock(&mng->free_sl); pool = container_of @@ -9477,15 +9481,30 @@ flow_dv_aso_age_alloc(struct rte_eth_dev *dev) (age_free - age_free->offset), const struct mlx5_aso_age_pool, actions); if (!age_free->dr_action) { + int reg_c = mlx5_flow_get_reg_id(dev, MLX5_ASO_FLOW_HIT, 0, + error); + + if (reg_c < 0) { + rte_flow_error_set(error, rte_errno, + RTE_FLOW_ERROR_TYPE_ACTION, + NULL, "failed to get reg_c " + "for ASO flow hit"); + return 0; /* 0 is an error. */ + } age_free->dr_action = mlx5_glue->dr_action_create_flow_hit (pool->flow_hit_aso_obj->obj, - age_free->offset, REG_C_5); + age_free->offset, + (reg_c - REG_C_0)); if (!age_free->dr_action) { rte_errno = errno; rte_spinlock_lock(&mng->free_sl); LIST_INSERT_HEAD(&mng->free, age_free, next); rte_spinlock_unlock(&mng->free_sl); - return 0; /* 0 is an error.*/ + rte_flow_error_set(error, rte_errno, + RTE_FLOW_ERROR_TYPE_ACTION, + NULL, "failed to create ASO " + "flow hit action"); + return 0; /* 0 is an error. */ } } __atomic_store_n(&age_free->refcnt, 1, __ATOMIC_RELAXED); @@ -9499,18 +9518,21 @@ flow_dv_aso_age_alloc(struct rte_eth_dev *dev) * Pointer to rte_eth_dev structure. * @param[in] age * Pointer to the aging action configuration. + * @param[out] error + * Pointer to the error structure. * * @return * Index to flow counter on success, 0 otherwise. */ static uint32_t flow_dv_translate_create_aso_age(struct rte_eth_dev *dev, - const struct rte_flow_action_age *age) + const struct rte_flow_action_age *age, + struct rte_flow_error *error) { uint32_t age_idx = 0; struct mlx5_aso_age_action *aso_age; - age_idx = flow_dv_aso_age_alloc(dev); + age_idx = flow_dv_aso_age_alloc(dev, error); if (!age_idx) return 0; aso_age = flow_aso_age_get_by_idx(dev, age_idx); @@ -9822,7 +9844,7 @@ flow_dv_translate(struct rte_eth_dev *dev, case RTE_FLOW_ACTION_TYPE_AGE: if (priv->sh->flow_hit_aso_en && attr->group) { flow->age = flow_dv_translate_create_aso_age - (dev, action->conf); + (dev, action->conf, error); if (!flow->age) return rte_flow_error_set (error, rte_errno, @@ -11512,7 +11534,7 @@ flow_dv_action_create(struct rte_eth_dev *dev, MLX5_SHARED_ACTION_TYPE_OFFSET) | ret; break; case RTE_FLOW_ACTION_TYPE_AGE: - ret = flow_dv_translate_create_aso_age(dev, action->conf); + ret = flow_dv_translate_create_aso_age(dev, action->conf, err); idx = (MLX5_SHARED_ACTION_TYPE_AGE << MLX5_SHARED_ACTION_TYPE_OFFSET) | ret; if (ret) { -- 2.25.1