mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-06 08:46:46 +00:00
net/mlx5: DR, No need for atomic refcount for internal SW steering resources
[ Upstream commit4ce380ca47
] No need for an atomic refcounter for the STE and hashtables. These are internal SW steering resources and they are always under domain mutex. This also fixes the following refcount error: refcount_t: addition on 0; use-after-free. WARNING: CPU: 9 PID: 3527 at lib/refcount.c:25 refcount_warn_saturate+0x81/0xe0 Call Trace: dr_table_init_nic+0x10d/0x110 [mlx5_core] mlx5dr_table_create+0xb4/0x230 [mlx5_core] mlx5_cmd_dr_create_flow_table+0x39/0x120 [mlx5_core] __mlx5_create_flow_table+0x221/0x5f0 [mlx5_core] esw_create_offloads_fdb_tables+0x180/0x5a0 [mlx5_core] ... Fixes:26d688e33f
("net/mlx5: DR, Add Steering entry (STE) utilities") Signed-off-by: Yevgeny Kliteynik <kliteyn@mellanox.com> Reviewed-by: Alex Vesker <valex@mellanox.com> Signed-off-by: Saeed Mahameed <saeedm@mellanox.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
0c3990776f
commit
c48a78c083
3 changed files with 14 additions and 12 deletions
|
@ -209,7 +209,7 @@ static void dr_rule_rehash_copy_ste_ctrl(struct mlx5dr_matcher *matcher,
|
||||||
/* We need to copy the refcount since this ste
|
/* We need to copy the refcount since this ste
|
||||||
* may have been traversed several times
|
* may have been traversed several times
|
||||||
*/
|
*/
|
||||||
refcount_set(&new_ste->refcount, refcount_read(&cur_ste->refcount));
|
new_ste->refcount = cur_ste->refcount;
|
||||||
|
|
||||||
/* Link old STEs rule_mem list to the new ste */
|
/* Link old STEs rule_mem list to the new ste */
|
||||||
mlx5dr_rule_update_rule_member(cur_ste, new_ste);
|
mlx5dr_rule_update_rule_member(cur_ste, new_ste);
|
||||||
|
|
|
@ -340,7 +340,7 @@ static void dr_ste_replace(struct mlx5dr_ste *dst, struct mlx5dr_ste *src)
|
||||||
if (dst->next_htbl)
|
if (dst->next_htbl)
|
||||||
dst->next_htbl->pointing_ste = dst;
|
dst->next_htbl->pointing_ste = dst;
|
||||||
|
|
||||||
refcount_set(&dst->refcount, refcount_read(&src->refcount));
|
dst->refcount = src->refcount;
|
||||||
|
|
||||||
INIT_LIST_HEAD(&dst->rule_list);
|
INIT_LIST_HEAD(&dst->rule_list);
|
||||||
list_splice_tail_init(&src->rule_list, &dst->rule_list);
|
list_splice_tail_init(&src->rule_list, &dst->rule_list);
|
||||||
|
@ -557,7 +557,7 @@ bool mlx5dr_ste_is_not_valid_entry(u8 *p_hw_ste)
|
||||||
|
|
||||||
bool mlx5dr_ste_not_used_ste(struct mlx5dr_ste *ste)
|
bool mlx5dr_ste_not_used_ste(struct mlx5dr_ste *ste)
|
||||||
{
|
{
|
||||||
return !refcount_read(&ste->refcount);
|
return !ste->refcount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Init one ste as a pattern for ste data array */
|
/* Init one ste as a pattern for ste data array */
|
||||||
|
@ -681,14 +681,14 @@ struct mlx5dr_ste_htbl *mlx5dr_ste_htbl_alloc(struct mlx5dr_icm_pool *pool,
|
||||||
htbl->ste_arr = chunk->ste_arr;
|
htbl->ste_arr = chunk->ste_arr;
|
||||||
htbl->hw_ste_arr = chunk->hw_ste_arr;
|
htbl->hw_ste_arr = chunk->hw_ste_arr;
|
||||||
htbl->miss_list = chunk->miss_list;
|
htbl->miss_list = chunk->miss_list;
|
||||||
refcount_set(&htbl->refcount, 0);
|
htbl->refcount = 0;
|
||||||
|
|
||||||
for (i = 0; i < chunk->num_of_entries; i++) {
|
for (i = 0; i < chunk->num_of_entries; i++) {
|
||||||
struct mlx5dr_ste *ste = &htbl->ste_arr[i];
|
struct mlx5dr_ste *ste = &htbl->ste_arr[i];
|
||||||
|
|
||||||
ste->hw_ste = htbl->hw_ste_arr + i * DR_STE_SIZE_REDUCED;
|
ste->hw_ste = htbl->hw_ste_arr + i * DR_STE_SIZE_REDUCED;
|
||||||
ste->htbl = htbl;
|
ste->htbl = htbl;
|
||||||
refcount_set(&ste->refcount, 0);
|
ste->refcount = 0;
|
||||||
INIT_LIST_HEAD(&ste->miss_list_node);
|
INIT_LIST_HEAD(&ste->miss_list_node);
|
||||||
INIT_LIST_HEAD(&htbl->miss_list[i]);
|
INIT_LIST_HEAD(&htbl->miss_list[i]);
|
||||||
INIT_LIST_HEAD(&ste->rule_list);
|
INIT_LIST_HEAD(&ste->rule_list);
|
||||||
|
@ -705,7 +705,7 @@ struct mlx5dr_ste_htbl *mlx5dr_ste_htbl_alloc(struct mlx5dr_icm_pool *pool,
|
||||||
|
|
||||||
int mlx5dr_ste_htbl_free(struct mlx5dr_ste_htbl *htbl)
|
int mlx5dr_ste_htbl_free(struct mlx5dr_ste_htbl *htbl)
|
||||||
{
|
{
|
||||||
if (refcount_read(&htbl->refcount))
|
if (htbl->refcount)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
mlx5dr_icm_free_chunk(htbl->chunk);
|
mlx5dr_icm_free_chunk(htbl->chunk);
|
||||||
|
|
|
@ -117,7 +117,7 @@ struct mlx5dr_matcher_rx_tx;
|
||||||
struct mlx5dr_ste {
|
struct mlx5dr_ste {
|
||||||
u8 *hw_ste;
|
u8 *hw_ste;
|
||||||
/* refcount: indicates the num of rules that using this ste */
|
/* refcount: indicates the num of rules that using this ste */
|
||||||
refcount_t refcount;
|
u32 refcount;
|
||||||
|
|
||||||
/* attached to the miss_list head at each htbl entry */
|
/* attached to the miss_list head at each htbl entry */
|
||||||
struct list_head miss_list_node;
|
struct list_head miss_list_node;
|
||||||
|
@ -149,7 +149,7 @@ struct mlx5dr_ste_htbl_ctrl {
|
||||||
struct mlx5dr_ste_htbl {
|
struct mlx5dr_ste_htbl {
|
||||||
u8 lu_type;
|
u8 lu_type;
|
||||||
u16 byte_mask;
|
u16 byte_mask;
|
||||||
refcount_t refcount;
|
u32 refcount;
|
||||||
struct mlx5dr_icm_chunk *chunk;
|
struct mlx5dr_icm_chunk *chunk;
|
||||||
struct mlx5dr_ste *ste_arr;
|
struct mlx5dr_ste *ste_arr;
|
||||||
u8 *hw_ste_arr;
|
u8 *hw_ste_arr;
|
||||||
|
@ -200,13 +200,14 @@ int mlx5dr_ste_htbl_free(struct mlx5dr_ste_htbl *htbl);
|
||||||
|
|
||||||
static inline void mlx5dr_htbl_put(struct mlx5dr_ste_htbl *htbl)
|
static inline void mlx5dr_htbl_put(struct mlx5dr_ste_htbl *htbl)
|
||||||
{
|
{
|
||||||
if (refcount_dec_and_test(&htbl->refcount))
|
htbl->refcount--;
|
||||||
|
if (!htbl->refcount)
|
||||||
mlx5dr_ste_htbl_free(htbl);
|
mlx5dr_ste_htbl_free(htbl);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void mlx5dr_htbl_get(struct mlx5dr_ste_htbl *htbl)
|
static inline void mlx5dr_htbl_get(struct mlx5dr_ste_htbl *htbl)
|
||||||
{
|
{
|
||||||
refcount_inc(&htbl->refcount);
|
htbl->refcount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* STE utils */
|
/* STE utils */
|
||||||
|
@ -248,14 +249,15 @@ static inline void mlx5dr_ste_put(struct mlx5dr_ste *ste,
|
||||||
struct mlx5dr_matcher *matcher,
|
struct mlx5dr_matcher *matcher,
|
||||||
struct mlx5dr_matcher_rx_tx *nic_matcher)
|
struct mlx5dr_matcher_rx_tx *nic_matcher)
|
||||||
{
|
{
|
||||||
if (refcount_dec_and_test(&ste->refcount))
|
ste->refcount--;
|
||||||
|
if (!ste->refcount)
|
||||||
mlx5dr_ste_free(ste, matcher, nic_matcher);
|
mlx5dr_ste_free(ste, matcher, nic_matcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* initial as 0, increased only when ste appears in a new rule */
|
/* initial as 0, increased only when ste appears in a new rule */
|
||||||
static inline void mlx5dr_ste_get(struct mlx5dr_ste *ste)
|
static inline void mlx5dr_ste_get(struct mlx5dr_ste *ste)
|
||||||
{
|
{
|
||||||
refcount_inc(&ste->refcount);
|
ste->refcount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mlx5dr_ste_set_hit_addr_by_next_htbl(u8 *hw_ste,
|
void mlx5dr_ste_set_hit_addr_by_next_htbl(u8 *hw_ste,
|
||||||
|
|
Loading…
Reference in a new issue