mlxsw: Use refcount_t for reference counting
authorAmit Cohen <amcohen@nvidia.com>
Fri, 26 Jan 2024 18:58:31 +0000 (19:58 +0100)
committerPaolo Abeni <pabeni@redhat.com>
Tue, 30 Jan 2024 14:47:36 +0000 (15:47 +0100)
mlxsw driver uses 'unsigned int' for reference counters in several
structures. Instead, use refcount_t type which allows us to catch overflow
and underflow issues. Change the type of the counters and use the
appropriate API.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Petr Machata <petrm@nvidia.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c
drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c

index faa63ea9b83e1abd89815c9ec62f21501e7886b8..1915fa41c622461d6343e9d935ca77c220cd0452 100644 (file)
@@ -95,7 +95,7 @@ struct mlxsw_afa_set {
                      */
           has_trap:1,
           has_police:1;
-       unsigned int ref_count;
+       refcount_t ref_count;
        struct mlxsw_afa_set *next; /* Pointer to the next set. */
        struct mlxsw_afa_set *prev; /* Pointer to the previous set,
                                     * note that set may have multiple
@@ -120,7 +120,7 @@ struct mlxsw_afa_fwd_entry {
        struct rhash_head ht_node;
        struct mlxsw_afa_fwd_entry_ht_key ht_key;
        u32 kvdl_index;
-       unsigned int ref_count;
+       refcount_t ref_count;
 };
 
 static const struct rhashtable_params mlxsw_afa_fwd_entry_ht_params = {
@@ -282,7 +282,7 @@ static struct mlxsw_afa_set *mlxsw_afa_set_create(bool is_first)
        /* Need to initialize the set to pass by default */
        mlxsw_afa_set_goto_set(set, MLXSW_AFA_SET_GOTO_BINDING_CMD_TERM, 0);
        set->ht_key.is_first = is_first;
-       set->ref_count = 1;
+       refcount_set(&set->ref_count, 1);
        return set;
 }
 
