// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2019 Mellanox Technologies. */
#include "dr_types.h"
#define DR_RULE_MAX_STE_CHAIN (DR_RULE_MAX_STES + DR_ACTION_MAX_STES)
struct mlx5dr_rule_action_member {
struct mlx5dr_action *action;
struct list_head list;
};
static int dr_rule_append_to_miss_list(struct mlx5dr_ste *new_last_ste,
struct list_head *miss_list,
struct list_head *send_list)
{
struct mlx5dr_ste_send_info *ste_info_last;
struct mlx5dr_ste *last_ste;
/* The new entry will be inserted after the last */
last_ste = list_last_entry(miss_list, struct mlx5dr_ste, miss_list_node);
WARN_ON(!last_ste);
ste_info_last = kzalloc(sizeof(*ste_info_last), GFP_KERNEL);
if (!ste_info_last)
return -ENOMEM;
mlx5dr_ste_set_miss_addr(last_ste->hw_ste,
mlx5dr_ste_get_icm_addr(new_last_ste));
list_add_tail(&new_last_ste->miss_list_node, miss_list);
mlx5dr_send_fill_and_append_ste_send_info(last_ste, DR_STE_SIZE_REDUCED,
0, last_ste->hw_ste,
ste_info_last, send_list, true);
return 0;
}
static struct mlx5dr_ste *
dr_rule_create_collision_htbl(struct mlx5dr_matcher *matcher,
struct mlx5dr_matcher_rx_tx *nic_matcher,
u8 *hw_ste)
{
struct mlx5dr_domain *dmn = matcher->tbl->dmn;
struct mlx5dr_ste_htbl *new_htbl;
struct mlx5dr_ste *ste;
/* Create new table for miss entry */
new_htbl = mlx5dr_ste_htbl_alloc(dmn->ste_icm_pool,
DR_CHUNK_SIZE_1,
MLX5DR_STE_LU_TYPE_DONT_CARE,
0);
if (!new_htbl) {
mlx5dr_dbg(dmn, "Failed allocating collision table\n");
return NULL;
}
/* One and only entry, never grows */
ste = new_htbl->ste_arr;
mlx5dr_ste_set_miss_addr(hw_ste, nic_matcher->e_anchor->chunk->icm_addr);
mlx5dr_htbl_get(new_htbl);
return ste;
}
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)
{
struct mlx5dr_ste *ste;
ste = dr_rule_create_collision_htbl(matcher, nic_matcher, hw_ste);
if (!ste) {
mlx5dr_dbg(matcher->tbl->dmn, "Failed creating collision entry\n");
return NULL;
}
ste->ste_chain_location = orig_ste->ste_chain_location;
/* In collision entry, all members share the same miss_list_head */
ste->htbl->miss_list = mlx5dr_ste_get_miss_list(o