1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /* Copyright (c) 2019 Mellanox Technologies. */
6 int mlx5dr_table_set_miss_action(struct mlx5dr_table *tbl,
7 struct mlx5dr_action *action)
9 struct mlx5dr_matcher *last_matcher = NULL;
10 struct mlx5dr_htbl_connect_info info;
11 struct mlx5dr_ste_htbl *last_htbl;
14 if (action && action->action_type != DR_ACTION_TYP_FT)
17 mutex_lock(&tbl->dmn->mutex);
19 if (!list_empty(&tbl->matcher_list))
20 last_matcher = list_last_entry(&tbl->matcher_list,
21 struct mlx5dr_matcher,
24 if (tbl->dmn->type == MLX5DR_DOMAIN_TYPE_NIC_RX ||
25 tbl->dmn->type == MLX5DR_DOMAIN_TYPE_FDB) {
27 last_htbl = last_matcher->rx.e_anchor;
29 last_htbl = tbl->rx.s_anchor;
31 tbl->rx.default_icm_addr = action ?
32 action->dest_tbl.tbl->rx.s_anchor->chunk->icm_addr :
33 tbl->rx.nic_dmn->default_icm_addr;
35 info.type = CONNECT_MISS;
36 info.miss_icm_addr = tbl->rx.default_icm_addr;
38 ret = mlx5dr_ste_htbl_init_and_postsend(tbl->dmn,
43 mlx5dr_dbg(tbl->dmn, "Failed to set RX miss action, ret %d\n", ret);
48 if (tbl->dmn->type == MLX5DR_DOMAIN_TYPE_NIC_TX ||
49 tbl->dmn->type == MLX5DR_DOMAIN_TYPE_FDB) {
51 last_htbl = last_matcher->tx.e_anchor;
53 last_htbl = tbl->tx.s_anchor;
55 tbl->tx.default_icm_addr = action ?
56 action->dest_tbl.tbl->tx.s_anchor->chunk->icm_addr :
57 tbl->tx.nic_dmn->default_icm_addr;
59 info.type = CONNECT_MISS;
60 info.miss_icm_addr = tbl->tx.default_icm_addr;
62 ret = mlx5dr_ste_htbl_init_and_postsend(tbl->dmn,
64 last_htbl, &info, true);
66 mlx5dr_dbg(tbl->dmn, "Failed to set TX miss action, ret %d\n", ret);
71 /* Release old action */
73 refcount_dec(&tbl->miss_action->refcount);
75 /* Set new miss action */
76 tbl->miss_action = action;
78 refcount_inc(&action->refcount);
81 mutex_unlock(&tbl->dmn->mutex);
85 static void dr_table_uninit_nic(struct mlx5dr_table_rx_tx *nic_tbl)
87 mlx5dr_htbl_put(nic_tbl->s_anchor);
90 static void dr_table_uninit_fdb(struct mlx5dr_table *tbl)
92 dr_table_uninit_nic(&tbl->rx);
93 dr_table_uninit_nic(&tbl->tx);
96 static void dr_table_uninit(struct mlx5dr_table *tbl)
98 mutex_lock(&tbl->dmn->mutex);
100 switch (tbl->dmn->type) {
101 case MLX5DR_DOMAIN_TYPE_NIC_RX:
102 dr_table_uninit_nic(&tbl->rx);
104 case MLX5DR_DOMAIN_TYPE_NIC_TX:
105 dr_table_uninit_nic(&tbl->tx);
107 case MLX5DR_DOMAIN_TYPE_FDB:
108 dr_table_uninit_fdb(tbl);
115 mutex_unlock(&tbl->dmn->mutex);
118 static int dr_table_init_nic(struct mlx5dr_domain *dmn,
119 struct mlx5dr_table_rx_tx *nic_tbl)
121 struct mlx5dr_domain_rx_tx *nic_dmn = nic_tbl->nic_dmn;
122 struct mlx5dr_htbl_connect_info info;
125 nic_tbl->default_icm_addr = nic_dmn->default_icm_addr;
127 nic_tbl->s_anchor = mlx5dr_ste_htbl_alloc(dmn->ste_icm_pool,
129 MLX5DR_STE_LU_TYPE_DONT_CARE,
131 if (!nic_tbl->s_anchor)
134 info.type = CONNECT_MISS;
135 info.miss_icm_addr = nic_dmn->default_icm_addr;
136 ret = mlx5dr_ste_htbl_init_and_postsend(dmn, nic_dmn,
142 mlx5dr_htbl_get(nic_tbl->s_anchor);
147 mlx5dr_ste_htbl_free(nic_tbl->s_anchor);
151 static int dr_table_init_fdb(struct mlx5dr_table *tbl)
155 ret = dr_table_init_nic(tbl->dmn, &tbl->rx);
159 ret = dr_table_init_nic(tbl->dmn, &tbl->tx);
166 dr_table_uninit_nic(&tbl->rx);
170 static int dr_table_init(struct mlx5dr_table *tbl)
174 INIT_LIST_HEAD(&tbl->matcher_list);
176 mutex_lock(&tbl->dmn->mutex);
178 switch (tbl->dmn->type) {
179 case MLX5DR_DOMAIN_TYPE_NIC_RX:
180 tbl->table_type = MLX5_FLOW_TABLE_TYPE_NIC_RX;
181 tbl->rx.nic_dmn = &tbl->dmn->info.rx;
182 ret = dr_table_init_nic(tbl->dmn, &tbl->rx);
184 case MLX5DR_DOMAIN_TYPE_NIC_TX:
185 tbl->table_type = MLX5_FLOW_TABLE_TYPE_NIC_TX;
186 tbl->tx.nic_dmn = &tbl->dmn->info.tx;
187 ret = dr_table_init_nic(tbl->dmn, &tbl->tx);
189 case MLX5DR_DOMAIN_TYPE_FDB:
190 tbl->table_type = MLX5_FLOW_TABLE_TYPE_FDB;
191 tbl->rx.nic_dmn = &tbl->dmn->info.rx;
192 tbl->tx.nic_dmn = &tbl->dmn->info.tx;
193 ret = dr_table_init_fdb(tbl);
200 mutex_unlock(&tbl->dmn->mutex);
205 static int dr_table_destroy_sw_owned_tbl(struct mlx5dr_table *tbl)
207 return mlx5dr_cmd_destroy_flow_table(tbl->dmn->mdev,
212 static int dr_table_create_sw_owned_tbl(struct mlx5dr_table *tbl)
218 if (tbl->rx.s_anchor)
219 icm_addr_rx = tbl->rx.s_anchor->chunk->icm_addr;
221 if (tbl->tx.s_anchor)
222 icm_addr_tx = tbl->tx.s_anchor->chunk->icm_addr;
224 ret = mlx5dr_cmd_create_flow_table(tbl->dmn->mdev,
228 tbl->dmn->info.caps.max_ft_level - 1,
235 struct mlx5dr_table *mlx5dr_table_create(struct mlx5dr_domain *dmn, u32 level)
237 struct mlx5dr_table *tbl;
240 refcount_inc(&dmn->refcount);
242 tbl = kzalloc(sizeof(*tbl), GFP_KERNEL);
248 refcount_set(&tbl->refcount, 1);
250 ret = dr_table_init(tbl);
254 ret = dr_table_create_sw_owned_tbl(tbl);
261 dr_table_uninit(tbl);
265 refcount_dec(&dmn->refcount);
269 int mlx5dr_table_destroy(struct mlx5dr_table *tbl)
273 if (refcount_read(&tbl->refcount) > 1)
276 ret = dr_table_destroy_sw_owned_tbl(tbl);
280 dr_table_uninit(tbl);
282 if (tbl->miss_action)
283 refcount_dec(&tbl->miss_action->refcount);
285 refcount_dec(&tbl->dmn->refcount);
291 u32 mlx5dr_table_get_id(struct mlx5dr_table *tbl)
293 return tbl->table_id;