141d07074SAlex Vesker // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
241d07074SAlex Vesker /* Copyright (c) 2019 Mellanox Technologies. */
341d07074SAlex Vesker
441d07074SAlex Vesker #include "dr_types.h"
541d07074SAlex Vesker
617b3222eSYevgeny Kliteynik #if defined(CONFIG_FRAME_WARN) && (CONFIG_FRAME_WARN < 2048)
717b3222eSYevgeny Kliteynik /* don't try to optimize STE allocation if the stack is too constaraining */
817b3222eSYevgeny Kliteynik #define DR_RULE_MAX_STES_OPTIMIZED 0
917b3222eSYevgeny Kliteynik #else
10b9b81e1eSYevgeny Kliteynik #define DR_RULE_MAX_STES_OPTIMIZED 5
1117b3222eSYevgeny Kliteynik #endif
12b9b81e1eSYevgeny Kliteynik #define DR_RULE_MAX_STE_CHAIN_OPTIMIZED (DR_RULE_MAX_STES_OPTIMIZED + DR_ACTION_MAX_STES)
1341d07074SAlex Vesker
dr_rule_append_to_miss_list(struct mlx5dr_domain * dmn,enum mlx5dr_domain_nic_type nic_type,struct mlx5dr_ste * new_last_ste,struct list_head * miss_list,struct list_head * send_list)1417b56073SYevgeny Kliteynik static int dr_rule_append_to_miss_list(struct mlx5dr_domain *dmn,
1517b56073SYevgeny Kliteynik enum mlx5dr_domain_nic_type nic_type,
166b93b400SYevgeny Kliteynik struct mlx5dr_ste *new_last_ste,
1741d07074SAlex Vesker struct list_head *miss_list,
1841d07074SAlex Vesker struct list_head *send_list)
1941d07074SAlex Vesker {
2017b56073SYevgeny Kliteynik struct mlx5dr_ste_ctx *ste_ctx = dmn->ste_ctx;
2141d07074SAlex Vesker struct mlx5dr_ste_send_info *ste_info_last;
2241d07074SAlex Vesker struct mlx5dr_ste *last_ste;
2341d07074SAlex Vesker
2441d07074SAlex Vesker /* The new entry will be inserted after the last */
2548cbde4bSAlex Vesker last_ste = list_last_entry(miss_list, struct mlx5dr_ste, miss_list_node);
2641d07074SAlex Vesker WARN_ON(!last_ste);
2741d07074SAlex Vesker
2817b56073SYevgeny Kliteynik ste_info_last = mlx5dr_send_info_alloc(dmn, nic_type);
2941d07074SAlex Vesker if (!ste_info_last)
3041d07074SAlex Vesker return -ENOMEM;
3141d07074SAlex Vesker
320d7f1595SRongwei Liu mlx5dr_ste_set_miss_addr(ste_ctx, mlx5dr_ste_get_hw_ste(last_ste),
3341d07074SAlex Vesker mlx5dr_ste_get_icm_addr(new_last_ste));
3441d07074SAlex Vesker list_add_tail(&new_last_ste->miss_list_node, miss_list);
3541d07074SAlex Vesker
36f06d4969SYevgeny Kliteynik mlx5dr_send_fill_and_append_ste_send_info(last_ste, DR_STE_SIZE_CTRL,
370d7f1595SRongwei Liu 0, mlx5dr_ste_get_hw_ste(last_ste),
3841d07074SAlex Vesker ste_info_last, send_list, true);
3941d07074SAlex Vesker
4041d07074SAlex Vesker return 0;
4141d07074SAlex Vesker }
4241d07074SAlex Vesker
dr_rule_set_last_ste_miss_addr(struct mlx5dr_matcher * matcher,struct mlx5dr_matcher_rx_tx * nic_matcher,u8 * hw_ste)43f31bda78SYevgeny Kliteynik static void dr_rule_set_last_ste_miss_addr(struct mlx5dr_matcher *matcher,
44f31bda78SYevgeny Kliteynik struct mlx5dr_matcher_rx_tx *nic_matcher,
45f31bda78SYevgeny Kliteynik u8 *hw_ste)
46f31bda78SYevgeny Kliteynik {
47f31bda78SYevgeny Kliteynik struct mlx5dr_ste_ctx *ste_ctx = matcher->tbl->dmn->ste_ctx;
48f31bda78SYevgeny Kliteynik u64 icm_addr;
49f31bda78SYevgeny Kliteynik
501207a772SYevgeny Kliteynik if (mlx5dr_ste_is_miss_addr_set(ste_ctx, hw_ste))
511207a772SYevgeny Kliteynik return;
521207a772SYevgeny Kliteynik
53f31bda78SYevgeny Kliteynik icm_addr = mlx5dr_icm_pool_get_chunk_icm_addr(nic_matcher->e_anchor->chunk);
54f31bda78SYevgeny Kliteynik mlx5dr_ste_set_miss_addr(ste_ctx, hw_ste, icm_addr);
55f31bda78SYevgeny Kliteynik }
56f31bda78SYevgeny Kliteynik
5741d07074SAlex Vesker static struct mlx5dr_ste *
dr_rule_create_collision_htbl(struct mlx5dr_matcher * matcher,struct mlx5dr_matcher_rx_tx * nic_matcher,u8 * hw_ste)5841d07074SAlex Vesker dr_rule_create_collision_htbl(struct mlx5dr_matcher *matcher,
5941d07074SAlex Vesker struct mlx5dr_matcher_rx_tx *nic_matcher,
6041d07074SAlex Vesker u8 *hw_ste)
6141d07074SAlex Vesker {
6241d07074SAlex Vesker struct mlx5dr_domain *dmn = matcher->tbl->dmn;
6341d07074SAlex Vesker struct mlx5dr_ste_htbl *new_htbl;
6441d07074SAlex Vesker struct mlx5dr_ste *ste;
6541d07074SAlex Vesker
6641d07074SAlex Vesker /* Create new table for miss entry */
6741d07074SAlex Vesker new_htbl = mlx5dr_ste_htbl_alloc(dmn->ste_icm_pool,
6841d07074SAlex Vesker DR_CHUNK_SIZE_1,
6941d07074SAlex Vesker MLX5DR_STE_LU_TYPE_DONT_CARE,
7041d07074SAlex Vesker 0);
7141d07074SAlex Vesker if (!new_htbl) {
7241d07074SAlex Vesker mlx5dr_dbg(dmn, "Failed allocating collision table\n");
7341d07074SAlex Vesker return NULL;
7441d07074SAlex Vesker }
7541d07074SAlex Vesker
7641d07074SAlex Vesker /* One and only entry, never grows */
77597534bdSRongwei Liu ste = new_htbl->chunk->ste_arr;
78f31bda78SYevgeny Kliteynik dr_rule_set_last_ste_miss_addr(matcher, nic_matcher, hw_ste);
7941d07074SAlex Vesker mlx5dr_htbl_get(new_htbl);
8041d07074SAlex Vesker
8141d07074SAlex Vesker return ste;
8241d07074SAlex Vesker }
8341d07074SAlex Vesker
8441d07074SAlex Vesker static struct mlx5dr_ste *
dr_rule_create_collision_entry(struct mlx5dr_matcher * matcher,struct mlx5dr_matcher_rx_tx * nic_matcher,u8 * hw_ste,struct mlx5dr_ste * orig_ste)8541d07074SAlex Vesker dr_rule_create_collision_entry(struct mlx5dr_matcher *matcher,
8641d07074SAlex Vesker struct mlx5dr_matcher_rx_tx *nic_matcher,
8741d07074SAlex Vesker u8 *hw_ste,
8841d07074SAlex Vesker struct mlx5dr_ste *orig_ste)
8941d07074SAlex Vesker {
9041d07074SAlex Vesker struct mlx5dr_ste *ste;
9141d07074SAlex Vesker
9241d07074SAlex Vesker ste = dr_rule_create_collision_htbl(matcher, nic_matcher, hw_ste);
9341d07074SAlex Vesker if (!ste) {
9441d07074SAlex Vesker mlx5dr_dbg(matcher->tbl->dmn, "Failed creating collision entry\n");
9541d07074SAlex Vesker return NULL;
9641d07074SAlex Vesker }
9741d07074SAlex Vesker
9841d07074SAlex Vesker ste->ste_chain_location = orig_ste->ste_chain_location;
998a015baeSYevgeny Kliteynik ste->htbl->pointing_ste = orig_ste->htbl->pointing_ste;
10041d07074SAlex Vesker
10141d07074SAlex Vesker /* In collision entry, all members share the same miss_list_head */
102597534bdSRongwei Liu ste->htbl->chunk->miss_list = mlx5dr_ste_get_miss_list(orig_ste);
10341d07074SAlex Vesker
10441d07074SAlex Vesker /* Next table */
10541d07074SAlex Vesker if (mlx5dr_ste_create_next_htbl(matcher, nic_matcher, ste, hw_ste,
10641d07074SAlex Vesker DR_CHUNK_SIZE_1)) {
10741d07074SAlex Vesker mlx5dr_dbg(matcher->tbl->dmn, "Failed allocating table\n");
10841d07074SAlex Vesker goto free_tbl;
10941d07074SAlex Vesker }
11041d07074SAlex Vesker
11141d07074SAlex Vesker return ste;
11241d07074SAlex Vesker
11341d07074SAlex Vesker free_tbl:
11441d07074SAlex Vesker mlx5dr_ste_free(ste, matcher, nic_matcher);
11541d07074SAlex Vesker return NULL;
11641d07074SAlex Vesker }
11741d07074SAlex Vesker
11841d07074SAlex Vesker static int
dr_rule_handle_one_ste_in_update_list(struct mlx5dr_ste_send_info * ste_info,struct mlx5dr_domain * dmn)11941d07074SAlex Vesker dr_rule_handle_one_ste_in_update_list(struct mlx5dr_ste_send_info *ste_info,
12041d07074SAlex Vesker struct mlx5dr_domain *dmn)
12141d07074SAlex Vesker {
12241d07074SAlex Vesker int ret;
12341d07074SAlex Vesker
12441d07074SAlex Vesker list_del(&ste_info->send_list);
125f06d4969SYevgeny Kliteynik
126f06d4969SYevgeny Kliteynik /* Copy data to ste, only reduced size or control, the last 16B (mask)
12741d07074SAlex Vesker * is already written to the hw.
12841d07074SAlex Vesker */
129f06d4969SYevgeny Kliteynik if (ste_info->size == DR_STE_SIZE_CTRL)
1300d7f1595SRongwei Liu memcpy(mlx5dr_ste_get_hw_ste(ste_info->ste),
1310d7f1595SRongwei Liu ste_info->data, DR_STE_SIZE_CTRL);
132f06d4969SYevgeny Kliteynik else
1330d7f1595SRongwei Liu memcpy(mlx5dr_ste_get_hw_ste(ste_info->ste),
1340d7f1595SRongwei Liu ste_info->data, DR_STE_SIZE_REDUCED);
13541d07074SAlex Vesker
1364fe45e1dSYevgeny Kliteynik ret = mlx5dr_send_postsend_ste(dmn, ste_info->ste, ste_info->data,
1374fe45e1dSYevgeny Kliteynik ste_info->size, ste_info->offset);
1384fe45e1dSYevgeny Kliteynik if (ret)
1394fe45e1dSYevgeny Kliteynik goto out;
1404fe45e1dSYevgeny Kliteynik
14141d07074SAlex Vesker out:
14217b56073SYevgeny Kliteynik mlx5dr_send_info_free(ste_info);
14341d07074SAlex Vesker return ret;
14441d07074SAlex Vesker }
14541d07074SAlex Vesker
dr_rule_send_update_list(struct list_head * send_ste_list,struct mlx5dr_domain * dmn,bool is_reverse)14641d07074SAlex Vesker static int dr_rule_send_update_list(struct list_head *send_ste_list,
14741d07074SAlex Vesker struct mlx5dr_domain *dmn,
14841d07074SAlex Vesker bool is_reverse)
14941d07074SAlex Vesker {
15041d07074SAlex Vesker struct mlx5dr_ste_send_info *ste_info, *tmp_ste_info;
15141d07074SAlex Vesker int ret;
15241d07074SAlex Vesker
15341d07074SAlex Vesker if (is_reverse) {
15441d07074SAlex Vesker list_for_each_entry_safe_reverse(ste_info, tmp_ste_info,
15541d07074SAlex Vesker send_ste_list, send_list) {
15641d07074SAlex Vesker ret = dr_rule_handle_one_ste_in_update_list(ste_info,
15741d07074SAlex Vesker dmn);
15841d07074SAlex Vesker if (ret)
15941d07074SAlex Vesker return ret;
16041d07074SAlex Vesker }
16141d07074SAlex Vesker } else {
16241d07074SAlex Vesker list_for_each_entry_safe(ste_info, tmp_ste_info,
16341d07074SAlex Vesker send_ste_list, send_list) {
16441d07074SAlex Vesker ret = dr_rule_handle_one_ste_in_update_list(ste_info,
16541d07074SAlex Vesker dmn);
16641d07074SAlex Vesker if (ret)
16741d07074SAlex Vesker return ret;
16841d07074SAlex Vesker }
16941d07074SAlex Vesker }
17041d07074SAlex Vesker
17141d07074SAlex Vesker return 0;
17241d07074SAlex Vesker }
17341d07074SAlex Vesker
17441d07074SAlex Vesker static struct mlx5dr_ste *
dr_rule_find_ste_in_miss_list(struct list_head * miss_list,u8 * hw_ste)17541d07074SAlex Vesker dr_rule_find_ste_in_miss_list(struct list_head *miss_list, u8 *hw_ste)
17641d07074SAlex Vesker {
17741d07074SAlex Vesker struct mlx5dr_ste *ste;
17841d07074SAlex Vesker
17941d07074SAlex Vesker if (list_empty(miss_list))
18041d07074SAlex Vesker return NULL;
18141d07074SAlex Vesker
18241d07074SAlex Vesker /* Check if hw_ste is present in the list */
18341d07074SAlex Vesker list_for_each_entry(ste, miss_list, miss_list_node) {
1840d7f1595SRongwei Liu if (mlx5dr_ste_equal_tag(mlx5dr_ste_get_hw_ste(ste), hw_ste))
18541d07074SAlex Vesker return ste;
18641d07074SAlex Vesker }
18741d07074SAlex Vesker
18841d07074SAlex Vesker return NULL;
18941d07074SAlex Vesker }
19041d07074SAlex Vesker
19141d07074SAlex Vesker static struct mlx5dr_ste *
dr_rule_rehash_handle_collision(struct mlx5dr_matcher * matcher,struct mlx5dr_matcher_rx_tx * nic_matcher,struct list_head * update_list,struct mlx5dr_ste * col_ste,u8 * hw_ste)19241d07074SAlex Vesker dr_rule_rehash_handle_collision(struct mlx5dr_matcher *matcher,
19341d07074SAlex Vesker struct mlx5dr_matcher_rx_tx *nic_matcher,
19441d07074SAlex Vesker struct list_head *update_list,
19541d07074SAlex Vesker struct mlx5dr_ste *col_ste,
19641d07074SAlex Vesker u8 *hw_ste)
19741d07074SAlex Vesker {
1986b93b400SYevgeny Kliteynik struct mlx5dr_domain *dmn = matcher->tbl->dmn;
19941d07074SAlex Vesker struct mlx5dr_ste *new_ste;
20041d07074SAlex Vesker int ret;
20141d07074SAlex Vesker
20241d07074SAlex Vesker new_ste = dr_rule_create_collision_htbl(matcher, nic_matcher, hw_ste);
20341d07074SAlex Vesker if (!new_ste)
20441d07074SAlex Vesker return NULL;
20541d07074SAlex Vesker
2068a015baeSYevgeny Kliteynik /* Update collision pointing STE */
2078a015baeSYevgeny Kliteynik new_ste->htbl->pointing_ste = col_ste->htbl->pointing_ste;
2088a015baeSYevgeny Kliteynik
20941d07074SAlex Vesker /* In collision entry, all members share the same miss_list_head */
210597534bdSRongwei Liu new_ste->htbl->chunk->miss_list = mlx5dr_ste_get_miss_list(col_ste);
21141d07074SAlex Vesker
21241d07074SAlex Vesker /* Update the previous from the list */
21317b56073SYevgeny Kliteynik ret = dr_rule_append_to_miss_list(dmn, nic_matcher->nic_tbl->nic_dmn->type,
21417b56073SYevgeny Kliteynik new_ste, mlx5dr_ste_get_miss_list(col_ste),
21541d07074SAlex Vesker update_list);
21641d07074SAlex Vesker if (ret) {
2176b93b400SYevgeny Kliteynik mlx5dr_dbg(dmn, "Failed update dup entry\n");
21841d07074SAlex Vesker goto err_exit;
21941d07074SAlex Vesker }
22041d07074SAlex Vesker
22141d07074SAlex Vesker return new_ste;
22241d07074SAlex Vesker
22341d07074SAlex Vesker err_exit:
22441d07074SAlex Vesker mlx5dr_ste_free(new_ste, matcher, nic_matcher);
22541d07074SAlex Vesker return NULL;
22641d07074SAlex Vesker }
22741d07074SAlex Vesker
dr_rule_rehash_copy_ste_ctrl(struct mlx5dr_matcher * matcher,struct mlx5dr_matcher_rx_tx * nic_matcher,struct mlx5dr_ste * cur_ste,struct mlx5dr_ste * new_ste)22841d07074SAlex Vesker static void dr_rule_rehash_copy_ste_ctrl(struct mlx5dr_matcher *matcher,
22941d07074SAlex Vesker struct mlx5dr_matcher_rx_tx *nic_matcher,
23041d07074SAlex Vesker struct mlx5dr_ste *cur_ste,
23141d07074SAlex Vesker struct mlx5dr_ste *new_ste)
23241d07074SAlex Vesker {
23341d07074SAlex Vesker new_ste->next_htbl = cur_ste->next_htbl;
23441d07074SAlex Vesker new_ste->ste_chain_location = cur_ste->ste_chain_location;
23541d07074SAlex Vesker
2368a015baeSYevgeny Kliteynik if (new_ste->next_htbl)
23741d07074SAlex Vesker new_ste->next_htbl->pointing_ste = new_ste;
23841d07074SAlex Vesker
23941d07074SAlex Vesker /* We need to copy the refcount since this ste
24041d07074SAlex Vesker * may have been traversed several times
24141d07074SAlex Vesker */
2424ce380caSYevgeny Kliteynik new_ste->refcount = cur_ste->refcount;
24341d07074SAlex Vesker
2448a015baeSYevgeny Kliteynik /* Link old STEs rule to the new ste */
2458a015baeSYevgeny Kliteynik mlx5dr_rule_set_last_member(cur_ste->rule_rx_tx, new_ste, false);
24641d07074SAlex Vesker }
24741d07074SAlex Vesker
24841d07074SAlex Vesker static struct mlx5dr_ste *
dr_rule_rehash_copy_ste(struct mlx5dr_matcher * matcher,struct mlx5dr_matcher_rx_tx * nic_matcher,struct mlx5dr_ste * cur_ste,struct mlx5dr_ste_htbl * new_htbl,struct list_head * update_list)24941d07074SAlex Vesker dr_rule_rehash_copy_ste(struct mlx5dr_matcher *matcher,
25041d07074SAlex Vesker struct mlx5dr_matcher_rx_tx *nic_matcher,
25141d07074SAlex Vesker struct mlx5dr_ste *cur_ste,
25241d07074SAlex Vesker struct mlx5dr_ste_htbl *new_htbl,
25341d07074SAlex Vesker struct list_head *update_list)
25441d07074SAlex Vesker {
2556b93b400SYevgeny Kliteynik struct mlx5dr_domain *dmn = matcher->tbl->dmn;
25641d07074SAlex Vesker struct mlx5dr_ste_send_info *ste_info;
25741d07074SAlex Vesker bool use_update_list = false;
25841d07074SAlex Vesker u8 hw_ste[DR_STE_SIZE] = {};
25941d07074SAlex Vesker struct mlx5dr_ste *new_ste;
26041d07074SAlex Vesker int new_idx;
26141d07074SAlex Vesker u8 sb_idx;
26241d07074SAlex Vesker
26341d07074SAlex Vesker /* Copy STE mask from the matcher */
26441d07074SAlex Vesker sb_idx = cur_ste->ste_chain_location - 1;
26541d07074SAlex Vesker mlx5dr_ste_set_bit_mask(hw_ste, nic_matcher->ste_builder[sb_idx].bit_mask);
26641d07074SAlex Vesker
26741d07074SAlex Vesker /* Copy STE control and tag */
2680d7f1595SRongwei Liu memcpy(hw_ste, mlx5dr_ste_get_hw_ste(cur_ste), DR_STE_SIZE_REDUCED);
269f31bda78SYevgeny Kliteynik dr_rule_set_last_ste_miss_addr(matcher, nic_matcher, hw_ste);
27041d07074SAlex Vesker
27141d07074SAlex Vesker new_idx = mlx5dr_ste_calc_hash_index(hw_ste, new_htbl);
272597534bdSRongwei Liu new_ste = &new_htbl->chunk->ste_arr[new_idx];
27341d07074SAlex Vesker
27497ffd895SYevgeny Kliteynik if (mlx5dr_ste_is_not_used(new_ste)) {
27541d07074SAlex Vesker mlx5dr_htbl_get(new_htbl);
27641d07074SAlex Vesker list_add_tail(&new_ste->miss_list_node,
27741d07074SAlex Vesker mlx5dr_ste_get_miss_list(new_ste));
27841d07074SAlex Vesker } else {
27941d07074SAlex Vesker new_ste = dr_rule_rehash_handle_collision(matcher,
28041d07074SAlex Vesker nic_matcher,
28141d07074SAlex Vesker update_list,
28241d07074SAlex Vesker new_ste,
28341d07074SAlex Vesker hw_ste);
28441d07074SAlex Vesker if (!new_ste) {
2856b93b400SYevgeny Kliteynik mlx5dr_dbg(dmn, "Failed adding collision entry, index: %d\n",
28641d07074SAlex Vesker new_idx);
28741d07074SAlex Vesker return NULL;
28841d07074SAlex Vesker }
28941d07074SAlex Vesker new_htbl->ctrl.num_of_collisions++;
29041d07074SAlex Vesker use_update_list = true;
29141d07074SAlex Vesker }
29241d07074SAlex Vesker
2930d7f1595SRongwei Liu memcpy(mlx5dr_ste_get_hw_ste(new_ste), hw_ste, DR_STE_SIZE_REDUCED);
29441d07074SAlex Vesker
29541d07074SAlex Vesker new_htbl->ctrl.num_of_valid_entries++;
29641d07074SAlex Vesker
29741d07074SAlex Vesker if (use_update_list) {
29817b56073SYevgeny Kliteynik ste_info = mlx5dr_send_info_alloc(dmn,
29917b56073SYevgeny Kliteynik nic_matcher->nic_tbl->nic_dmn->type);
30041d07074SAlex Vesker if (!ste_info)
30141d07074SAlex Vesker goto err_exit;
30241d07074SAlex Vesker
30341d07074SAlex Vesker mlx5dr_send_fill_and_append_ste_send_info(new_ste, DR_STE_SIZE, 0,
30441d07074SAlex Vesker hw_ste, ste_info,
30541d07074SAlex Vesker update_list, true);
30641d07074SAlex Vesker }
30741d07074SAlex Vesker
30841d07074SAlex Vesker dr_rule_rehash_copy_ste_ctrl(matcher, nic_matcher, cur_ste, new_ste);
30941d07074SAlex Vesker
31041d07074SAlex Vesker return new_ste;
31141d07074SAlex Vesker
31241d07074SAlex Vesker err_exit:
31341d07074SAlex Vesker mlx5dr_ste_free(new_ste, matcher, nic_matcher);
31441d07074SAlex Vesker return NULL;
31541d07074SAlex Vesker }
31641d07074SAlex Vesker
dr_rule_rehash_copy_miss_list(struct mlx5dr_matcher * matcher,struct mlx5dr_matcher_rx_tx * nic_matcher,struct list_head * cur_miss_list,struct mlx5dr_ste_htbl * new_htbl,struct list_head * update_list)31741d07074SAlex Vesker static int dr_rule_rehash_copy_miss_list(struct mlx5dr_matcher *matcher,
31841d07074SAlex Vesker struct mlx5dr_matcher_rx_tx *nic_matcher,
31941d07074SAlex Vesker struct list_head *cur_miss_list,
32041d07074SAlex Vesker struct mlx5dr_ste_htbl *new_htbl,
32141d07074SAlex Vesker struct list_head *update_list)
32241d07074SAlex Vesker {
32341d07074SAlex Vesker struct mlx5dr_ste *tmp_ste, *cur_ste, *new_ste;
32441d07074SAlex Vesker
32541d07074SAlex Vesker if (list_empty(cur_miss_list))
32641d07074SAlex Vesker return 0;
32741d07074SAlex Vesker
32841d07074SAlex Vesker list_for_each_entry_safe(cur_ste, tmp_ste, cur_miss_list, miss_list_node) {
32941d07074SAlex Vesker new_ste = dr_rule_rehash_copy_ste(matcher,
33041d07074SAlex Vesker nic_matcher,
33141d07074SAlex Vesker cur_ste,
33241d07074SAlex Vesker new_htbl,
33341d07074SAlex Vesker update_list);
33441d07074SAlex Vesker if (!new_ste)
33541d07074SAlex Vesker goto err_insert;
33641d07074SAlex Vesker
33741d07074SAlex Vesker list_del(&cur_ste->miss_list_node);
33841d07074SAlex Vesker mlx5dr_htbl_put(cur_ste->htbl);
33941d07074SAlex Vesker }
34041d07074SAlex Vesker return 0;
34141d07074SAlex Vesker
34241d07074SAlex Vesker err_insert:
34341d07074SAlex Vesker mlx5dr_err(matcher->tbl->dmn, "Fatal error during resize\n");
34441d07074SAlex Vesker WARN_ON(true);
34541d07074SAlex Vesker return -EINVAL;
34641d07074SAlex Vesker }
34741d07074SAlex Vesker
dr_rule_rehash_copy_htbl(struct mlx5dr_matcher * matcher,struct mlx5dr_matcher_rx_tx * nic_matcher,struct mlx5dr_ste_htbl * cur_htbl,struct mlx5dr_ste_htbl * new_htbl,struct list_head * update_list)34841d07074SAlex Vesker static int dr_rule_rehash_copy_htbl(struct mlx5dr_matcher *matcher,
34941d07074SAlex Vesker struct mlx5dr_matcher_rx_tx *nic_matcher,
35041d07074SAlex Vesker struct mlx5dr_ste_htbl *cur_htbl,
35141d07074SAlex Vesker struct mlx5dr_ste_htbl *new_htbl,
35241d07074SAlex Vesker struct list_head *update_list)
35341d07074SAlex Vesker {
35441d07074SAlex Vesker struct mlx5dr_ste *cur_ste;
35541d07074SAlex Vesker int cur_entries;
35641d07074SAlex Vesker int err = 0;
35741d07074SAlex Vesker int i;
35841d07074SAlex Vesker
359597534bdSRongwei Liu cur_entries = mlx5dr_icm_pool_chunk_size_to_entries(cur_htbl->chunk->size);
36041d07074SAlex Vesker
36141d07074SAlex Vesker if (cur_entries < 1) {
36241d07074SAlex Vesker mlx5dr_dbg(matcher->tbl->dmn, "Invalid number of entries\n");
36341d07074SAlex Vesker return -EINVAL;
36441d07074SAlex Vesker }
36541d07074SAlex Vesker
36641d07074SAlex Vesker for (i = 0; i < cur_entries; i++) {
367597534bdSRongwei Liu cur_ste = &cur_htbl->chunk->ste_arr[i];
36897ffd895SYevgeny Kliteynik if (mlx5dr_ste_is_not_used(cur_ste)) /* Empty, nothing to copy */
36941d07074SAlex Vesker continue;
37041d07074SAlex Vesker
37141d07074SAlex Vesker err = dr_rule_rehash_copy_miss_list(matcher,
37241d07074SAlex Vesker nic_matcher,
37341d07074SAlex Vesker mlx5dr_ste_get_miss_list(cur_ste),
37441d07074SAlex Vesker new_htbl,
37541d07074SAlex Vesker update_list);
37641d07074SAlex Vesker if (err)
37741d07074SAlex Vesker goto clean_copy;
3781bea2dc7SYevgeny Kliteynik
3791bea2dc7SYevgeny Kliteynik /* In order to decrease the number of allocated ste_send_info
3801bea2dc7SYevgeny Kliteynik * structs, send the current table row now.
3811bea2dc7SYevgeny Kliteynik */
3821bea2dc7SYevgeny Kliteynik err = dr_rule_send_update_list(update_list, matcher->tbl->dmn, false);
3831bea2dc7SYevgeny Kliteynik if (err) {
3841bea2dc7SYevgeny Kliteynik mlx5dr_dbg(matcher->tbl->dmn, "Failed updating table to HW\n");
3851bea2dc7SYevgeny Kliteynik goto clean_copy;
3861bea2dc7SYevgeny Kliteynik }
38741d07074SAlex Vesker }
38841d07074SAlex Vesker
38941d07074SAlex Vesker clean_copy:
39041d07074SAlex Vesker return err;
39141d07074SAlex Vesker }
39241d07074SAlex Vesker
39341d07074SAlex Vesker static struct mlx5dr_ste_htbl *
dr_rule_rehash_htbl(struct mlx5dr_rule * rule,struct mlx5dr_rule_rx_tx * nic_rule,struct mlx5dr_ste_htbl * cur_htbl,u8 ste_location,struct list_head * update_list,enum mlx5dr_icm_chunk_size new_size)39441d07074SAlex Vesker dr_rule_rehash_htbl(struct mlx5dr_rule *rule,
39541d07074SAlex Vesker struct mlx5dr_rule_rx_tx *nic_rule,
39641d07074SAlex Vesker struct mlx5dr_ste_htbl *cur_htbl,
39741d07074SAlex Vesker u8 ste_location,
39841d07074SAlex Vesker struct list_head *update_list,
39941d07074SAlex Vesker enum mlx5dr_icm_chunk_size new_size)
40041d07074SAlex Vesker {
40141d07074SAlex Vesker struct mlx5dr_ste_send_info *del_ste_info, *tmp_ste_info;
40241d07074SAlex Vesker struct mlx5dr_matcher *matcher = rule->matcher;
40341d07074SAlex Vesker struct mlx5dr_domain *dmn = matcher->tbl->dmn;
40441d07074SAlex Vesker struct mlx5dr_matcher_rx_tx *nic_matcher;
40541d07074SAlex Vesker struct mlx5dr_ste_send_info *ste_info;
40641d07074SAlex Vesker struct mlx5dr_htbl_connect_info info;
40741d07074SAlex Vesker struct mlx5dr_domain_rx_tx *nic_dmn;
40841d07074SAlex Vesker u8 formatted_ste[DR_STE_SIZE] = {};
40941d07074SAlex Vesker LIST_HEAD(rehash_table_send_list);
41041d07074SAlex Vesker struct mlx5dr_ste *ste_to_update;
41141d07074SAlex Vesker struct mlx5dr_ste_htbl *new_htbl;
41241d07074SAlex Vesker int err;
41341d07074SAlex Vesker
41441d07074SAlex Vesker nic_matcher = nic_rule->nic_matcher;
41541d07074SAlex Vesker nic_dmn = nic_matcher->nic_tbl->nic_dmn;
41641d07074SAlex Vesker
41717b56073SYevgeny Kliteynik ste_info = mlx5dr_send_info_alloc(dmn,
41817b56073SYevgeny Kliteynik nic_matcher->nic_tbl->nic_dmn->type);
41941d07074SAlex Vesker if (!ste_info)
42041d07074SAlex Vesker return NULL;
42141d07074SAlex Vesker
42241d07074SAlex Vesker new_htbl = mlx5dr_ste_htbl_alloc(dmn->ste_icm_pool,
42341d07074SAlex Vesker new_size,
42441d07074SAlex Vesker cur_htbl->lu_type,
42541d07074SAlex Vesker cur_htbl->byte_mask);
42641d07074SAlex Vesker if (!new_htbl) {
42741d07074SAlex Vesker mlx5dr_err(dmn, "Failed to allocate new hash table\n");
42841d07074SAlex Vesker goto free_ste_info;
42941d07074SAlex Vesker }
43041d07074SAlex Vesker
43141d07074SAlex Vesker /* Write new table to HW */
43241d07074SAlex Vesker info.type = CONNECT_MISS;
4335c4f9b6eSRongwei Liu info.miss_icm_addr = mlx5dr_icm_pool_get_chunk_icm_addr(nic_matcher->e_anchor->chunk);
4346b93b400SYevgeny Kliteynik mlx5dr_ste_set_formatted_ste(dmn->ste_ctx,
4356b93b400SYevgeny Kliteynik dmn->info.caps.gvmi,
43646f2a8aeSYevgeny Kliteynik nic_dmn->type,
43741d07074SAlex Vesker new_htbl,
43841d07074SAlex Vesker formatted_ste,
43941d07074SAlex Vesker &info);
44041d07074SAlex Vesker
44141d07074SAlex Vesker new_htbl->pointing_ste = cur_htbl->pointing_ste;
44241d07074SAlex Vesker new_htbl->pointing_ste->next_htbl = new_htbl;
44341d07074SAlex Vesker err = dr_rule_rehash_copy_htbl(matcher,
44441d07074SAlex Vesker nic_matcher,
44541d07074SAlex Vesker cur_htbl,
44641d07074SAlex Vesker new_htbl,
44741d07074SAlex Vesker &rehash_table_send_list);
44841d07074SAlex Vesker if (err)
44941d07074SAlex Vesker goto free_new_htbl;
45041d07074SAlex Vesker
45141d07074SAlex Vesker if (mlx5dr_send_postsend_htbl(dmn, new_htbl, formatted_ste,
45241d07074SAlex Vesker nic_matcher->ste_builder[ste_location - 1].bit_mask)) {
45341d07074SAlex Vesker mlx5dr_err(dmn, "Failed writing table to HW\n");
45441d07074SAlex Vesker goto free_new_htbl;
45541d07074SAlex Vesker }
45641d07074SAlex Vesker
45741d07074SAlex Vesker /* Writing to the hw is done in regular order of rehash_table_send_list,
45841d07074SAlex Vesker * in order to have the origin data written before the miss address of
45941d07074SAlex Vesker * collision entries, if exists.
46041d07074SAlex Vesker */
46141d07074SAlex Vesker if (dr_rule_send_update_list(&rehash_table_send_list, dmn, false)) {
46241d07074SAlex Vesker mlx5dr_err(dmn, "Failed updating table to HW\n");
46341d07074SAlex Vesker goto free_ste_list;
46441d07074SAlex Vesker }
46541d07074SAlex Vesker
46641d07074SAlex Vesker /* Connect previous hash table to current */
46741d07074SAlex Vesker if (ste_location == 1) {
46841d07074SAlex Vesker /* The previous table is an anchor, anchors size is always one STE */
46941d07074SAlex Vesker struct mlx5dr_ste_htbl *prev_htbl = cur_htbl->pointing_ste->htbl;
47041d07074SAlex Vesker
47141d07074SAlex Vesker /* On matcher s_anchor we keep an extra refcount */
47241d07074SAlex Vesker mlx5dr_htbl_get(new_htbl);
47341d07074SAlex Vesker mlx5dr_htbl_put(cur_htbl);
47441d07074SAlex Vesker
47541d07074SAlex Vesker nic_matcher->s_htbl = new_htbl;
47641d07074SAlex Vesker
47741d07074SAlex Vesker /* It is safe to operate dr_ste_set_hit_addr on the hw_ste here
47841d07074SAlex Vesker * (48B len) which works only on first 32B
47941d07074SAlex Vesker */
4806b93b400SYevgeny Kliteynik mlx5dr_ste_set_hit_addr(dmn->ste_ctx,
4810d7f1595SRongwei Liu prev_htbl->chunk->hw_ste_arr,
4825c4f9b6eSRongwei Liu mlx5dr_icm_pool_get_chunk_icm_addr(new_htbl->chunk),
483f51bb517SRongwei Liu mlx5dr_icm_pool_get_chunk_num_of_entries(new_htbl->chunk));
48441d07074SAlex Vesker
485597534bdSRongwei Liu ste_to_update = &prev_htbl->chunk->ste_arr[0];
48641d07074SAlex Vesker } else {
4876b93b400SYevgeny Kliteynik mlx5dr_ste_set_hit_addr_by_next_htbl(dmn->ste_ctx,
4880d7f1595SRongwei Liu mlx5dr_ste_get_hw_ste(cur_htbl->pointing_ste),
48941d07074SAlex Vesker new_htbl);
49041d07074SAlex Vesker ste_to_update = cur_htbl->pointing_ste;
49141d07074SAlex Vesker }
49241d07074SAlex Vesker
493f06d4969SYevgeny Kliteynik mlx5dr_send_fill_and_append_ste_send_info(ste_to_update, DR_STE_SIZE_CTRL,
4940d7f1595SRongwei Liu 0, mlx5dr_ste_get_hw_ste(ste_to_update),
4950d7f1595SRongwei Liu ste_info, update_list, false);
49641d07074SAlex Vesker
49741d07074SAlex Vesker return new_htbl;
49841d07074SAlex Vesker
49941d07074SAlex Vesker free_ste_list:
50041d07074SAlex Vesker /* Clean all ste_info's from the new table */
50141d07074SAlex Vesker list_for_each_entry_safe(del_ste_info, tmp_ste_info,
50241d07074SAlex Vesker &rehash_table_send_list, send_list) {
50341d07074SAlex Vesker list_del(&del_ste_info->send_list);
50417b56073SYevgeny Kliteynik mlx5dr_send_info_free(del_ste_info);
50541d07074SAlex Vesker }
50641d07074SAlex Vesker
50741d07074SAlex Vesker free_new_htbl:
50841d07074SAlex Vesker mlx5dr_ste_htbl_free(new_htbl);
50941d07074SAlex Vesker free_ste_info:
51017b56073SYevgeny Kliteynik mlx5dr_send_info_free(ste_info);
51141d07074SAlex Vesker mlx5dr_info(dmn, "Failed creating rehash table\n");
51241d07074SAlex Vesker return NULL;
51341d07074SAlex Vesker }
51441d07074SAlex Vesker
dr_rule_rehash(struct mlx5dr_rule * rule,struct mlx5dr_rule_rx_tx * nic_rule,struct mlx5dr_ste_htbl * cur_htbl,u8 ste_location,struct list_head * update_list)51541d07074SAlex Vesker static struct mlx5dr_ste_htbl *dr_rule_rehash(struct mlx5dr_rule *rule,
51641d07074SAlex Vesker struct mlx5dr_rule_rx_tx *nic_rule,
51741d07074SAlex Vesker struct mlx5dr_ste_htbl *cur_htbl,
51841d07074SAlex Vesker u8 ste_location,
51941d07074SAlex Vesker struct list_head *update_list)
52041d07074SAlex Vesker {
52141d07074SAlex Vesker struct mlx5dr_domain *dmn = rule->matcher->tbl->dmn;
52241d07074SAlex Vesker enum mlx5dr_icm_chunk_size new_size;
52341d07074SAlex Vesker
524597534bdSRongwei Liu new_size = mlx5dr_icm_next_higher_chunk(cur_htbl->chunk->size);
52541d07074SAlex Vesker new_size = min_t(u32, new_size, dmn->info.max_log_sw_icm_sz);
52641d07074SAlex Vesker
527597534bdSRongwei Liu if (new_size == cur_htbl->chunk->size)
52841d07074SAlex Vesker return NULL; /* Skip rehash, we already at the max size */
52941d07074SAlex Vesker
53041d07074SAlex Vesker return dr_rule_rehash_htbl(rule, nic_rule, cur_htbl, ste_location,
53141d07074SAlex Vesker update_list, new_size);
53241d07074SAlex Vesker }
53341d07074SAlex Vesker
53441d07074SAlex Vesker static struct mlx5dr_ste *
dr_rule_handle_collision(struct mlx5dr_matcher * matcher,struct mlx5dr_matcher_rx_tx * nic_matcher,struct mlx5dr_ste * ste,u8 * hw_ste,struct list_head * miss_list,struct list_head * send_list)53541d07074SAlex Vesker dr_rule_handle_collision(struct mlx5dr_matcher *matcher,
53641d07074SAlex Vesker struct mlx5dr_matcher_rx_tx *nic_matcher,
53741d07074SAlex Vesker struct mlx5dr_ste *ste,
53841d07074SAlex Vesker u8 *hw_ste,
53941d07074SAlex Vesker struct list_head *miss_list,
54041d07074SAlex Vesker struct list_head *send_list)
54141d07074SAlex Vesker {
5426b93b400SYevgeny Kliteynik struct mlx5dr_domain *dmn = matcher->tbl->dmn;
54341d07074SAlex Vesker struct mlx5dr_ste_send_info *ste_info;
54441d07074SAlex Vesker struct mlx5dr_ste *new_ste;
54541d07074SAlex Vesker
54617b56073SYevgeny Kliteynik ste_info = mlx5dr_send_info_alloc(dmn,
54717b56073SYevgeny Kliteynik nic_matcher->nic_tbl->nic_dmn->type);
54841d07074SAlex Vesker if (!ste_info)
54941d07074SAlex Vesker return NULL;
55041d07074SAlex Vesker
55141d07074SAlex Vesker new_ste = dr_rule_create_collision_entry(matcher, nic_matcher, hw_ste, ste);
55241d07074SAlex Vesker if (!new_ste)
55341d07074SAlex Vesker goto free_send_info;
55441d07074SAlex Vesker
55517b56073SYevgeny Kliteynik if (dr_rule_append_to_miss_list(dmn, nic_matcher->nic_tbl->nic_dmn->type,
55617b56073SYevgeny Kliteynik new_ste, miss_list, send_list)) {
5576b93b400SYevgeny Kliteynik mlx5dr_dbg(dmn, "Failed to update prev miss_list\n");
55841d07074SAlex Vesker goto err_exit;
55941d07074SAlex Vesker }
56041d07074SAlex Vesker
56141d07074SAlex Vesker mlx5dr_send_fill_and_append_ste_send_info(new_ste, DR_STE_SIZE, 0, hw_ste,
56241d07074SAlex Vesker ste_info, send_list, false);
56341d07074SAlex Vesker
56441d07074SAlex Vesker ste->htbl->ctrl.num_of_collisions++;
56541d07074SAlex Vesker ste->htbl->ctrl.num_of_valid_entries++;
56641d07074SAlex Vesker
56741d07074SAlex Vesker return new_ste;
56841d07074SAlex Vesker
56941d07074SAlex Vesker err_exit:
57041d07074SAlex Vesker mlx5dr_ste_free(new_ste, matcher, nic_matcher);
57141d07074SAlex Vesker free_send_info:
57217b56073SYevgeny Kliteynik mlx5dr_send_info_free(ste_info);
57341d07074SAlex Vesker return NULL;
57441d07074SAlex Vesker }
57541d07074SAlex Vesker
dr_rule_remove_action_members(struct mlx5dr_rule * rule)57641d07074SAlex Vesker static void dr_rule_remove_action_members(struct mlx5dr_rule *rule)
57741d07074SAlex Vesker {
57841d07074SAlex Vesker struct mlx5dr_rule_action_member *action_mem;
57941d07074SAlex Vesker struct mlx5dr_rule_action_member *tmp;
58041d07074SAlex Vesker
58141d07074SAlex Vesker list_for_each_entry_safe(action_mem, tmp, &rule->rule_actions_list, list) {
58241d07074SAlex Vesker list_del(&action_mem->list);
58341d07074SAlex Vesker refcount_dec(&action_mem->action->refcount);
58441d07074SAlex Vesker kvfree(action_mem);
58541d07074SAlex Vesker }
58641d07074SAlex Vesker }
58741d07074SAlex Vesker
dr_rule_add_action_members(struct mlx5dr_rule * rule,size_t num_actions,struct mlx5dr_action * actions[])58841d07074SAlex Vesker static int dr_rule_add_action_members(struct mlx5dr_rule *rule,
58941d07074SAlex Vesker size_t num_actions,
59041d07074SAlex Vesker struct mlx5dr_action *actions[])
59141d07074SAlex Vesker {
59241d07074SAlex Vesker struct mlx5dr_rule_action_member *action_mem;
59341d07074SAlex Vesker int i;
59441d07074SAlex Vesker
59541d07074SAlex Vesker for (i = 0; i < num_actions; i++) {
59641d07074SAlex Vesker action_mem = kvzalloc(sizeof(*action_mem), GFP_KERNEL);
59741d07074SAlex Vesker if (!action_mem)
59841d07074SAlex Vesker goto free_action_members;
59941d07074SAlex Vesker
60041d07074SAlex Vesker action_mem->action = actions[i];
60141d07074SAlex Vesker INIT_LIST_HEAD(&action_mem->list);
60241d07074SAlex Vesker list_add_tail(&action_mem->list, &rule->rule_actions_list);
60341d07074SAlex Vesker refcount_inc(&action_mem->action->refcount);
60441d07074SAlex Vesker }
60541d07074SAlex Vesker
60641d07074SAlex Vesker return 0;
60741d07074SAlex Vesker
60841d07074SAlex Vesker free_action_members:
60941d07074SAlex Vesker dr_rule_remove_action_members(rule);
61041d07074SAlex Vesker return -ENOMEM;
61141d07074SAlex Vesker }
61241d07074SAlex Vesker
mlx5dr_rule_set_last_member(struct mlx5dr_rule_rx_tx * nic_rule,struct mlx5dr_ste * ste,bool force)6138a015baeSYevgeny Kliteynik void mlx5dr_rule_set_last_member(struct mlx5dr_rule_rx_tx *nic_rule,
6148a015baeSYevgeny Kliteynik struct mlx5dr_ste *ste,
6158a015baeSYevgeny Kliteynik bool force)
61641d07074SAlex Vesker {
6178a015baeSYevgeny Kliteynik /* Update rule member is usually done for the last STE or during rule
6188a015baeSYevgeny Kliteynik * creation to recover from mid-creation failure (for this peruse the
6198a015baeSYevgeny Kliteynik * force flag is used)
6208a015baeSYevgeny Kliteynik */
6218a015baeSYevgeny Kliteynik if (ste->next_htbl && !force)
6228a015baeSYevgeny Kliteynik return;
62341d07074SAlex Vesker
6248a015baeSYevgeny Kliteynik /* Update is required since each rule keeps track of its last STE */
6258a015baeSYevgeny Kliteynik ste->rule_rx_tx = nic_rule;
6268a015baeSYevgeny Kliteynik nic_rule->last_rule_ste = ste;
6278a015baeSYevgeny Kliteynik }
6288a015baeSYevgeny Kliteynik
dr_rule_get_pointed_ste(struct mlx5dr_ste * curr_ste)6298a015baeSYevgeny Kliteynik static struct mlx5dr_ste *dr_rule_get_pointed_ste(struct mlx5dr_ste *curr_ste)
6308a015baeSYevgeny Kliteynik {
6318a015baeSYevgeny Kliteynik struct mlx5dr_ste *first_ste;
6328a015baeSYevgeny Kliteynik
6338a015baeSYevgeny Kliteynik first_ste = list_first_entry(mlx5dr_ste_get_miss_list(curr_ste),
6348a015baeSYevgeny Kliteynik struct mlx5dr_ste, miss_list_node);
6358a015baeSYevgeny Kliteynik
6368a015baeSYevgeny Kliteynik return first_ste->htbl->pointing_ste;
6378a015baeSYevgeny Kliteynik }
6388a015baeSYevgeny Kliteynik
mlx5dr_rule_get_reverse_rule_members(struct mlx5dr_ste ** ste_arr,struct mlx5dr_ste * curr_ste,int * num_of_stes)6398a015baeSYevgeny Kliteynik int mlx5dr_rule_get_reverse_rule_members(struct mlx5dr_ste **ste_arr,
6408a015baeSYevgeny Kliteynik struct mlx5dr_ste *curr_ste,
6418a015baeSYevgeny Kliteynik int *num_of_stes)
6428a015baeSYevgeny Kliteynik {
6438a015baeSYevgeny Kliteynik bool first = false;
6448a015baeSYevgeny Kliteynik
6458a015baeSYevgeny Kliteynik *num_of_stes = 0;
6468a015baeSYevgeny Kliteynik
6478a015baeSYevgeny Kliteynik if (!curr_ste)
6488a015baeSYevgeny Kliteynik return -ENOENT;
6498a015baeSYevgeny Kliteynik
6508a015baeSYevgeny Kliteynik /* Iterate from last to first */
6518a015baeSYevgeny Kliteynik while (!first) {
6528a015baeSYevgeny Kliteynik first = curr_ste->ste_chain_location == 1;
6538a015baeSYevgeny Kliteynik ste_arr[*num_of_stes] = curr_ste;
6548a015baeSYevgeny Kliteynik *num_of_stes += 1;
6558a015baeSYevgeny Kliteynik curr_ste = dr_rule_get_pointed_ste(curr_ste);
6568a015baeSYevgeny Kliteynik }
6578a015baeSYevgeny Kliteynik
6588a015baeSYevgeny Kliteynik return 0;
65941d07074SAlex Vesker }
66041d07074SAlex Vesker
dr_rule_clean_rule_members(struct mlx5dr_rule * rule,struct mlx5dr_rule_rx_tx * nic_rule)66141d07074SAlex Vesker static void dr_rule_clean_rule_members(struct mlx5dr_rule *rule,
66241d07074SAlex Vesker struct mlx5dr_rule_rx_tx *nic_rule)
66341d07074SAlex Vesker {
6648a015baeSYevgeny Kliteynik struct mlx5dr_ste *ste_arr[DR_RULE_MAX_STES + DR_ACTION_MAX_STES];
6658a015baeSYevgeny Kliteynik struct mlx5dr_ste *curr_ste = nic_rule->last_rule_ste;
6668a015baeSYevgeny Kliteynik int i;
66741d07074SAlex Vesker
6688a015baeSYevgeny Kliteynik if (mlx5dr_rule_get_reverse_rule_members(ste_arr, curr_ste, &i))
66941d07074SAlex Vesker return;
6708a015baeSYevgeny Kliteynik
6718a015baeSYevgeny Kliteynik while (i--)
6728a015baeSYevgeny Kliteynik mlx5dr_ste_put(ste_arr[i], rule->matcher, nic_rule->nic_matcher);
67341d07074SAlex Vesker }
67441d07074SAlex Vesker
dr_get_bits_per_mask(u16 byte_mask)67521586a0fSAlex Vesker static u16 dr_get_bits_per_mask(u16 byte_mask)
67621586a0fSAlex Vesker {
67721586a0fSAlex Vesker u16 bits = 0;
67821586a0fSAlex Vesker
67921586a0fSAlex Vesker while (byte_mask) {
68021586a0fSAlex Vesker byte_mask = byte_mask & (byte_mask - 1);
68121586a0fSAlex Vesker bits++;
68221586a0fSAlex Vesker }
68321586a0fSAlex Vesker
68421586a0fSAlex Vesker return bits;
68521586a0fSAlex Vesker }
68621586a0fSAlex Vesker
dr_rule_need_enlarge_hash(struct mlx5dr_ste_htbl * htbl,struct mlx5dr_domain * dmn,struct mlx5dr_domain_rx_tx * nic_dmn)68741d07074SAlex Vesker static bool dr_rule_need_enlarge_hash(struct mlx5dr_ste_htbl *htbl,
68841d07074SAlex Vesker struct mlx5dr_domain *dmn,
68941d07074SAlex Vesker struct mlx5dr_domain_rx_tx *nic_dmn)
69041d07074SAlex Vesker {
69141d07074SAlex Vesker struct mlx5dr_ste_htbl_ctrl *ctrl = &htbl->ctrl;
69232c8e3b2SYevgeny Kliteynik int threshold;
69341d07074SAlex Vesker
694597534bdSRongwei Liu if (dmn->info.max_log_sw_icm_sz <= htbl->chunk->size)
69541d07074SAlex Vesker return false;
69641d07074SAlex Vesker
69732c8e3b2SYevgeny Kliteynik if (!mlx5dr_ste_htbl_may_grow(htbl))
69841d07074SAlex Vesker return false;
69941d07074SAlex Vesker
700597534bdSRongwei Liu if (dr_get_bits_per_mask(htbl->byte_mask) * BITS_PER_BYTE <= htbl->chunk->size)
70121586a0fSAlex Vesker return false;
70221586a0fSAlex Vesker
70332c8e3b2SYevgeny Kliteynik threshold = mlx5dr_ste_htbl_increase_threshold(htbl);
70432c8e3b2SYevgeny Kliteynik if (ctrl->num_of_collisions >= threshold &&
70532c8e3b2SYevgeny Kliteynik (ctrl->num_of_valid_entries - ctrl->num_of_collisions) >= threshold)
70641d07074SAlex Vesker return true;
70741d07074SAlex Vesker
70841d07074SAlex Vesker return false;
70941d07074SAlex Vesker }
71041d07074SAlex Vesker
dr_rule_handle_action_stes(struct mlx5dr_rule * rule,struct mlx5dr_rule_rx_tx * nic_rule,struct list_head * send_ste_list,struct mlx5dr_ste * last_ste,u8 * hw_ste_arr,u32 new_hw_ste_arr_sz)71141d07074SAlex Vesker static int dr_rule_handle_action_stes(struct mlx5dr_rule *rule,
71241d07074SAlex Vesker struct mlx5dr_rule_rx_tx *nic_rule,
71341d07074SAlex Vesker struct list_head *send_ste_list,
71441d07074SAlex Vesker struct mlx5dr_ste *last_ste,
71541d07074SAlex Vesker u8 *hw_ste_arr,
71641d07074SAlex Vesker u32 new_hw_ste_arr_sz)
71741d07074SAlex Vesker {
71841d07074SAlex Vesker struct mlx5dr_matcher_rx_tx *nic_matcher = nic_rule->nic_matcher;
71941d07074SAlex Vesker struct mlx5dr_ste_send_info *ste_info_arr[DR_ACTION_MAX_STES];
72041d07074SAlex Vesker u8 num_of_builders = nic_matcher->num_of_builders;
72141d07074SAlex Vesker struct mlx5dr_matcher *matcher = rule->matcher;
7226b93b400SYevgeny Kliteynik struct mlx5dr_domain *dmn = matcher->tbl->dmn;
72341d07074SAlex Vesker u8 *curr_hw_ste, *prev_hw_ste;
72441d07074SAlex Vesker struct mlx5dr_ste *action_ste;
7258a015baeSYevgeny Kliteynik int i, k;
72641d07074SAlex Vesker
72741d07074SAlex Vesker /* Two cases:
72841d07074SAlex Vesker * 1. num_of_builders is equal to new_hw_ste_arr_sz, the action in the ste
72941d07074SAlex Vesker * 2. num_of_builders is less then new_hw_ste_arr_sz, new ste was added
73041d07074SAlex Vesker * to support the action.
73141d07074SAlex Vesker */
73241d07074SAlex Vesker
73341d07074SAlex Vesker for (i = num_of_builders, k = 0; i < new_hw_ste_arr_sz; i++, k++) {
73441d07074SAlex Vesker curr_hw_ste = hw_ste_arr + i * DR_STE_SIZE;
73541d07074SAlex Vesker prev_hw_ste = (i == 0) ? curr_hw_ste : hw_ste_arr + ((i - 1) * DR_STE_SIZE);
73641d07074SAlex Vesker action_ste = dr_rule_create_collision_htbl(matcher,
73741d07074SAlex Vesker nic_matcher,
73841d07074SAlex Vesker curr_hw_ste);
73941d07074SAlex Vesker if (!action_ste)
74041d07074SAlex Vesker return -ENOMEM;
74141d07074SAlex Vesker
74241d07074SAlex Vesker mlx5dr_ste_get(action_ste);
74341d07074SAlex Vesker
7448a015baeSYevgeny Kliteynik action_ste->htbl->pointing_ste = last_ste;
7458a015baeSYevgeny Kliteynik last_ste->next_htbl = action_ste->htbl;
7468a015baeSYevgeny Kliteynik last_ste = action_ste;
7478a015baeSYevgeny Kliteynik
74841d07074SAlex Vesker /* While free ste we go over the miss list, so add this ste to the list */
74941d07074SAlex Vesker list_add_tail(&action_ste->miss_list_node,
75041d07074SAlex Vesker mlx5dr_ste_get_miss_list(action_ste));
75141d07074SAlex Vesker
75217b56073SYevgeny Kliteynik ste_info_arr[k] = mlx5dr_send_info_alloc(dmn,
75317b56073SYevgeny Kliteynik nic_matcher->nic_tbl->nic_dmn->type);
75441d07074SAlex Vesker if (!ste_info_arr[k])
75541d07074SAlex Vesker goto err_exit;
75641d07074SAlex Vesker
75741d07074SAlex Vesker /* Point current ste to the new action */
7586b93b400SYevgeny Kliteynik mlx5dr_ste_set_hit_addr_by_next_htbl(dmn->ste_ctx,
7596b93b400SYevgeny Kliteynik prev_hw_ste,
7606b93b400SYevgeny Kliteynik action_ste->htbl);
7618a015baeSYevgeny Kliteynik
7628a015baeSYevgeny Kliteynik mlx5dr_rule_set_last_member(nic_rule, action_ste, true);
7638a015baeSYevgeny Kliteynik
76441d07074SAlex Vesker mlx5dr_send_fill_and_append_ste_send_info(action_ste, DR_STE_SIZE, 0,
76541d07074SAlex Vesker curr_hw_ste,
76641d07074SAlex Vesker ste_info_arr[k],
76741d07074SAlex Vesker send_ste_list, false);
76841d07074SAlex Vesker }
76941d07074SAlex Vesker
7708a015baeSYevgeny Kliteynik last_ste->next_htbl = NULL;
7718a015baeSYevgeny Kliteynik
77241d07074SAlex Vesker return 0;
77341d07074SAlex Vesker
77441d07074SAlex Vesker err_exit:
77541d07074SAlex Vesker mlx5dr_ste_put(action_ste, matcher, nic_matcher);
77641d07074SAlex Vesker return -ENOMEM;
77741d07074SAlex Vesker }
77841d07074SAlex Vesker
dr_rule_handle_empty_entry(struct mlx5dr_matcher * matcher,struct mlx5dr_matcher_rx_tx * nic_matcher,struct mlx5dr_ste_htbl * cur_htbl,struct mlx5dr_ste * ste,u8 ste_location,u8 * hw_ste,struct list_head * miss_list,struct list_head * send_list)77941d07074SAlex Vesker static int dr_rule_handle_empty_entry(struct mlx5dr_matcher *matcher,
78041d07074SAlex Vesker struct mlx5dr_matcher_rx_tx *nic_matcher,
78141d07074SAlex Vesker struct mlx5dr_ste_htbl *cur_htbl,
78241d07074SAlex Vesker struct mlx5dr_ste *ste,
78341d07074SAlex Vesker u8 ste_location,
78441d07074SAlex Vesker u8 *hw_ste,
78541d07074SAlex Vesker struct list_head *miss_list,
78641d07074SAlex Vesker struct list_head *send_list)
78741d07074SAlex Vesker {
7886b93b400SYevgeny Kliteynik struct mlx5dr_domain *dmn = matcher->tbl->dmn;
78941d07074SAlex Vesker struct mlx5dr_ste_send_info *ste_info;
79041d07074SAlex Vesker
79141d07074SAlex Vesker /* Take ref on table, only on first time this ste is used */
79241d07074SAlex Vesker mlx5dr_htbl_get(cur_htbl);
79341d07074SAlex Vesker
79441d07074SAlex Vesker /* new entry -> new branch */
79541d07074SAlex Vesker list_add_tail(&ste->miss_list_node, miss_list);
79641d07074SAlex Vesker
797f31bda78SYevgeny Kliteynik dr_rule_set_last_ste_miss_addr(matcher, nic_matcher, hw_ste);
79841d07074SAlex Vesker
79941d07074SAlex Vesker ste->ste_chain_location = ste_location;
80041d07074SAlex Vesker
80117b56073SYevgeny Kliteynik ste_info = mlx5dr_send_info_alloc(dmn,
80217b56073SYevgeny Kliteynik nic_matcher->nic_tbl->nic_dmn->type);
80341d07074SAlex Vesker if (!ste_info)
80441d07074SAlex Vesker goto clean_ste_setting;
80541d07074SAlex Vesker
80641d07074SAlex Vesker if (mlx5dr_ste_create_next_htbl(matcher,
80741d07074SAlex Vesker nic_matcher,
80841d07074SAlex Vesker ste,
80941d07074SAlex Vesker hw_ste,
81041d07074SAlex Vesker DR_CHUNK_SIZE_1)) {
8116b93b400SYevgeny Kliteynik mlx5dr_dbg(dmn, "Failed allocating table\n");
81241d07074SAlex Vesker goto clean_ste_info;
81341d07074SAlex Vesker }
81441d07074SAlex Vesker
81541d07074SAlex Vesker cur_htbl->ctrl.num_of_valid_entries++;
81641d07074SAlex Vesker
81741d07074SAlex Vesker mlx5dr_send_fill_and_append_ste_send_info(ste, DR_STE_SIZE, 0, hw_ste,
81841d07074SAlex Vesker ste_info, send_list, false);
81941d07074SAlex Vesker
82041d07074SAlex Vesker return 0;
82141d07074SAlex Vesker
82241d07074SAlex Vesker clean_ste_info:
82317b56073SYevgeny Kliteynik mlx5dr_send_info_free(ste_info);
82441d07074SAlex Vesker clean_ste_setting:
82541d07074SAlex Vesker list_del_init(&ste->miss_list_node);
82641d07074SAlex Vesker mlx5dr_htbl_put(cur_htbl);
82741d07074SAlex Vesker
82841d07074SAlex Vesker return -ENOMEM;
82941d07074SAlex Vesker }
83041d07074SAlex Vesker
83141d07074SAlex Vesker static struct mlx5dr_ste *
dr_rule_handle_ste_branch(struct mlx5dr_rule * rule,struct mlx5dr_rule_rx_tx * nic_rule,struct list_head * send_ste_list,struct mlx5dr_ste_htbl * cur_htbl,u8 * hw_ste,u8 ste_location,struct mlx5dr_ste_htbl ** put_htbl)83241d07074SAlex Vesker dr_rule_handle_ste_branch(struct mlx5dr_rule *rule,
83341d07074SAlex Vesker struct mlx5dr_rule_rx_tx *nic_rule,
83441d07074SAlex Vesker struct list_head *send_ste_list,
83541d07074SAlex Vesker struct mlx5dr_ste_htbl *cur_htbl,
83641d07074SAlex Vesker u8 *hw_ste,
83741d07074SAlex Vesker u8 ste_location,
83841d07074SAlex Vesker struct mlx5dr_ste_htbl **put_htbl)
83941d07074SAlex Vesker {
84041d07074SAlex Vesker struct mlx5dr_matcher *matcher = rule->matcher;
84141d07074SAlex Vesker struct mlx5dr_domain *dmn = matcher->tbl->dmn;
84241d07074SAlex Vesker struct mlx5dr_matcher_rx_tx *nic_matcher;
84341d07074SAlex Vesker struct mlx5dr_domain_rx_tx *nic_dmn;
84441d07074SAlex Vesker struct mlx5dr_ste_htbl *new_htbl;
84541d07074SAlex Vesker struct mlx5dr_ste *matched_ste;
84641d07074SAlex Vesker struct list_head *miss_list;
84741d07074SAlex Vesker bool skip_rehash = false;
84841d07074SAlex Vesker struct mlx5dr_ste *ste;
84941d07074SAlex Vesker int index;
85041d07074SAlex Vesker
85141d07074SAlex Vesker nic_matcher = nic_rule->nic_matcher;
85241d07074SAlex Vesker nic_dmn = nic_matcher->nic_tbl->nic_dmn;
85341d07074SAlex Vesker
85441d07074SAlex Vesker again:
85541d07074SAlex Vesker index = mlx5dr_ste_calc_hash_index(hw_ste, cur_htbl);
85641d07074SAlex Vesker miss_list = &cur_htbl->chunk->miss_list[index];
857597534bdSRongwei Liu ste = &cur_htbl->chunk->ste_arr[index];
85841d07074SAlex Vesker
85997ffd895SYevgeny Kliteynik if (mlx5dr_ste_is_not_used(ste)) {
86041d07074SAlex Vesker if (dr_rule_handle_empty_entry(matcher, nic_matcher, cur_htbl,
86141d07074SAlex Vesker ste, ste_location,
86241d07074SAlex Vesker hw_ste, miss_list,
86341d07074SAlex Vesker send_ste_list))
86441d07074SAlex Vesker return NULL;
86541d07074SAlex Vesker } else {
86641d07074SAlex Vesker /* Hash table index in use, check if this ste is in the miss list */
86741d07074SAlex Vesker matched_ste = dr_rule_find_ste_in_miss_list(miss_list, hw_ste);
86841d07074SAlex Vesker if (matched_ste) {
86941d07074SAlex Vesker /* If it is last STE in the chain, and has the same tag
87041d07074SAlex Vesker * it means that all the previous stes are the same,
87141d07074SAlex Vesker * if so, this rule is duplicated.
87241d07074SAlex Vesker */
87300414126SAlex Vesker if (!mlx5dr_ste_is_last_in_rule(nic_matcher, ste_location))
87441d07074SAlex Vesker return matched_ste;
87500414126SAlex Vesker
87600414126SAlex Vesker mlx5dr_dbg(dmn, "Duplicate rule inserted\n");
87741d07074SAlex Vesker }
87841d07074SAlex Vesker
87941d07074SAlex Vesker if (!skip_rehash && dr_rule_need_enlarge_hash(cur_htbl, dmn, nic_dmn)) {
88041d07074SAlex Vesker /* Hash table index in use, try to resize of the hash */
88141d07074SAlex Vesker skip_rehash = true;
88241d07074SAlex Vesker
88341d07074SAlex Vesker /* Hold the table till we update.
88441d07074SAlex Vesker * Release in dr_rule_create_rule()
88541d07074SAlex Vesker */
88641d07074SAlex Vesker *put_htbl = cur_htbl;
88741d07074SAlex Vesker mlx5dr_htbl_get(cur_htbl);
88841d07074SAlex Vesker
88941d07074SAlex Vesker new_htbl = dr_rule_rehash(rule, nic_rule, cur_htbl,
89041d07074SAlex Vesker ste_location, send_ste_list);
89141d07074SAlex Vesker if (!new_htbl) {
892b7d0db55SErez Shitrit mlx5dr_err(dmn, "Failed creating rehash table, htbl-log_size: %d\n",
893597534bdSRongwei Liu cur_htbl->chunk->size);
8946cc64770SWentao_Liang mlx5dr_htbl_put(cur_htbl);
89541d07074SAlex Vesker } else {
89641d07074SAlex Vesker cur_htbl = new_htbl;
89741d07074SAlex Vesker }
89841d07074SAlex Vesker goto again;
89941d07074SAlex Vesker } else {
90041d07074SAlex Vesker /* Hash table index in use, add another collision (miss) */
90141d07074SAlex Vesker ste = dr_rule_handle_collision(matcher,
90241d07074SAlex Vesker nic_matcher,
90341d07074SAlex Vesker ste,
90441d07074SAlex Vesker hw_ste,
90541d07074SAlex Vesker miss_list,
90641d07074SAlex Vesker send_ste_list);
90741d07074SAlex Vesker if (!ste) {
90841d07074SAlex Vesker mlx5dr_dbg(dmn, "failed adding collision entry, index: %d\n",
90941d07074SAlex Vesker index);
91041d07074SAlex Vesker return NULL;
91141d07074SAlex Vesker }
91241d07074SAlex Vesker }
91341d07074SAlex Vesker }
91441d07074SAlex Vesker return ste;
91541d07074SAlex Vesker }
91641d07074SAlex Vesker
dr_rule_cmp_value_to_mask(u8 * mask,u8 * value,u32 s_idx,u32 e_idx)91741d07074SAlex Vesker static bool dr_rule_cmp_value_to_mask(u8 *mask, u8 *value,
91841d07074SAlex Vesker u32 s_idx, u32 e_idx)
91941d07074SAlex Vesker {
92041d07074SAlex Vesker u32 i;
92141d07074SAlex Vesker
92241d07074SAlex Vesker for (i = s_idx; i < e_idx; i++) {
92341d07074SAlex Vesker if (value[i] & ~mask[i]) {
92441d07074SAlex Vesker pr_info("Rule parameters contains a value not specified by mask\n");
92541d07074SAlex Vesker return false;
92641d07074SAlex Vesker }
92741d07074SAlex Vesker }
92841d07074SAlex Vesker return true;
92941d07074SAlex Vesker }
93041d07074SAlex Vesker
dr_rule_verify(struct mlx5dr_matcher * matcher,struct mlx5dr_match_parameters * value,struct mlx5dr_match_param * param)93141d07074SAlex Vesker static bool dr_rule_verify(struct mlx5dr_matcher *matcher,
93241d07074SAlex Vesker struct mlx5dr_match_parameters *value,
93341d07074SAlex Vesker struct mlx5dr_match_param *param)
93441d07074SAlex Vesker {
93541d07074SAlex Vesker u8 match_criteria = matcher->match_criteria;
93641d07074SAlex Vesker size_t value_size = value->match_sz;
93741d07074SAlex Vesker u8 *mask_p = (u8 *)&matcher->mask;
93841d07074SAlex Vesker u8 *param_p = (u8 *)param;
93941d07074SAlex Vesker u32 s_idx, e_idx;
94041d07074SAlex Vesker
94141d07074SAlex Vesker if (!value_size ||
942699d531fSMuhammad Sammar (value_size > DR_SZ_MATCH_PARAM || (value_size % sizeof(u32)))) {
943b7d0db55SErez Shitrit mlx5dr_err(matcher->tbl->dmn, "Rule parameters length is incorrect\n");
94441d07074SAlex Vesker return false;
94541d07074SAlex Vesker }
94641d07074SAlex Vesker
947941f1979SMuhammad Sammar mlx5dr_ste_copy_param(matcher->match_criteria, param, value, false);
94841d07074SAlex Vesker
94941d07074SAlex Vesker if (match_criteria & DR_MATCHER_CRITERIA_OUTER) {
95041d07074SAlex Vesker s_idx = offsetof(struct mlx5dr_match_param, outer);
95141d07074SAlex Vesker e_idx = min(s_idx + sizeof(param->outer), value_size);
95241d07074SAlex Vesker
95341d07074SAlex Vesker if (!dr_rule_cmp_value_to_mask(mask_p, param_p, s_idx, e_idx)) {
954b7d0db55SErez Shitrit mlx5dr_err(matcher->tbl->dmn, "Rule outer parameters contains a value not specified by mask\n");
95541d07074SAlex Vesker return false;
95641d07074SAlex Vesker }
95741d07074SAlex Vesker }
95841d07074SAlex Vesker
95941d07074SAlex Vesker if (match_criteria & DR_MATCHER_CRITERIA_MISC) {
96041d07074SAlex Vesker s_idx = offsetof(struct mlx5dr_match_param, misc);
96141d07074SAlex Vesker e_idx = min(s_idx + sizeof(param->misc), value_size);
96241d07074SAlex Vesker
96341d07074SAlex Vesker if (!dr_rule_cmp_value_to_mask(mask_p, param_p, s_idx, e_idx)) {
964b7d0db55SErez Shitrit mlx5dr_err(matcher->tbl->dmn, "Rule misc parameters contains a value not specified by mask\n");
96541d07074SAlex Vesker return false;
96641d07074SAlex Vesker }
96741d07074SAlex Vesker }
96841d07074SAlex Vesker
96941d07074SAlex Vesker if (match_criteria & DR_MATCHER_CRITERIA_INNER) {
97041d07074SAlex Vesker s_idx = offsetof(struct mlx5dr_match_param, inner);
97141d07074SAlex Vesker e_idx = min(s_idx + sizeof(param->inner), value_size);
97241d07074SAlex Vesker
97341d07074SAlex Vesker if (!dr_rule_cmp_value_to_mask(mask_p, param_p, s_idx, e_idx)) {
974b7d0db55SErez Shitrit mlx5dr_err(matcher->tbl->dmn, "Rule inner parameters contains a value not specified by mask\n");
97541d07074SAlex Vesker return false;
97641d07074SAlex Vesker }
97741d07074SAlex Vesker }
97841d07074SAlex Vesker
97941d07074SAlex Vesker if (match_criteria & DR_MATCHER_CRITERIA_MISC2) {
98041d07074SAlex Vesker s_idx = offsetof(struct mlx5dr_match_param, misc2);
98141d07074SAlex Vesker e_idx = min(s_idx + sizeof(param->misc2), value_size);
98241d07074SAlex Vesker
98341d07074SAlex Vesker if (!dr_rule_cmp_value_to_mask(mask_p, param_p, s_idx, e_idx)) {
984b7d0db55SErez Shitrit mlx5dr_err(matcher->tbl->dmn, "Rule misc2 parameters contains a value not specified by mask\n");
98541d07074SAlex Vesker return false;
98641d07074SAlex Vesker }
98741d07074SAlex Vesker }
98841d07074SAlex Vesker
98941d07074SAlex Vesker if (match_criteria & DR_MATCHER_CRITERIA_MISC3) {
99041d07074SAlex Vesker s_idx = offsetof(struct mlx5dr_match_param, misc3);
99141d07074SAlex Vesker e_idx = min(s_idx + sizeof(param->misc3), value_size);
99241d07074SAlex Vesker
99341d07074SAlex Vesker if (!dr_rule_cmp_value_to_mask(mask_p, param_p, s_idx, e_idx)) {
994b7d0db55SErez Shitrit mlx5dr_err(matcher->tbl->dmn, "Rule misc3 parameters contains a value not specified by mask\n");
99541d07074SAlex Vesker return false;
99641d07074SAlex Vesker }
99741d07074SAlex Vesker }
998160e9cb3SYevgeny Kliteynik
999160e9cb3SYevgeny Kliteynik if (match_criteria & DR_MATCHER_CRITERIA_MISC4) {
1000160e9cb3SYevgeny Kliteynik s_idx = offsetof(struct mlx5dr_match_param, misc4);
1001160e9cb3SYevgeny Kliteynik e_idx = min(s_idx + sizeof(param->misc4), value_size);
1002160e9cb3SYevgeny Kliteynik
1003160e9cb3SYevgeny Kliteynik if (!dr_rule_cmp_value_to_mask(mask_p, param_p, s_idx, e_idx)) {
1004160e9cb3SYevgeny Kliteynik mlx5dr_err(matcher->tbl->dmn,
1005160e9cb3SYevgeny Kliteynik "Rule misc4 parameters contains a value not specified by mask\n");
1006160e9cb3SYevgeny Kliteynik return false;
1007160e9cb3SYevgeny Kliteynik }
1008160e9cb3SYevgeny Kliteynik }
10098c2b4feeSMuhammad Sammar
10108c2b4feeSMuhammad Sammar if (match_criteria & DR_MATCHER_CRITERIA_MISC5) {
10118c2b4feeSMuhammad Sammar s_idx = offsetof(struct mlx5dr_match_param, misc5);
10128c2b4feeSMuhammad Sammar e_idx = min(s_idx + sizeof(param->misc5), value_size);
10138c2b4feeSMuhammad Sammar
10148c2b4feeSMuhammad Sammar if (!dr_rule_cmp_value_to_mask(mask_p, param_p, s_idx, e_idx)) {
10158c2b4feeSMuhammad Sammar mlx5dr_err(matcher->tbl->dmn, "Rule misc5 parameters contains a value not specified by mask\n");
10168c2b4feeSMuhammad Sammar return false;
10178c2b4feeSMuhammad Sammar }
10188c2b4feeSMuhammad Sammar }
101941d07074SAlex Vesker return true;
102041d07074SAlex Vesker }
102141d07074SAlex Vesker
dr_rule_destroy_rule_nic(struct mlx5dr_rule * rule,struct mlx5dr_rule_rx_tx * nic_rule)102241d07074SAlex Vesker static int dr_rule_destroy_rule_nic(struct mlx5dr_rule *rule,
102341d07074SAlex Vesker struct mlx5dr_rule_rx_tx *nic_rule)
102441d07074SAlex Vesker {
1025cc2295cdSYevgeny Kliteynik /* Check if this nic rule was actually created, or was it skipped
1026cc2295cdSYevgeny Kliteynik * and only the other type of the RX/TX nic rule was created.
1027cc2295cdSYevgeny Kliteynik */
1028cc2295cdSYevgeny Kliteynik if (!nic_rule->last_rule_ste)
1029cc2295cdSYevgeny Kliteynik return 0;
1030cc2295cdSYevgeny Kliteynik
1031ed03a418SAlex Vesker mlx5dr_domain_nic_lock(nic_rule->nic_matcher->nic_tbl->nic_dmn);
103241d07074SAlex Vesker dr_rule_clean_rule_members(rule, nic_rule);
1033cc2295cdSYevgeny Kliteynik
1034cc2295cdSYevgeny Kliteynik nic_rule->nic_matcher->rules--;
1035cc2295cdSYevgeny Kliteynik if (!nic_rule->nic_matcher->rules)
1036cc2295cdSYevgeny Kliteynik mlx5dr_matcher_remove_from_tbl_nic(rule->matcher->tbl->dmn,
1037cc2295cdSYevgeny Kliteynik nic_rule->nic_matcher);
1038cc2295cdSYevgeny Kliteynik
1039ed03a418SAlex Vesker mlx5dr_domain_nic_unlock(nic_rule->nic_matcher->nic_tbl->nic_dmn);
1040ed03a418SAlex Vesker
104141d07074SAlex Vesker return 0;
104241d07074SAlex Vesker }
104341d07074SAlex Vesker
dr_rule_destroy_rule_fdb(struct mlx5dr_rule * rule)104441d07074SAlex Vesker static int dr_rule_destroy_rule_fdb(struct mlx5dr_rule *rule)
104541d07074SAlex Vesker {
104641d07074SAlex Vesker dr_rule_destroy_rule_nic(rule, &rule->rx);
104741d07074SAlex Vesker dr_rule_destroy_rule_nic(rule, &rule->tx);
104841d07074SAlex Vesker return 0;
104941d07074SAlex Vesker }
105041d07074SAlex Vesker
dr_rule_destroy_rule(struct mlx5dr_rule * rule)105141d07074SAlex Vesker static int dr_rule_destroy_rule(struct mlx5dr_rule *rule)
105241d07074SAlex Vesker {
105341d07074SAlex Vesker struct mlx5dr_domain *dmn = rule->matcher->tbl->dmn;
105441d07074SAlex Vesker
10559222f0b2SMuhammad Sammar mlx5dr_dbg_rule_del(rule);
10569222f0b2SMuhammad Sammar
105741d07074SAlex Vesker switch (dmn->type) {
105841d07074SAlex Vesker case MLX5DR_DOMAIN_TYPE_NIC_RX:
105941d07074SAlex Vesker dr_rule_destroy_rule_nic(rule, &rule->rx);
106041d07074SAlex Vesker break;
106141d07074SAlex Vesker case MLX5DR_DOMAIN_TYPE_NIC_TX:
106241d07074SAlex Vesker dr_rule_destroy_rule_nic(rule, &rule->tx);
106341d07074SAlex Vesker break;
106441d07074SAlex Vesker case MLX5DR_DOMAIN_TYPE_FDB:
106541d07074SAlex Vesker dr_rule_destroy_rule_fdb(rule);
106641d07074SAlex Vesker break;
106741d07074SAlex Vesker default:
106841d07074SAlex Vesker return -EINVAL;
106941d07074SAlex Vesker }
107041d07074SAlex Vesker
107141d07074SAlex Vesker dr_rule_remove_action_members(rule);
107241d07074SAlex Vesker kfree(rule);
107341d07074SAlex Vesker return 0;
107441d07074SAlex Vesker }
107541d07074SAlex Vesker
dr_rule_get_ipv(struct mlx5dr_match_spec * spec)1076667f2646SAlex Vesker static enum mlx5dr_ipv dr_rule_get_ipv(struct mlx5dr_match_spec *spec)
107741d07074SAlex Vesker {
1078667f2646SAlex Vesker if (spec->ip_version == 6 || spec->ethertype == ETH_P_IPV6)
1079667f2646SAlex Vesker return DR_RULE_IPV6;
1080667f2646SAlex Vesker
1081667f2646SAlex Vesker return DR_RULE_IPV4;
108241d07074SAlex Vesker }
108341d07074SAlex Vesker
dr_rule_skip(enum mlx5dr_domain_type domain,enum mlx5dr_domain_nic_type nic_type,struct mlx5dr_match_param * mask,struct mlx5dr_match_param * value,u32 flow_source)108441d07074SAlex Vesker static bool dr_rule_skip(enum mlx5dr_domain_type domain,
108546f2a8aeSYevgeny Kliteynik enum mlx5dr_domain_nic_type nic_type,
108641d07074SAlex Vesker struct mlx5dr_match_param *mask,
108701723919SHamdan Igbaria struct mlx5dr_match_param *value,
108801723919SHamdan Igbaria u32 flow_source)
108941d07074SAlex Vesker {
109046f2a8aeSYevgeny Kliteynik bool rx = nic_type == DR_DOMAIN_NIC_TYPE_RX;
109101723919SHamdan Igbaria
109241d07074SAlex Vesker if (domain != MLX5DR_DOMAIN_TYPE_FDB)
109341d07074SAlex Vesker return false;
109441d07074SAlex Vesker
109541d07074SAlex Vesker if (mask->misc.source_port) {
10967ae8ac9aSYevgeny Kliteynik if (rx && value->misc.source_port != MLX5_VPORT_UPLINK)
109741d07074SAlex Vesker return true;
109841d07074SAlex Vesker
10997ae8ac9aSYevgeny Kliteynik if (!rx && value->misc.source_port == MLX5_VPORT_UPLINK)
110041d07074SAlex Vesker return true;
110141d07074SAlex Vesker }
110241d07074SAlex Vesker
110301723919SHamdan Igbaria if (rx && flow_source == MLX5_FLOW_CONTEXT_FLOW_SOURCE_LOCAL_VPORT)
110441d07074SAlex Vesker return true;
110541d07074SAlex Vesker
110601723919SHamdan Igbaria if (!rx && flow_source == MLX5_FLOW_CONTEXT_FLOW_SOURCE_UPLINK)
110741d07074SAlex Vesker return true;
110801723919SHamdan Igbaria
110941d07074SAlex Vesker return false;
111041d07074SAlex Vesker }
111141d07074SAlex Vesker
111241d07074SAlex Vesker static int
dr_rule_create_rule_nic(struct mlx5dr_rule * rule,struct mlx5dr_rule_rx_tx * nic_rule,struct mlx5dr_match_param * param,size_t num_actions,struct mlx5dr_action * actions[])111341d07074SAlex Vesker dr_rule_create_rule_nic(struct mlx5dr_rule *rule,
111441d07074SAlex Vesker struct mlx5dr_rule_rx_tx *nic_rule,
111541d07074SAlex Vesker struct mlx5dr_match_param *param,
111641d07074SAlex Vesker size_t num_actions,
111741d07074SAlex Vesker struct mlx5dr_action *actions[])
111841d07074SAlex Vesker {
1119b9b81e1eSYevgeny Kliteynik u8 hw_ste_arr_optimized[DR_RULE_MAX_STE_CHAIN_OPTIMIZED * DR_STE_SIZE] = {};
112041d07074SAlex Vesker struct mlx5dr_ste_send_info *ste_info, *tmp_ste_info;
112141d07074SAlex Vesker struct mlx5dr_matcher *matcher = rule->matcher;
112241d07074SAlex Vesker struct mlx5dr_domain *dmn = matcher->tbl->dmn;
112341d07074SAlex Vesker struct mlx5dr_matcher_rx_tx *nic_matcher;
112441d07074SAlex Vesker struct mlx5dr_domain_rx_tx *nic_dmn;
112541d07074SAlex Vesker struct mlx5dr_ste_htbl *htbl = NULL;
112641d07074SAlex Vesker struct mlx5dr_ste_htbl *cur_htbl;
112741d07074SAlex Vesker struct mlx5dr_ste *ste = NULL;
112841d07074SAlex Vesker LIST_HEAD(send_ste_list);
1129b9b81e1eSYevgeny Kliteynik bool hw_ste_arr_is_opt;
113041d07074SAlex Vesker u8 *hw_ste_arr = NULL;
113141d07074SAlex Vesker u32 new_hw_ste_arr_sz;
113241d07074SAlex Vesker int ret, i;
113341d07074SAlex Vesker
113441d07074SAlex Vesker nic_matcher = nic_rule->nic_matcher;
113541d07074SAlex Vesker nic_dmn = nic_matcher->nic_tbl->nic_dmn;
113641d07074SAlex Vesker
113746f2a8aeSYevgeny Kliteynik if (dr_rule_skip(dmn->type, nic_dmn->type, &matcher->mask, param,
113801723919SHamdan Igbaria rule->flow_source))
113941d07074SAlex Vesker return 0;
114041d07074SAlex Vesker
1141*288d85e0SYevgeny Kliteynik mlx5dr_domain_nic_lock(nic_dmn);
1142*288d85e0SYevgeny Kliteynik
1143b9b81e1eSYevgeny Kliteynik ret = mlx5dr_matcher_select_builders(matcher,
1144b9b81e1eSYevgeny Kliteynik nic_matcher,
1145b9b81e1eSYevgeny Kliteynik dr_rule_get_ipv(¶m->outer),
1146b9b81e1eSYevgeny Kliteynik dr_rule_get_ipv(¶m->inner));
1147b9b81e1eSYevgeny Kliteynik if (ret)
1148*288d85e0SYevgeny Kliteynik goto err_unlock;
1149b9b81e1eSYevgeny Kliteynik
1150b9b81e1eSYevgeny Kliteynik hw_ste_arr_is_opt = nic_matcher->num_of_builders <= DR_RULE_MAX_STES_OPTIMIZED;
1151b9b81e1eSYevgeny Kliteynik if (likely(hw_ste_arr_is_opt)) {
1152b9b81e1eSYevgeny Kliteynik hw_ste_arr = hw_ste_arr_optimized;
1153b9b81e1eSYevgeny Kliteynik } else {
1154b9b81e1eSYevgeny Kliteynik hw_ste_arr = kzalloc((nic_matcher->num_of_builders + DR_ACTION_MAX_STES) *
1155b9b81e1eSYevgeny Kliteynik DR_STE_SIZE, GFP_KERNEL);
1156b9b81e1eSYevgeny Kliteynik
1157*288d85e0SYevgeny Kliteynik if (!hw_ste_arr) {
1158*288d85e0SYevgeny Kliteynik ret = -ENOMEM;
1159*288d85e0SYevgeny Kliteynik goto err_unlock;
1160b9b81e1eSYevgeny Kliteynik }
1161*288d85e0SYevgeny Kliteynik }
1162ed03a418SAlex Vesker
1163cc2295cdSYevgeny Kliteynik ret = mlx5dr_matcher_add_to_tbl_nic(dmn, nic_matcher);
1164cc2295cdSYevgeny Kliteynik if (ret)
1165cc2295cdSYevgeny Kliteynik goto free_hw_ste;
1166cc2295cdSYevgeny Kliteynik
116741d07074SAlex Vesker /* Set the tag values inside the ste array */
116841d07074SAlex Vesker ret = mlx5dr_ste_build_ste_arr(matcher, nic_matcher, param, hw_ste_arr);
116941d07074SAlex Vesker if (ret)
1170cc2295cdSYevgeny Kliteynik goto remove_from_nic_tbl;
117141d07074SAlex Vesker
117241d07074SAlex Vesker /* Set the actions values/addresses inside the ste array */
117341d07074SAlex Vesker ret = mlx5dr_actions_build_ste_arr(matcher, nic_matcher, actions,
117441d07074SAlex Vesker num_actions, hw_ste_arr,
117541d07074SAlex Vesker &new_hw_ste_arr_sz);
117641d07074SAlex Vesker if (ret)
1177cc2295cdSYevgeny Kliteynik goto remove_from_nic_tbl;
117841d07074SAlex Vesker
117941d07074SAlex Vesker cur_htbl = nic_matcher->s_htbl;
118041d07074SAlex Vesker
118141d07074SAlex Vesker /* Go over the array of STEs, and build dr_ste accordingly.
118241d07074SAlex Vesker * The loop is over only the builders which are equal or less to the
118341d07074SAlex Vesker * number of stes, in case we have actions that lives in other stes.
118441d07074SAlex Vesker */
118541d07074SAlex Vesker for (i = 0; i < nic_matcher->num_of_builders; i++) {
118641d07074SAlex Vesker /* Calculate CRC and keep new ste entry */
118741d07074SAlex Vesker u8 *cur_hw_ste_ent = hw_ste_arr + (i * DR_STE_SIZE);
118841d07074SAlex Vesker
118941d07074SAlex Vesker ste = dr_rule_handle_ste_branch(rule,
119041d07074SAlex Vesker nic_rule,
119141d07074SAlex Vesker &send_ste_list,
119241d07074SAlex Vesker cur_htbl,
119341d07074SAlex Vesker cur_hw_ste_ent,
119441d07074SAlex Vesker i + 1,
119541d07074SAlex Vesker &htbl);
119641d07074SAlex Vesker if (!ste) {
119741d07074SAlex Vesker mlx5dr_err(dmn, "Failed creating next branch\n");
119841d07074SAlex Vesker ret = -ENOENT;
119941d07074SAlex Vesker goto free_rule;
120041d07074SAlex Vesker }
120141d07074SAlex Vesker
120241d07074SAlex Vesker cur_htbl = ste->next_htbl;
120341d07074SAlex Vesker
120441d07074SAlex Vesker mlx5dr_ste_get(ste);
12058a015baeSYevgeny Kliteynik mlx5dr_rule_set_last_member(nic_rule, ste, true);
120641d07074SAlex Vesker }
120741d07074SAlex Vesker
120841d07074SAlex Vesker /* Connect actions */
120941d07074SAlex Vesker ret = dr_rule_handle_action_stes(rule, nic_rule, &send_ste_list,
121041d07074SAlex Vesker ste, hw_ste_arr, new_hw_ste_arr_sz);
121141d07074SAlex Vesker if (ret) {
121241d07074SAlex Vesker mlx5dr_dbg(dmn, "Failed apply actions\n");
121341d07074SAlex Vesker goto free_rule;
121441d07074SAlex Vesker }
121541d07074SAlex Vesker ret = dr_rule_send_update_list(&send_ste_list, dmn, true);
121641d07074SAlex Vesker if (ret) {
121741d07074SAlex Vesker mlx5dr_err(dmn, "Failed sending ste!\n");
121841d07074SAlex Vesker goto free_rule;
121941d07074SAlex Vesker }
122041d07074SAlex Vesker
122141d07074SAlex Vesker if (htbl)
122241d07074SAlex Vesker mlx5dr_htbl_put(htbl);
122341d07074SAlex Vesker
1224cc2295cdSYevgeny Kliteynik nic_matcher->rules++;
1225cc2295cdSYevgeny Kliteynik
1226ed03a418SAlex Vesker mlx5dr_domain_nic_unlock(nic_dmn);
1227ed03a418SAlex Vesker
1228*288d85e0SYevgeny Kliteynik if (unlikely(!hw_ste_arr_is_opt))
1229*288d85e0SYevgeny Kliteynik kfree(hw_ste_arr);
1230*288d85e0SYevgeny Kliteynik
1231*288d85e0SYevgeny Kliteynik return 0;
123241d07074SAlex Vesker
123341d07074SAlex Vesker free_rule:
123441d07074SAlex Vesker dr_rule_clean_rule_members(rule, nic_rule);
123541d07074SAlex Vesker /* Clean all ste_info's */
123641d07074SAlex Vesker list_for_each_entry_safe(ste_info, tmp_ste_info, &send_ste_list, send_list) {
123741d07074SAlex Vesker list_del(&ste_info->send_list);
123817b56073SYevgeny Kliteynik mlx5dr_send_info_free(ste_info);
123941d07074SAlex Vesker }
1240cc2295cdSYevgeny Kliteynik
1241cc2295cdSYevgeny Kliteynik remove_from_nic_tbl:
12424ea9891dSRongwei Liu if (!nic_matcher->rules)
1243cc2295cdSYevgeny Kliteynik mlx5dr_matcher_remove_from_tbl_nic(dmn, nic_matcher);
1244cc2295cdSYevgeny Kliteynik
124541d07074SAlex Vesker free_hw_ste:
1246*288d85e0SYevgeny Kliteynik if (!hw_ste_arr_is_opt)
124741d07074SAlex Vesker kfree(hw_ste_arr);
1248b9b81e1eSYevgeny Kliteynik
1249*288d85e0SYevgeny Kliteynik err_unlock:
1250*288d85e0SYevgeny Kliteynik mlx5dr_domain_nic_unlock(nic_dmn);
1251*288d85e0SYevgeny Kliteynik
125241d07074SAlex Vesker return ret;
125341d07074SAlex Vesker }
125441d07074SAlex Vesker
125541d07074SAlex Vesker static int
dr_rule_create_rule_fdb(struct mlx5dr_rule * rule,struct mlx5dr_match_param * param,size_t num_actions,struct mlx5dr_action * actions[])125641d07074SAlex Vesker dr_rule_create_rule_fdb(struct mlx5dr_rule *rule,
125741d07074SAlex Vesker struct mlx5dr_match_param *param,
125841d07074SAlex Vesker size_t num_actions,
125941d07074SAlex Vesker struct mlx5dr_action *actions[])
126041d07074SAlex Vesker {
126141d07074SAlex Vesker struct mlx5dr_match_param copy_param = {};
126241d07074SAlex Vesker int ret;
126341d07074SAlex Vesker
126441d07074SAlex Vesker /* Copy match_param since they will be consumed during the first
126541d07074SAlex Vesker * nic_rule insertion.
126641d07074SAlex Vesker */
126741d07074SAlex Vesker memcpy(©_param, param, sizeof(struct mlx5dr_match_param));
126841d07074SAlex Vesker
126941d07074SAlex Vesker ret = dr_rule_create_rule_nic(rule, &rule->rx, param,
127041d07074SAlex Vesker num_actions, actions);
127141d07074SAlex Vesker if (ret)
127241d07074SAlex Vesker return ret;
127341d07074SAlex Vesker
127441d07074SAlex Vesker ret = dr_rule_create_rule_nic(rule, &rule->tx, ©_param,
127541d07074SAlex Vesker num_actions, actions);
127641d07074SAlex Vesker if (ret)
127741d07074SAlex Vesker goto destroy_rule_nic_rx;
127841d07074SAlex Vesker
127941d07074SAlex Vesker return 0;
128041d07074SAlex Vesker
128141d07074SAlex Vesker destroy_rule_nic_rx:
128241d07074SAlex Vesker dr_rule_destroy_rule_nic(rule, &rule->rx);
128341d07074SAlex Vesker return ret;
128441d07074SAlex Vesker }
128541d07074SAlex Vesker
128641d07074SAlex Vesker static struct mlx5dr_rule *
dr_rule_create_rule(struct mlx5dr_matcher * matcher,struct mlx5dr_match_parameters * value,size_t num_actions,struct mlx5dr_action * actions[],u32 flow_source)128741d07074SAlex Vesker dr_rule_create_rule(struct mlx5dr_matcher *matcher,
128841d07074SAlex Vesker struct mlx5dr_match_parameters *value,
128941d07074SAlex Vesker size_t num_actions,
129001723919SHamdan Igbaria struct mlx5dr_action *actions[],
129101723919SHamdan Igbaria u32 flow_source)
129241d07074SAlex Vesker {
129341d07074SAlex Vesker struct mlx5dr_domain *dmn = matcher->tbl->dmn;
129441d07074SAlex Vesker struct mlx5dr_match_param param = {};
129541d07074SAlex Vesker struct mlx5dr_rule *rule;
129641d07074SAlex Vesker int ret;
129741d07074SAlex Vesker
129841d07074SAlex Vesker if (!dr_rule_verify(matcher, value, ¶m))
129941d07074SAlex Vesker return NULL;
130041d07074SAlex Vesker
130141d07074SAlex Vesker rule = kzalloc(sizeof(*rule), GFP_KERNEL);
130241d07074SAlex Vesker if (!rule)
130341d07074SAlex Vesker return NULL;
130441d07074SAlex Vesker
130541d07074SAlex Vesker rule->matcher = matcher;
130601723919SHamdan Igbaria rule->flow_source = flow_source;
130741d07074SAlex Vesker INIT_LIST_HEAD(&rule->rule_actions_list);
130841d07074SAlex Vesker
130941d07074SAlex Vesker ret = dr_rule_add_action_members(rule, num_actions, actions);
131041d07074SAlex Vesker if (ret)
131141d07074SAlex Vesker goto free_rule;
131241d07074SAlex Vesker
131341d07074SAlex Vesker switch (dmn->type) {
131441d07074SAlex Vesker case MLX5DR_DOMAIN_TYPE_NIC_RX:
131541d07074SAlex Vesker rule->rx.nic_matcher = &matcher->rx;
131641d07074SAlex Vesker ret = dr_rule_create_rule_nic(rule, &rule->rx, ¶m,
131741d07074SAlex Vesker num_actions, actions);
131841d07074SAlex Vesker break;
131941d07074SAlex Vesker case MLX5DR_DOMAIN_TYPE_NIC_TX:
132041d07074SAlex Vesker rule->tx.nic_matcher = &matcher->tx;
132141d07074SAlex Vesker ret = dr_rule_create_rule_nic(rule, &rule->tx, ¶m,
132241d07074SAlex Vesker num_actions, actions);
132341d07074SAlex Vesker break;
132441d07074SAlex Vesker case MLX5DR_DOMAIN_TYPE_FDB:
132541d07074SAlex Vesker rule->rx.nic_matcher = &matcher->rx;
132641d07074SAlex Vesker rule->tx.nic_matcher = &matcher->tx;
132741d07074SAlex Vesker ret = dr_rule_create_rule_fdb(rule, ¶m,
132841d07074SAlex Vesker num_actions, actions);
132941d07074SAlex Vesker break;
133041d07074SAlex Vesker default:
133141d07074SAlex Vesker ret = -EINVAL;
133241d07074SAlex Vesker break;
133341d07074SAlex Vesker }
133441d07074SAlex Vesker
133541d07074SAlex Vesker if (ret)
133641d07074SAlex Vesker goto remove_action_members;
133741d07074SAlex Vesker
13389222f0b2SMuhammad Sammar INIT_LIST_HEAD(&rule->dbg_node);
13399222f0b2SMuhammad Sammar mlx5dr_dbg_rule_add(rule);
134041d07074SAlex Vesker return rule;
134141d07074SAlex Vesker
134241d07074SAlex Vesker remove_action_members:
134341d07074SAlex Vesker dr_rule_remove_action_members(rule);
134441d07074SAlex Vesker free_rule:
134541d07074SAlex Vesker kfree(rule);
1346b7d0db55SErez Shitrit mlx5dr_err(dmn, "Failed creating rule\n");
134741d07074SAlex Vesker return NULL;
134841d07074SAlex Vesker }
134941d07074SAlex Vesker
mlx5dr_rule_create(struct mlx5dr_matcher * matcher,struct mlx5dr_match_parameters * value,size_t num_actions,struct mlx5dr_action * actions[],u32 flow_source)135041d07074SAlex Vesker struct mlx5dr_rule *mlx5dr_rule_create(struct mlx5dr_matcher *matcher,
135141d07074SAlex Vesker struct mlx5dr_match_parameters *value,
135241d07074SAlex Vesker size_t num_actions,
135301723919SHamdan Igbaria struct mlx5dr_action *actions[],
135401723919SHamdan Igbaria u32 flow_source)
135541d07074SAlex Vesker {
135641d07074SAlex Vesker struct mlx5dr_rule *rule;
135741d07074SAlex Vesker
135841d07074SAlex Vesker refcount_inc(&matcher->refcount);
135941d07074SAlex Vesker
136001723919SHamdan Igbaria rule = dr_rule_create_rule(matcher, value, num_actions, actions, flow_source);
136141d07074SAlex Vesker if (!rule)
136241d07074SAlex Vesker refcount_dec(&matcher->refcount);
136341d07074SAlex Vesker
136441d07074SAlex Vesker return rule;
136541d07074SAlex Vesker }
136641d07074SAlex Vesker
mlx5dr_rule_destroy(struct mlx5dr_rule * rule)136741d07074SAlex Vesker int mlx5dr_rule_destroy(struct mlx5dr_rule *rule)
136841d07074SAlex Vesker {
136941d07074SAlex Vesker struct mlx5dr_matcher *matcher = rule->matcher;
137041d07074SAlex Vesker int ret;
137141d07074SAlex Vesker
137241d07074SAlex Vesker ret = dr_rule_destroy_rule(rule);
137341d07074SAlex Vesker if (!ret)
137441d07074SAlex Vesker refcount_dec(&matcher->refcount);
1375ed03a418SAlex Vesker
137641d07074SAlex Vesker return ret;
137741d07074SAlex Vesker }
1378