@@ -330,7 +330,7 @@ static void mlxsw_afa_set_unshare(struct mlxsw_afa *mlxsw_afa,
 static void mlxsw_afa_set_put(struct mlxsw_afa *mlxsw_afa,
                              struct mlxsw_afa_set *set)
 {
-       if (--set->ref_count)
+       if (!refcount_dec_and_test(&set->ref_count))
                return;
        if (set->shared)
                mlxsw_afa_set_unshare(mlxsw_afa, set);
@@ -350,7 +350,7 @@ static struct mlxsw_afa_set *mlxsw_afa_set_get(struct mlxsw_afa *mlxsw_afa,
        set = rhashtable_lookup_fast(&mlxsw_afa->set_ht, &orig_set->ht_key,
                                     mlxsw_afa_set_ht_params);
        if (set) {
-               set->ref_count++;
+               refcount_inc(&set->ref_count);
                mlxsw_afa_set_put(mlxsw_afa, orig_set);
        } else {
                set = orig_set;
@@ -564,7 +564,7 @@ mlxsw_afa_fwd_entry_create(struct mlxsw_afa *mlxsw_afa, u16 local_port)
        if (!fwd_entry)
                return ERR_PTR(-ENOMEM);
        fwd_entry->ht_key.local_port = local_port;
-       fwd_entry->ref_count = 1;
+       refcount_set(&fwd_entry->ref_count, 1);
 
        err = rhashtable_insert_fast(&mlxsw_afa->fwd_entry_ht,
                                     &fwd_entry->ht_node,
@@ -607,7 +607,7 @@ mlxsw_afa_fwd_entry_get(struct mlxsw_afa *mlxsw_afa, u16 local_port)
        fwd_entry = rhashtable_lookup_fast(&mlxsw_afa->fwd_entry_ht, &ht_key,
                                           mlxsw_afa_fwd_entry_ht_params);
        if (fwd_entry) {
-               fwd_entry->ref_count++;
+               refcount_inc(&fwd_entry->ref_count);
                return fwd_entry;
        }
        return mlxsw_afa_fwd_entry_create(mlxsw_afa, local_port);
@@ -616,7 +616,7 @@ mlxsw_afa_fwd_entry_get(struct mlxsw_afa *mlxsw_afa, u16 local_port)
 static void mlxsw_afa_fwd_entry_put(struct mlxsw_afa *mlxsw_afa,
                                    struct mlxsw_afa_fwd_entry *fwd_entry)
 {
-       if (--fwd_entry->ref_count)
+       if (!refcount_dec_and_test(&fwd_entry->ref_count))
                return;
        mlxsw_afa_fwd_entry_destroy(mlxsw_afa, fwd_entry);
 }
index 0d5e6f9b466ec2fee8bd8d6259dfe54d48b270f7..947500f8ed714299f31dc91c7005912ae496fb91 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/slab.h>
 #include <linux/list.h>
 #include <linux/errno.h>
+#include <linux/refcount.h>
 
 #include "item.h"
 #include "core_acl_flex_keys.h"
@@ -107,7 +108,7 @@ EXPORT_SYMBOL(mlxsw_afk_destroy);
 
 struct mlxsw_afk_key_info {
        struct list_head list;
-       unsigned int ref_count;
+       refcount_t ref_count;
        unsigned int blocks_count;
        int element_to_block[MLXSW_AFK_ELEMENT_MAX]; /* index is element, value
                                                      * is index inside "blocks"
@@ -334,7 +335,7 @@ mlxsw_afk_key_info_create(struct mlxsw_afk *mlxsw_afk,
        if (err)
                goto err_picker;
        list_add(&key_info->list, &mlxsw_afk->key_info_list);
-       key_info->ref_count = 1;
+       refcount_set(&key_info->ref_count, 1);
        return key_info;
 
 err_picker:
@@ -356,7 +357,7 @@ mlxsw_afk_key_info_get(struct mlxsw_afk *mlxsw_afk,
 
        key_info = mlxsw_afk_key_info_find(mlxsw_afk, elusage);
        if (key_info) {
-               key_info->ref_count++;
+               refcount_inc(&key_info->ref_count);
                return key_info;
        }
        return mlxsw_afk_key_info_create(mlxsw_afk, elusage);
@@ -365,7 +366,7 @@ EXPORT_SYMBOL(mlxsw_afk_key_info_get);
 
 void mlxsw_afk_key_info_put(struct mlxsw_afk_key_info *key_info)
 {
-       if (--key_info->ref_count)
+       if (!refcount_dec_and_test(&key_info->ref_count))
                return;
        mlxsw_afk_key_info_destroy(key_info);
 }
index 7c59c8a13584053ff2b91123956e44df66dfc27c..b01b000bc71c145da7fe1b183d551708d92505b2 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/rhashtable.h>
 #include <linux/netdevice.h>
 #include <linux/mutex.h>
+#include <linux/refcount.h>
 #include <net/net_namespace.h>
 #include <net/tc_act/tc_vlan.h>
 
@@ -55,7 +56,7 @@ struct mlxsw_sp_acl_ruleset {
        struct rhash_head ht_node; /* Member of acl HT */
        struct mlxsw_sp_acl_ruleset_ht_key ht_key;
        struct rhashtable rule_ht;
-       unsigned int ref_count;
+       refcount_t ref_count;
        unsigned int min_prio;
        unsigned int max_prio;
        unsigned long priv[];
@@ -99,7 +100,7 @@ static bool
 mlxsw_sp_acl_ruleset_is_singular(const struct mlxsw_sp_acl_ruleset *ruleset)
 {
        /* We hold a reference on ruleset ourselves */
-       return ruleset->ref_count == 2;
+       return refcount_read(&ruleset->ref_count) == 2;
 }
 
 int mlxsw_sp_acl_ruleset_bind(struct mlxsw_sp *mlxsw_sp,
@@ -176,7 +177,7 @@ mlxsw_sp_acl_ruleset_create(struct mlxsw_sp *mlxsw_sp,
        ruleset = kzalloc(alloc_size, GFP_KERNEL);
        if (!ruleset)
                return ERR_PTR(-ENOMEM);
-       ruleset->ref_count = 1;
+       refcount_set(&ruleset->ref_count, 1);
        ruleset->ht_key.block = block;
        ruleset->ht_key.chain_index = chain_index;
        ruleset->ht_key.ops = ops;
@@ -222,13 +223,13 @@ static void mlxsw_sp_acl_ruleset_destroy(struct mlxsw_sp *mlxsw_sp,
 
 static void mlxsw_sp_acl_ruleset_ref_inc(struct mlxsw_sp_acl_ruleset *ruleset)
 {
-       ruleset->ref_count++;
+       refcount_inc(&ruleset->ref_count);
 }
 
 static void mlxsw_sp_acl_ruleset_ref_dec(struct mlxsw_sp *mlxsw_sp,
                                         struct mlxsw_sp_acl_ruleset *ruleset)
 {
-       if (--ruleset->ref_count)
+       if (!refcount_dec_and_test(&ruleset->ref_count))
                return;
        mlxsw_sp_acl_ruleset_destroy(mlxsw_sp, ruleset);
 }
index 50ea1eff02b2f713ee847a6ea8dffb2ca248ae57..f20052776b3f2e9a3ac7181921a12c3858abea4b 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/rhashtable.h>
 #include <linux/netdevice.h>
 #include <linux/mutex.h>
+#include <linux/refcount.h>
 #include <net/devlink.h>
 #include <trace/events/mlxsw.h>
 
@@ -155,7 +156,7 @@ struct mlxsw_sp_acl_tcam_vregion {
                struct mlxsw_sp_acl_tcam_rehash_ctx ctx;
        } rehash;
        struct mlxsw_sp *mlxsw_sp;
-       unsigned int ref_count;
+       refcount_t ref_count;
 };
 
 struct mlxsw_sp_acl_tcam_vchunk;
@@ -176,7 +177,7 @@ struct mlxsw_sp_acl_tcam_vchunk {
        unsigned int priority; /* Priority within the vregion and group */
        struct mlxsw_sp_acl_tcam_vgroup *vgroup;
        struct mlxsw_sp_acl_tcam_vregion *vregion;
-       unsigned int ref_count;
+       refcount_t ref_count;
 };
 
 struct mlxsw_sp_acl_tcam_entry {
@@ -769,7 +770,7 @@ mlxsw_sp_acl_tcam_vregion_create(struct mlxsw_sp *mlxsw_sp,
        vregion->tcam = tcam;
        vregion->mlxsw_sp = mlxsw_sp;
        vregion->vgroup = vgroup;
-       vregion->ref_count = 1;
+       refcount_set(&vregion->ref_count, 1);
 
        vregion->key_info = mlxsw_afk_key_info_get(afk, elusage);
        if (IS_ERR(vregion->key_info)) {
@@ -856,7 +857,7 @@ mlxsw_sp_acl_tcam_vregion_get(struct mlxsw_sp *mlxsw_sp,
                         */
                        return ERR_PTR(-EOPNOTSUPP);
                }
-               vregion->ref_count++;
+               refcount_inc(&vregion->ref_count);
                return vregion;
        }
 
@@ -871,7 +872,7 @@ static void
 mlxsw_sp_acl_tcam_vregion_put(struct mlxsw_sp *mlxsw_sp,
                              struct mlxsw_sp_acl_tcam_vregion *vregion)
 {
-       if (--vregion->ref_count)
+       if (!refcount_dec_and_test(&vregion->ref_count))
                return;
        mlxsw_sp_acl_tcam_vregion_destroy(mlxsw_sp, vregion);
 }
@@ -924,7 +925,7 @@ mlxsw_sp_acl_tcam_vchunk_create(struct mlxsw_sp *mlxsw_sp,
        INIT_LIST_HEAD(&vchunk->ventry_list);
        vchunk->priority = priority;
        vchunk->vgroup = vgroup;
-       vchunk->ref_count = 1;
+       refcount_set(&vchunk->ref_count, 1);
 
        vregion = mlxsw_sp_acl_tcam_vregion_get(mlxsw_sp, vgroup,
                                                priority, elusage);
@@ -1008,7 +1009,7 @@ mlxsw_sp_acl_tcam_vchunk_get(struct mlxsw_sp *mlxsw_sp,
                if (WARN_ON(!mlxsw_afk_key_info_subset(vchunk->vregion->key_info,
                                                       elusage)))
                        return ERR_PTR(-EINVAL);
-               vchunk->ref_count++;
+               refcount_inc(&vchunk->ref_count);
                return vchunk;
        }
        return mlxsw_sp_acl_tcam_vchunk_create(mlxsw_sp, vgroup,
@@ -1019,7 +1020,7 @@ static void
 mlxsw_sp_acl_tcam_vchunk_put(struct mlxsw_sp *mlxsw_sp,
                             struct mlxsw_sp_acl_tcam_vchunk *vchunk)
 {
-       if (--vchunk->ref_count)
+       if (!refcount_dec_and_test(&vchunk->ref_count))
                return;
        mlxsw_sp_acl_tcam_vchunk_destroy(mlxsw_sp, vchunk);
 }
index 7164f9e6370fb76d91aad3c09f4a93f061daf1fc..87617df694ab29a6c790a1755fab44095fb14f4a 100644 (file)
@@ -501,7 +501,7 @@ struct mlxsw_sp_rt6 {
 
 struct mlxsw_sp_lpm_tree {
        u8 id; /* tree ID */
-       unsigned int ref_count;
+       refcount_t ref_count;
        enum mlxsw_sp_l3proto proto;
        unsigned long prefix_ref_count[MLXSW_SP_PREFIX_COUNT];
        struct mlxsw_sp_prefix_usage prefix_usage;
@@ -578,7 +578,7 @@ mlxsw_sp_lpm_tree_find_unused(struct mlxsw_sp *mlxsw_sp)
 
        for (i = 0; i < mlxsw_sp->router->lpm.tree_count; i++) {
                lpm_tree = &mlxsw_sp->router->lpm.trees[i];
-               if (lpm_tree->ref_count == 0)
+               if (refcount_read(&lpm_tree->ref_count) == 0)
                        return lpm_tree;
        }
        return NULL;
@@ -654,7 +654,7 @@ mlxsw_sp_lpm_tree_create(struct mlxsw_sp *mlxsw_sp,
               sizeof(lpm_tree->prefix_usage));
        memset(&lpm_tree->prefix_ref_count, 0,
               sizeof(lpm_tree->prefix_ref_count));
-       lpm_tree->ref_count = 1;
+       refcount_set(&lpm_tree->ref_count, 1);
        return lpm_tree;
 
 err_left_struct_set:
@@ -678,7 +678,7 @@ mlxsw_sp_lpm_tree_get(struct mlxsw_sp *mlxsw_sp,
 
        for (i = 0; i < mlxsw_sp->router->lpm.tree_count; i++) {
                lpm_tree = &mlxsw_sp->router->lpm.trees[i];
-               if (lpm_tree->ref_count != 0 &&
+               if (refcount_read(&lpm_tree->ref_count) &&
                    lpm_tree->proto == proto &&
                    mlxsw_sp_prefix_usage_eq(&lpm_tree->prefix_usage,
                                             prefix_usage)) {
@@ -691,14 +691,15 @@ mlxsw_sp_lpm_tree_get(struct mlxsw_sp *mlxsw_sp,
 
 static void mlxsw_sp_lpm_tree_hold(struct mlxsw_sp_lpm_tree *lpm_tree)
 {
-       lpm_tree->ref_count++;
+       refcount_inc(&lpm_tree->ref_count);
 }
 
 static void mlxsw_sp_lpm_tree_put(struct mlxsw_sp *mlxsw_sp,
                                  struct mlxsw_sp_lpm_tree *lpm_tree)
 {
-       if (--lpm_tree->ref_count == 0)
-               mlxsw_sp_lpm_tree_destroy(mlxsw_sp, lpm_tree);
+       if (!refcount_dec_and_test(&lpm_tree->ref_count))
+               return;
+       mlxsw_sp_lpm_tree_destroy(mlxsw_sp, lpm_tree);
 }
 
 #define MLXSW_SP_LPM_TREE_MIN 1 /* tree 0 is reserved */
index 6c749c148148d3a93fba39bec5596e7f75c1198f..6397ff0dc951cddb86272027a1bd33c0d123e980 100644 (file)
@@ -61,7 +61,7 @@ struct mlxsw_sp_bridge_port {
        struct mlxsw_sp_bridge_device *bridge_device;
        struct list_head list;
        struct list_head vlans_list;
-       unsigned int ref_count;
+       refcount_t ref_count;
        u8 stp_state;
        unsigned long flags;
        bool mrouter;
@@ -495,7 +495,7 @@ mlxsw_sp_bridge_port_create(struct mlxsw_sp_bridge_device *bridge_device,
                             BR_MCAST_FLOOD;
        INIT_LIST_HEAD(&bridge_port->vlans_list);
        list_add(&bridge_port->list, &bridge_device->ports_list);
-       bridge_port->ref_count = 1;
+       refcount_set(&bridge_port->ref_count, 1);
 
        err = switchdev_bridge_port_offload(brport_dev, mlxsw_sp_port->dev,
                                            NULL, NULL, NULL, false, extack);
@@ -531,7 +531,7 @@ mlxsw_sp_bridge_port_get(struct mlxsw_sp_bridge *bridge,
 
        bridge_port = mlxsw_sp_bridge_port_find(bridge, brport_dev);
        if (bridge_port) {
-               bridge_port->ref_count++;
+               refcount_inc(&bridge_port->ref_count);
                return bridge_port;
        }
 
@@ -558,7 +558,7 @@ static void mlxsw_sp_bridge_port_put(struct mlxsw_sp_bridge *bridge,
 {
        struct mlxsw_sp_bridge_device *bridge_device;
 
-       if (--bridge_port->ref_count != 0)
+       if (!refcount_dec_and_test(&bridge_port->ref_count))
                return;
        bridge_device = bridge_port->bridge_device;
        mlxsw_sp_bridge_port_destroy(bridge_port);