From 31ef2982fa4c3ce6fb0e8a7e24d5b670f59444f1 Mon Sep 17 00:00:00 2001 From: Dekel Peled Date: Wed, 18 Nov 2020 10:59:56 +0200 Subject: [PATCH] net/mlx5: fix input register for ASO object 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 Acked-by: Matan Azrad --- 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 5a6ae790a7..2e7bbb471d 100644 --- a/drivers/net/mlx5/linux/mlx5_os.c +++ b/drivers/net/mlx5/linux/mlx5_os.c @@ -1133,17 +1133,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 = @@ -1190,8 +1179,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; @@ -1200,6 +1198,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 772f1145aa..5dc0832db2 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 70fa028afb..088fa21e4d 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 b70d9a8fe8..8791471379 100644 --- a/drivers/net/mlx5/mlx5_flow_dv.c +++ b/drivers/net/mlx5/mlx5_flow_dv.c @@ -9469,12 +9469,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; @@ -9489,7 +9491,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 @@ -9497,15 +9501,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); @@ -9519,18 +9538,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); @@ -9842,7 +9864,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, @@ -11532,7 +11554,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) {