From: Yevgeny Kliteynik <klit...@nvidia.com> If resized rule is deleted, the delete process also includes clearing the rule's resize_info. The problem is, this resize_info contains info on the action STEs that are freed onle when the completion of rule deletion received. This means that resize_info should be freed only after action STEs.
This patch separates rule's resize_info saving and clearing into a separate calls. Saving of resize_info is done similar to saving of delete info (same as it was before this patch), and clearing is done only after mlx5dr_rule_free_action_ste_idx. Additional issue that is fixed here is using the right max_stes when calculating which STEs should be freed - max_stes is now saved as part of resize_info. Fixes: 762feceb8294 ("net/mlx5/hws: support resizable matchers") Signed-off-by: Yevgeny Kliteynik <klit...@nvidia.com> --- drivers/net/mlx5/hws/mlx5dr_rule.c | 44 ++++++++++++++++++------------ drivers/net/mlx5/hws/mlx5dr_rule.h | 3 ++ drivers/net/mlx5/hws/mlx5dr_send.c | 8 ++++-- 3 files changed, 35 insertions(+), 20 deletions(-) diff --git a/drivers/net/mlx5/hws/mlx5dr_rule.c b/drivers/net/mlx5/hws/mlx5dr_rule.c index 550f00a4c1..74abb38163 100644 --- a/drivers/net/mlx5/hws/mlx5dr_rule.c +++ b/drivers/net/mlx5/hws/mlx5dr_rule.c @@ -157,6 +157,9 @@ static void mlx5dr_rule_save_resize_info(struct mlx5dr_rule *rule, struct mlx5dr_send_ste_attr *ste_attr) { + if (likely(!mlx5dr_matcher_is_resizable(rule->matcher))) + return; + rule->resize_info = simple_calloc(1, sizeof(*rule->resize_info)); if (unlikely(!rule->resize_info)) { assert(rule->resize_info); @@ -168,14 +171,16 @@ mlx5dr_rule_save_resize_info(struct mlx5dr_rule *rule, memcpy(rule->resize_info->data_seg, ste_attr->wqe_data, sizeof(rule->resize_info->data_seg)); + rule->resize_info->max_stes = rule->matcher->action_ste.max_stes; rule->resize_info->action_ste_pool = rule->matcher->action_ste.max_stes ? rule->matcher->action_ste.pool : NULL; } -static void mlx5dr_rule_clear_resize_info(struct mlx5dr_rule *rule) +void mlx5dr_rule_clear_resize_info(struct mlx5dr_rule *rule) { - if (rule->resize_info) { + if (unlikely(mlx5dr_matcher_is_resizable(rule->matcher) && + rule->resize_info)) { simple_free(rule->resize_info); rule->resize_info = NULL; } @@ -220,8 +225,6 @@ mlx5dr_rule_save_delete_info(struct mlx5dr_rule *rule, memcpy(&rule->tag.match, ste_attr->wqe_data->tag, MLX5DR_MATCH_TAG_SZ); return; } - - mlx5dr_rule_save_resize_info(rule, ste_attr); } static void @@ -231,11 +234,6 @@ mlx5dr_rule_clear_delete_info(struct mlx5dr_rule *rule) simple_free(rule->tag_ptr); return; } - - if (unlikely(mlx5dr_matcher_is_resizable(rule->matcher))) { - mlx5dr_rule_clear_resize_info(rule); - return; - } } static void @@ -288,19 +286,26 @@ void mlx5dr_rule_free_action_ste_idx(struct mlx5dr_rule *rule) { struct mlx5dr_matcher *matcher = rule->matcher; struct mlx5dr_pool *pool; + uint8_t max_stes; if (rule->action_ste_idx > -1 && !matcher->attr.optimize_using_rule_idx && !mlx5dr_matcher_is_insert_by_idx(matcher)) { struct mlx5dr_pool_chunk ste = {0}; + if (unlikely(mlx5dr_matcher_is_resizable(matcher))) { + /* Free the original action pool if rule was resized */ + max_stes = rule->resize_info->max_stes; + pool = rule->resize_info->action_ste_pool; + } else { + max_stes = matcher->action_ste.max_stes; + pool = matcher->action_ste.pool; + } + /* This release is safe only when the rule match part was deleted */ - ste.order = rte_log2_u32(matcher->action_ste.max_stes); + ste.order = rte_log2_u32(max_stes); ste.offset = rule->action_ste_idx; - /* Free the original action pool if rule was resized */ - pool = mlx5dr_matcher_is_resizable(matcher) ? rule->resize_info->action_ste_pool : - matcher->action_ste.pool; mlx5dr_pool_chunk_free(pool, &ste); } } @@ -442,9 +447,7 @@ static int mlx5dr_rule_create_hws_fw_wqe(struct mlx5dr_rule *rule, /* Send WQEs to FW */ mlx5dr_send_stes_fw(queue, &ste_attr); - /* Backup TAG on the rule for deletion, and save ctrl/data - * segments to be used when resizing the matcher. - */ + /* Backup TAG on the rule for deletion */ mlx5dr_rule_save_delete_info(rule, &ste_attr); mlx5dr_send_engine_inc_rule(queue); @@ -569,8 +572,10 @@ static int mlx5dr_rule_create_hws(struct mlx5dr_rule *rule, /* Backup TAG on the rule for deletion and resize info for * moving rules to a new matcher, only after insertion. */ - if (!is_update) + if (!is_update) { mlx5dr_rule_save_delete_info(rule, &ste_attr); + mlx5dr_rule_save_resize_info(rule, &ste_attr); + } mlx5dr_send_engine_inc_rule(queue); @@ -595,9 +600,12 @@ static void mlx5dr_rule_destroy_failed_hws(struct mlx5dr_rule *rule, /* Rule failed now we can safely release action STEs */ mlx5dr_rule_free_action_ste_idx(rule); - /* Clear complex tag or info that was saved for matcher resizing */ + /* Clear complex tag */ mlx5dr_rule_clear_delete_info(rule); + /* Clear info that was saved for resizing */ + mlx5dr_rule_clear_resize_info(rule); + /* If a rule that was indicated as burst (need to trigger HW) has failed * insertion we won't ring the HW as nothing is being written to the WQ. * In such case update the last WQE and ring the HW with that work diff --git a/drivers/net/mlx5/hws/mlx5dr_rule.h b/drivers/net/mlx5/hws/mlx5dr_rule.h index 33779ade48..3617fd59dd 100644 --- a/drivers/net/mlx5/hws/mlx5dr_rule.h +++ b/drivers/net/mlx5/hws/mlx5dr_rule.h @@ -44,6 +44,7 @@ struct mlx5dr_rule_resize_info { uint32_t rtc_1; uint32_t rule_idx; uint8_t state; + uint8_t max_stes; uint8_t ctrl_seg[MLX5DR_WQE_SZ_GTA_CTRL]; /* Ctrl segment of STE: 48 bytes */ uint8_t data_seg[MLX5DR_WQE_SZ_GTA_DATA]; /* Data segment of STE: 64 bytes */ }; @@ -74,6 +75,8 @@ int mlx5dr_rule_move_hws_add(struct mlx5dr_rule *rule, bool mlx5dr_rule_move_in_progress(struct mlx5dr_rule *rule); +void mlx5dr_rule_clear_resize_info(struct mlx5dr_rule *rule); + int mlx5dr_rule_create_root_no_comp(struct mlx5dr_rule *rule, const struct rte_flow_item items[], uint8_t num_actions, diff --git a/drivers/net/mlx5/hws/mlx5dr_send.c b/drivers/net/mlx5/hws/mlx5dr_send.c index 0120f03a48..3022c50260 100644 --- a/drivers/net/mlx5/hws/mlx5dr_send.c +++ b/drivers/net/mlx5/hws/mlx5dr_send.c @@ -523,9 +523,13 @@ static void mlx5dr_send_engine_update_rule(struct mlx5dr_send_engine *queue, */ priv->rule->status++; *status = RTE_FLOW_OP_SUCCESS; - /* Rule was deleted now we can safely release action STEs */ - if (priv->rule->status == MLX5DR_RULE_STATUS_DELETED) + /* Rule was deleted now we can safely release action STEs + * and clear resize info + */ + if (priv->rule->status == MLX5DR_RULE_STATUS_DELETED) { mlx5dr_rule_free_action_ste_idx(priv->rule); + mlx5dr_rule_clear_resize_info(priv->rule); + } } } } -- 2.25.1