1c47ff7baSAlex Vesker // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2c47ff7baSAlex Vesker /* Copyright (c) 2019 Mellanox Technologies. */
3c47ff7baSAlex Vesker 
4c47ff7baSAlex Vesker #include <linux/types.h>
5c47ff7baSAlex Vesker #include "dr_types.h"
6c47ff7baSAlex Vesker 
7c47ff7baSAlex Vesker struct mlx5dr_fw_recalc_cs_ft *
mlx5dr_fw_create_recalc_cs_ft(struct mlx5dr_domain * dmn,u16 vport_num)8f9f93bd5SYevgeny Kliteynik mlx5dr_fw_create_recalc_cs_ft(struct mlx5dr_domain *dmn, u16 vport_num)
9c47ff7baSAlex Vesker {
10cc78dbd7SAlex Vesker 	struct mlx5dr_cmd_create_flow_table_attr ft_attr = {};
11c47ff7baSAlex Vesker 	struct mlx5dr_fw_recalc_cs_ft *recalc_cs_ft;
12c47ff7baSAlex Vesker 	u32 table_id, group_id, modify_hdr_id;
13c47ff7baSAlex Vesker 	u64 rx_icm_addr, modify_ttl_action;
14c47ff7baSAlex Vesker 	int ret;
15c47ff7baSAlex Vesker 
16c47ff7baSAlex Vesker 	recalc_cs_ft = kzalloc(sizeof(*recalc_cs_ft), GFP_KERNEL);
17c47ff7baSAlex Vesker 	if (!recalc_cs_ft)
18c47ff7baSAlex Vesker 		return NULL;
19c47ff7baSAlex Vesker 
20cc78dbd7SAlex Vesker 	ft_attr.table_type = MLX5_FLOW_TABLE_TYPE_FDB;
21cc78dbd7SAlex Vesker 	ft_attr.level = dmn->info.caps.max_ft_level - 1;
22cc78dbd7SAlex Vesker 	ft_attr.term_tbl = true;
23cc78dbd7SAlex Vesker 
24cc78dbd7SAlex Vesker 	ret = mlx5dr_cmd_create_flow_table(dmn->mdev,
25cc78dbd7SAlex Vesker 					   &ft_attr,
26cc78dbd7SAlex Vesker 					   &rx_icm_addr,
27cc78dbd7SAlex Vesker 					   &table_id);
28c47ff7baSAlex Vesker 	if (ret) {
29c47ff7baSAlex Vesker 		mlx5dr_err(dmn, "Failed creating TTL W/A FW flow table %d\n", ret);
30c47ff7baSAlex Vesker 		goto free_ttl_tbl;
31c47ff7baSAlex Vesker 	}
32c47ff7baSAlex Vesker 
33c47ff7baSAlex Vesker 	ret = mlx5dr_cmd_create_empty_flow_group(dmn->mdev,
34c47ff7baSAlex Vesker 						 MLX5_FLOW_TABLE_TYPE_FDB,
35c47ff7baSAlex Vesker 						 table_id, &group_id);
36c47ff7baSAlex Vesker 	if (ret) {
37c47ff7baSAlex Vesker 		mlx5dr_err(dmn, "Failed creating TTL W/A FW flow group %d\n", ret);
38c47ff7baSAlex Vesker 		goto destroy_flow_table;
39c47ff7baSAlex Vesker 	}
40c47ff7baSAlex Vesker 
41c47ff7baSAlex Vesker 	/* Modify TTL action by adding zero to trigger CS recalculation */
42c47ff7baSAlex Vesker 	modify_ttl_action = 0;
43c47ff7baSAlex Vesker 	MLX5_SET(set_action_in, &modify_ttl_action, action_type, MLX5_ACTION_TYPE_ADD);
44c47ff7baSAlex Vesker 	MLX5_SET(set_action_in, &modify_ttl_action, field, MLX5_ACTION_IN_FIELD_OUT_IP_TTL);
45c47ff7baSAlex Vesker 
46c47ff7baSAlex Vesker 	ret = mlx5dr_cmd_alloc_modify_header(dmn->mdev, MLX5_FLOW_TABLE_TYPE_FDB, 1,
47c47ff7baSAlex Vesker 					     &modify_ttl_action,
48c47ff7baSAlex Vesker 					     &modify_hdr_id);
49c47ff7baSAlex Vesker 	if (ret) {
50c47ff7baSAlex Vesker 		mlx5dr_err(dmn, "Failed modify header TTL %d\n", ret);
51c47ff7baSAlex Vesker 		goto destroy_flow_group;
52c47ff7baSAlex Vesker 	}
53c47ff7baSAlex Vesker 
54c47ff7baSAlex Vesker 	ret = mlx5dr_cmd_set_fte_modify_and_vport(dmn->mdev,
55c47ff7baSAlex Vesker 						  MLX5_FLOW_TABLE_TYPE_FDB,
56c47ff7baSAlex Vesker 						  table_id, group_id, modify_hdr_id,
57c47ff7baSAlex Vesker 						  vport_num);
58c47ff7baSAlex Vesker 	if (ret) {
59c47ff7baSAlex Vesker 		mlx5dr_err(dmn, "Failed setting TTL W/A flow table entry %d\n", ret);
60c47ff7baSAlex Vesker 		goto dealloc_modify_header;
61c47ff7baSAlex Vesker 	}
62c47ff7baSAlex Vesker 
63c47ff7baSAlex Vesker 	recalc_cs_ft->modify_hdr_id = modify_hdr_id;
64c47ff7baSAlex Vesker 	recalc_cs_ft->rx_icm_addr = rx_icm_addr;
65c47ff7baSAlex Vesker 	recalc_cs_ft->table_id = table_id;
66c47ff7baSAlex Vesker 	recalc_cs_ft->group_id = group_id;
67c47ff7baSAlex Vesker 
68c47ff7baSAlex Vesker 	return recalc_cs_ft;
69c47ff7baSAlex Vesker 
70c47ff7baSAlex Vesker dealloc_modify_header:
71c47ff7baSAlex Vesker 	mlx5dr_cmd_dealloc_modify_header(dmn->mdev, modify_hdr_id);
72c47ff7baSAlex Vesker destroy_flow_group:
73c47ff7baSAlex Vesker 	mlx5dr_cmd_destroy_flow_group(dmn->mdev,
74c47ff7baSAlex Vesker 				      MLX5_FLOW_TABLE_TYPE_FDB,
75c47ff7baSAlex Vesker 				      table_id, group_id);
76c47ff7baSAlex Vesker destroy_flow_table:
77c47ff7baSAlex Vesker 	mlx5dr_cmd_destroy_flow_table(dmn->mdev, table_id, MLX5_FLOW_TABLE_TYPE_FDB);
78c47ff7baSAlex Vesker free_ttl_tbl:
79c47ff7baSAlex Vesker 	kfree(recalc_cs_ft);
80c47ff7baSAlex Vesker 	return NULL;
81c47ff7baSAlex Vesker }
82c47ff7baSAlex Vesker 
mlx5dr_fw_destroy_recalc_cs_ft(struct mlx5dr_domain * dmn,struct mlx5dr_fw_recalc_cs_ft * recalc_cs_ft)83c47ff7baSAlex Vesker void mlx5dr_fw_destroy_recalc_cs_ft(struct mlx5dr_domain *dmn,
84c47ff7baSAlex Vesker 				    struct mlx5dr_fw_recalc_cs_ft *recalc_cs_ft)
85c47ff7baSAlex Vesker {
86c47ff7baSAlex Vesker 	mlx5dr_cmd_del_flow_table_entry(dmn->mdev,
87c47ff7baSAlex Vesker 					MLX5_FLOW_TABLE_TYPE_FDB,
88c47ff7baSAlex Vesker 					recalc_cs_ft->table_id);
89c47ff7baSAlex Vesker 	mlx5dr_cmd_dealloc_modify_header(dmn->mdev, recalc_cs_ft->modify_hdr_id);
90c47ff7baSAlex Vesker 	mlx5dr_cmd_destroy_flow_group(dmn->mdev,
91c47ff7baSAlex Vesker 				      MLX5_FLOW_TABLE_TYPE_FDB,
92c47ff7baSAlex Vesker 				      recalc_cs_ft->table_id,
93c47ff7baSAlex Vesker 				      recalc_cs_ft->group_id);
94c47ff7baSAlex Vesker 	mlx5dr_cmd_destroy_flow_table(dmn->mdev,
95c47ff7baSAlex Vesker 				      recalc_cs_ft->table_id,
96c47ff7baSAlex Vesker 				      MLX5_FLOW_TABLE_TYPE_FDB);
97c47ff7baSAlex Vesker 
98c47ff7baSAlex Vesker 	kfree(recalc_cs_ft);
99c47ff7baSAlex Vesker }
10034583beeSErez Shitrit 
mlx5dr_fw_create_md_tbl(struct mlx5dr_domain * dmn,struct mlx5dr_cmd_flow_destination_hw_info * dest,int num_dest,bool reformat_req,u32 * tbl_id,u32 * group_id,bool ignore_flow_level,u32 flow_source)10134583beeSErez Shitrit int mlx5dr_fw_create_md_tbl(struct mlx5dr_domain *dmn,
10234583beeSErez Shitrit 			    struct mlx5dr_cmd_flow_destination_hw_info *dest,
10334583beeSErez Shitrit 			    int num_dest,
10434583beeSErez Shitrit 			    bool reformat_req,
10534583beeSErez Shitrit 			    u32 *tbl_id,
10663b85f49SYevgeny Kliteynik 			    u32 *group_id,
107*2c5fc6cdSMaor Dickman 			    bool ignore_flow_level,
108*2c5fc6cdSMaor Dickman 			    u32 flow_source)
10934583beeSErez Shitrit {
11034583beeSErez Shitrit 	struct mlx5dr_cmd_create_flow_table_attr ft_attr = {};
11134583beeSErez Shitrit 	struct mlx5dr_cmd_fte_info fte_info = {};
11234583beeSErez Shitrit 	u32 val[MLX5_ST_SZ_DW_MATCH_PARAM] = {};
11334583beeSErez Shitrit 	struct mlx5dr_cmd_ft_info ft_info = {};
11434583beeSErez Shitrit 	int ret;
11534583beeSErez Shitrit 
11634583beeSErez Shitrit 	ft_attr.table_type = MLX5_FLOW_TABLE_TYPE_FDB;
117216214c6SYevgeny Kliteynik 	ft_attr.level = min_t(int, dmn->info.caps.max_ft_level - 2,
118216214c6SYevgeny Kliteynik 			      MLX5_FT_MAX_MULTIPATH_LEVEL);
11934583beeSErez Shitrit 	ft_attr.reformat_en = reformat_req;
12034583beeSErez Shitrit 	ft_attr.decap_en = reformat_req;
12134583beeSErez Shitrit 
12234583beeSErez Shitrit 	ret = mlx5dr_cmd_create_flow_table(dmn->mdev, &ft_attr, NULL, tbl_id);
12334583beeSErez Shitrit 	if (ret) {
12434583beeSErez Shitrit 		mlx5dr_err(dmn, "Failed creating multi dest FW flow table %d\n", ret);
12534583beeSErez Shitrit 		return ret;
12634583beeSErez Shitrit 	}
12734583beeSErez Shitrit 
12834583beeSErez Shitrit 	ret = mlx5dr_cmd_create_empty_flow_group(dmn->mdev,
12934583beeSErez Shitrit 						 MLX5_FLOW_TABLE_TYPE_FDB,
13034583beeSErez Shitrit 						 *tbl_id, group_id);
13134583beeSErez Shitrit 	if (ret) {
13234583beeSErez Shitrit 		mlx5dr_err(dmn, "Failed creating multi dest FW flow group %d\n", ret);
13334583beeSErez Shitrit 		goto free_flow_table;
13434583beeSErez Shitrit 	}
13534583beeSErez Shitrit 
13634583beeSErez Shitrit 	ft_info.id = *tbl_id;
13734583beeSErez Shitrit 	ft_info.type = FS_FT_FDB;
13834583beeSErez Shitrit 	fte_info.action.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
13934583beeSErez Shitrit 	fte_info.dests_size = num_dest;
14034583beeSErez Shitrit 	fte_info.val = val;
14134583beeSErez Shitrit 	fte_info.dest_arr = dest;
14263b85f49SYevgeny Kliteynik 	fte_info.ignore_flow_level = ignore_flow_level;
143*2c5fc6cdSMaor Dickman 	fte_info.flow_context.flow_source = flow_source;
14434583beeSErez Shitrit 
14534583beeSErez Shitrit 	ret = mlx5dr_cmd_set_fte(dmn->mdev, 0, 0, &ft_info, *group_id, &fte_info);
14634583beeSErez Shitrit 	if (ret) {
14734583beeSErez Shitrit 		mlx5dr_err(dmn, "Failed setting fte into table %d\n", ret);
14834583beeSErez Shitrit 		goto free_flow_group;
14934583beeSErez Shitrit 	}
15034583beeSErez Shitrit 
15134583beeSErez Shitrit 	return 0;
15234583beeSErez Shitrit 
15334583beeSErez Shitrit free_flow_group:
15434583beeSErez Shitrit 	mlx5dr_cmd_destroy_flow_group(dmn->mdev, MLX5_FLOW_TABLE_TYPE_FDB,
15534583beeSErez Shitrit 				      *tbl_id, *group_id);
15634583beeSErez Shitrit free_flow_table:
15734583beeSErez Shitrit 	mlx5dr_cmd_destroy_flow_table(dmn->mdev, *tbl_id,
15834583beeSErez Shitrit 				      MLX5_FLOW_TABLE_TYPE_FDB);
15934583beeSErez Shitrit 	return ret;
16034583beeSErez Shitrit }
16134583beeSErez Shitrit 
mlx5dr_fw_destroy_md_tbl(struct mlx5dr_domain * dmn,u32 tbl_id,u32 group_id)16234583beeSErez Shitrit void mlx5dr_fw_destroy_md_tbl(struct mlx5dr_domain *dmn,
16334583beeSErez Shitrit 			      u32 tbl_id, u32 group_id)
16434583beeSErez Shitrit {
16534583beeSErez Shitrit 	mlx5dr_cmd_del_flow_table_entry(dmn->mdev, FS_FT_FDB, tbl_id);
16634583beeSErez Shitrit 	mlx5dr_cmd_destroy_flow_group(dmn->mdev,
16734583beeSErez Shitrit 				      MLX5_FLOW_TABLE_TYPE_FDB,
16834583beeSErez Shitrit 				      tbl_id, group_id);
16934583beeSErez Shitrit 	mlx5dr_cmd_destroy_flow_table(dmn->mdev, tbl_id,
17034583beeSErez Shitrit 				      MLX5_FLOW_TABLE_TYPE_FDB);
17134583beeSErez Shitrit }
172