net/mlx5: DR, No need for atomic refcount for internal SW steering resources
authorYevgeny Kliteynik <kliteyn@mellanox.com>
Mon, 23 Dec 2019 14:16:31 +0000 (16:16 +0200)
committerSaeed Mahameed <saeedm@mellanox.com>
Mon, 6 Jan 2020 23:30:04 +0000 (15:30 -0800)
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: 26d688e33f88 ("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>
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_rule.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h

index 32e94d2..f21bc1b 100644 (file)
@@ -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
         * 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 */
        mlx5dr_rule_update_rule_member(cur_ste, new_ste);
index a5a2669..c6c7d1d 100644 (file)
@@ -348,7 +348,7 @@ static void dr_ste_replace(struct mlx5dr_ste *dst, struct mlx5dr_ste *src)
        if (dst->next_htbl)
                dst->next_htbl->pointing_ste = dst;
 
-       refcount_set(&dst->refcount, refcount_read(&src->refcount));
+       dst->refcount = src->refcount;
 
        INIT_LIST_HEAD(&dst->rule_list);
        list_splice_tail_init(&src->rule_list, &dst->rule_list);
@@ -565,7 +565,7 @@ bool mlx5dr_ste_is_not_valid_entry(u8 *p_hw_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 */
@@ -689,14 +689,14 @@ struct mlx5dr_ste_htbl *mlx5dr_ste_htbl_alloc(struct mlx5dr_icm_pool *pool,
        htbl->ste_arr = chunk->ste_arr;
        htbl->hw_ste_arr = chunk->hw_ste_arr;
        htbl->miss_list = chunk->miss_list;
-       refcount_set(&htbl->refcount, 0);
+       htbl->refcount = 0;
 
        for (i = 0; i < chunk->num_of_entries; i++) {
                struct mlx5dr_ste *ste = &htbl->ste_arr[i];
 
                ste->hw_ste = htbl->hw_ste_arr + i * DR_STE_SIZE_REDUCED;
                ste->htbl = htbl;
-               refcount_set(&ste->refcount, 0);
+               ste->refcount = 0;
                INIT_LIST_HEAD(&ste->miss_list_node);
                INIT_LIST_HEAD(&htbl->miss_list[i]);
                INIT_LIST_HEAD(&ste->rule_list);
@@ -713,7 +713,7 @@ out_free_htbl:
 
 int mlx5dr_ste_htbl_free(struct mlx5dr_ste_htbl *htbl)
 {
-       if (refcount_read(&htbl->refcount))
+       if (htbl->refcount)
                return -EBUSY;
 
        mlx5dr_icm_free_chunk(htbl->chunk);
index 290fe61..3fdf4a5 100644 (file)
@@ -123,7 +123,7 @@ struct mlx5dr_matcher_rx_tx;
 struct mlx5dr_ste {
        u8 *hw_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 */
        struct list_head miss_list_node;
@@ -155,7 +155,7 @@ struct mlx5dr_ste_htbl_ctrl {
 struct mlx5dr_ste_htbl {
        u8 lu_type;
        u16 byte_mask;
-       refcount_t refcount;
+       u32 refcount;
        struct mlx5dr_icm_chunk *chunk;
        struct mlx5dr_ste *ste_arr;
        u8 *hw_ste_arr;
@@ -206,13 +206,14 @@ int mlx5dr_ste_htbl_free(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);
 }
 
 static inline void mlx5dr_htbl_get(struct mlx5dr_ste_htbl *htbl)
 {
-       refcount_inc(&htbl->refcount);
+       htbl->refcount++;
 }
 
 /* STE utils */
@@ -254,14 +255,15 @@ static inline void mlx5dr_ste_put(struct mlx5dr_ste *ste,
                                  struct mlx5dr_matcher *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);
 }
 
 /* initial as 0, increased only when ste appears in a new rule */
 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,