Commit d0005e76 authored by Paolo Abeni's avatar Paolo Abeni

Merge branch 'mlxsw-refactor-reference-counting-code'

Petr Machata says:

====================
mlxsw: Refactor reference counting code

Amit Cohen writes:

This set converts all reference counters defined as 'unsigned int' to
refcount_t type. The reference counting of LAGs can be simplified, so first
refactor the related code and then change the type of the reference
counter.

Patch set overview:
Patches #1-#4 are preparations for LAG refactor
Patch #5 refactors LAG code and change the type of reference counter
Patch #6 converts the remaining reference counters in mlxsw driver
====================

Link: https://lore.kernel.org/r/cover.1706293430.git.petrm@nvidia.comSigned-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents 4acf4e62 1267f722
...@@ -95,7 +95,7 @@ struct mlxsw_afa_set { ...@@ -95,7 +95,7 @@ struct mlxsw_afa_set {
*/ */
has_trap:1, has_trap:1,
has_police: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 *next; /* Pointer to the next set. */
struct mlxsw_afa_set *prev; /* Pointer to the previous set, struct mlxsw_afa_set *prev; /* Pointer to the previous set,
* note that set may have multiple * note that set may have multiple
...@@ -120,7 +120,7 @@ struct mlxsw_afa_fwd_entry { ...@@ -120,7 +120,7 @@ struct mlxsw_afa_fwd_entry {
struct rhash_head ht_node; struct rhash_head ht_node;
struct mlxsw_afa_fwd_entry_ht_key ht_key; struct mlxsw_afa_fwd_entry_ht_key ht_key;
u32 kvdl_index; u32 kvdl_index;
unsigned int ref_count; refcount_t ref_count;
}; };
static const struct rhashtable_params mlxsw_afa_fwd_entry_ht_params = { 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) ...@@ -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 */ /* Need to initialize the set to pass by default */
mlxsw_afa_set_goto_set(set, MLXSW_AFA_SET_GOTO_BINDING_CMD_TERM, 0); mlxsw_afa_set_goto_set(set, MLXSW_AFA_SET_GOTO_BINDING_CMD_TERM, 0);
set->ht_key.is_first = is_first; set->ht_key.is_first = is_first;
set->ref_count = 1; refcount_set(&set->ref_count, 1);
return set; return set;
} }
...@@ -330,7 +330,7 @@ static void mlxsw_afa_set_unshare(struct mlxsw_afa *mlxsw_afa, ...@@ -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, static void mlxsw_afa_set_put(struct mlxsw_afa *mlxsw_afa,
struct mlxsw_afa_set *set) struct mlxsw_afa_set *set)
{ {
if (--set->ref_count) if (!refcount_dec_and_test(&set->ref_count))
return; return;
if (set->shared) if (set->shared)
mlxsw_afa_set_unshare(mlxsw_afa, set); 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, ...@@ -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, set = rhashtable_lookup_fast(&mlxsw_afa->set_ht, &orig_set->ht_key,
mlxsw_afa_set_ht_params); mlxsw_afa_set_ht_params);
if (set) { if (set) {
set->ref_count++; refcount_inc(&set->ref_count);
mlxsw_afa_set_put(mlxsw_afa, orig_set); mlxsw_afa_set_put(mlxsw_afa, orig_set);
} else { } else {
set = orig_set; set = orig_set;
...@@ -564,7 +564,7 @@ mlxsw_afa_fwd_entry_create(struct mlxsw_afa *mlxsw_afa, u16 local_port) ...@@ -564,7 +564,7 @@ mlxsw_afa_fwd_entry_create(struct mlxsw_afa *mlxsw_afa, u16 local_port)
if (!fwd_entry) if (!fwd_entry)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
fwd_entry->ht_key.local_port = local_port; 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, err = rhashtable_insert_fast(&mlxsw_afa->fwd_entry_ht,
&fwd_entry->ht_node, &fwd_entry->ht_node,
...@@ -607,7 +607,7 @@ mlxsw_afa_fwd_entry_get(struct mlxsw_afa *mlxsw_afa, u16 local_port) ...@@ -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, fwd_entry = rhashtable_lookup_fast(&mlxsw_afa->fwd_entry_ht, &ht_key,
mlxsw_afa_fwd_entry_ht_params); mlxsw_afa_fwd_entry_ht_params);
if (fwd_entry) { if (fwd_entry) {
fwd_entry->ref_count++; refcount_inc(&fwd_entry->ref_count);
return fwd_entry; return fwd_entry;
} }
return mlxsw_afa_fwd_entry_create(mlxsw_afa, local_port); 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) ...@@ -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, static void mlxsw_afa_fwd_entry_put(struct mlxsw_afa *mlxsw_afa,
struct mlxsw_afa_fwd_entry *fwd_entry) struct mlxsw_afa_fwd_entry *fwd_entry)
{ {
if (--fwd_entry->ref_count) if (!refcount_dec_and_test(&fwd_entry->ref_count))
return; return;
mlxsw_afa_fwd_entry_destroy(mlxsw_afa, fwd_entry); mlxsw_afa_fwd_entry_destroy(mlxsw_afa, fwd_entry);
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/refcount.h>
#include "item.h" #include "item.h"
#include "core_acl_flex_keys.h" #include "core_acl_flex_keys.h"
...@@ -107,7 +108,7 @@ EXPORT_SYMBOL(mlxsw_afk_destroy); ...@@ -107,7 +108,7 @@ EXPORT_SYMBOL(mlxsw_afk_destroy);
struct mlxsw_afk_key_info { struct mlxsw_afk_key_info {
struct list_head list; struct list_head list;
unsigned int ref_count; refcount_t ref_count;
unsigned int blocks_count; unsigned int blocks_count;
int element_to_block[MLXSW_AFK_ELEMENT_MAX]; /* index is element, value int element_to_block[MLXSW_AFK_ELEMENT_MAX]; /* index is element, value
* is index inside "blocks" * is index inside "blocks"
...@@ -334,7 +335,7 @@ mlxsw_afk_key_info_create(struct mlxsw_afk *mlxsw_afk, ...@@ -334,7 +335,7 @@ mlxsw_afk_key_info_create(struct mlxsw_afk *mlxsw_afk,
if (err) if (err)
goto err_picker; goto err_picker;
list_add(&key_info->list, &mlxsw_afk->key_info_list); 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; return key_info;
err_picker: err_picker:
...@@ -356,7 +357,7 @@ mlxsw_afk_key_info_get(struct mlxsw_afk *mlxsw_afk, ...@@ -356,7 +357,7 @@ mlxsw_afk_key_info_get(struct mlxsw_afk *mlxsw_afk,
key_info = mlxsw_afk_key_info_find(mlxsw_afk, elusage); key_info = mlxsw_afk_key_info_find(mlxsw_afk, elusage);
if (key_info) { if (key_info) {
key_info->ref_count++; refcount_inc(&key_info->ref_count);
return key_info; return key_info;
} }
return mlxsw_afk_key_info_create(mlxsw_afk, elusage); return mlxsw_afk_key_info_create(mlxsw_afk, elusage);
...@@ -365,7 +366,7 @@ EXPORT_SYMBOL(mlxsw_afk_key_info_get); ...@@ -365,7 +366,7 @@ EXPORT_SYMBOL(mlxsw_afk_key_info_get);
void mlxsw_afk_key_info_put(struct mlxsw_afk_key_info *key_info) 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; return;
mlxsw_afk_key_info_destroy(key_info); mlxsw_afk_key_info_destroy(key_info);
} }
......
...@@ -2695,23 +2695,18 @@ static void mlxsw_sp_traps_fini(struct mlxsw_sp *mlxsw_sp) ...@@ -2695,23 +2695,18 @@ static void mlxsw_sp_traps_fini(struct mlxsw_sp *mlxsw_sp)
static int mlxsw_sp_lag_pgt_init(struct mlxsw_sp *mlxsw_sp) static int mlxsw_sp_lag_pgt_init(struct mlxsw_sp *mlxsw_sp)
{ {
char sgcr_pl[MLXSW_REG_SGCR_LEN]; char sgcr_pl[MLXSW_REG_SGCR_LEN];
u16 max_lag;
int err; int err;
if (mlxsw_core_lag_mode(mlxsw_sp->core) != if (mlxsw_core_lag_mode(mlxsw_sp->core) !=
MLXSW_CMD_MBOX_CONFIG_PROFILE_LAG_MODE_SW) MLXSW_CMD_MBOX_CONFIG_PROFILE_LAG_MODE_SW)
return 0; return 0;
err = mlxsw_core_max_lag(mlxsw_sp->core, &max_lag);
if (err)
return err;
/* In DDD mode, which we by default use, each LAG entry is 8 PGT /* In DDD mode, which we by default use, each LAG entry is 8 PGT
* entries. The LAG table address needs to be 8-aligned, but that ought * entries. The LAG table address needs to be 8-aligned, but that ought
* to be the case, since the LAG table is allocated first. * to be the case, since the LAG table is allocated first.
*/ */
err = mlxsw_sp_pgt_mid_alloc_range(mlxsw_sp, &mlxsw_sp->lag_pgt_base, err = mlxsw_sp_pgt_mid_alloc_range(mlxsw_sp, &mlxsw_sp->lag_pgt_base,
max_lag * 8); mlxsw_sp->max_lag * 8);
if (err) if (err)
return err; return err;
if (WARN_ON_ONCE(mlxsw_sp->lag_pgt_base % 8)) { if (WARN_ON_ONCE(mlxsw_sp->lag_pgt_base % 8)) {
...@@ -2728,33 +2723,31 @@ static int mlxsw_sp_lag_pgt_init(struct mlxsw_sp *mlxsw_sp) ...@@ -2728,33 +2723,31 @@ static int mlxsw_sp_lag_pgt_init(struct mlxsw_sp *mlxsw_sp)
err_mid_alloc_range: err_mid_alloc_range:
mlxsw_sp_pgt_mid_free_range(mlxsw_sp, mlxsw_sp->lag_pgt_base, mlxsw_sp_pgt_mid_free_range(mlxsw_sp, mlxsw_sp->lag_pgt_base,
max_lag * 8); mlxsw_sp->max_lag * 8);
return err; return err;
} }
static void mlxsw_sp_lag_pgt_fini(struct mlxsw_sp *mlxsw_sp) static void mlxsw_sp_lag_pgt_fini(struct mlxsw_sp *mlxsw_sp)
{ {
u16 max_lag;
int err;
if (mlxsw_core_lag_mode(mlxsw_sp->core) != if (mlxsw_core_lag_mode(mlxsw_sp->core) !=
MLXSW_CMD_MBOX_CONFIG_PROFILE_LAG_MODE_SW) MLXSW_CMD_MBOX_CONFIG_PROFILE_LAG_MODE_SW)
return; return;
err = mlxsw_core_max_lag(mlxsw_sp->core, &max_lag);
if (err)
return;
mlxsw_sp_pgt_mid_free_range(mlxsw_sp, mlxsw_sp->lag_pgt_base, mlxsw_sp_pgt_mid_free_range(mlxsw_sp, mlxsw_sp->lag_pgt_base,
max_lag * 8); mlxsw_sp->max_lag * 8);
} }
#define MLXSW_SP_LAG_SEED_INIT 0xcafecafe #define MLXSW_SP_LAG_SEED_INIT 0xcafecafe
struct mlxsw_sp_lag {
struct net_device *dev;
refcount_t ref_count;
u16 lag_id;
};
static int mlxsw_sp_lag_init(struct mlxsw_sp *mlxsw_sp) static int mlxsw_sp_lag_init(struct mlxsw_sp *mlxsw_sp)
{ {
char slcr_pl[MLXSW_REG_SLCR_LEN]; char slcr_pl[MLXSW_REG_SLCR_LEN];
u16 max_lag;
u32 seed; u32 seed;
int err; int err;
...@@ -2773,7 +2766,7 @@ static int mlxsw_sp_lag_init(struct mlxsw_sp *mlxsw_sp) ...@@ -2773,7 +2766,7 @@ static int mlxsw_sp_lag_init(struct mlxsw_sp *mlxsw_sp)
if (err) if (err)
return err; return err;
err = mlxsw_core_max_lag(mlxsw_sp->core, &max_lag); err = mlxsw_core_max_lag(mlxsw_sp->core, &mlxsw_sp->max_lag);
if (err) if (err)
return err; return err;
...@@ -2784,7 +2777,7 @@ static int mlxsw_sp_lag_init(struct mlxsw_sp *mlxsw_sp) ...@@ -2784,7 +2777,7 @@ static int mlxsw_sp_lag_init(struct mlxsw_sp *mlxsw_sp)
if (err) if (err)
return err; return err;
mlxsw_sp->lags = kcalloc(max_lag, sizeof(struct mlxsw_sp_upper), mlxsw_sp->lags = kcalloc(mlxsw_sp->max_lag, sizeof(struct mlxsw_sp_lag),
GFP_KERNEL); GFP_KERNEL);
if (!mlxsw_sp->lags) { if (!mlxsw_sp->lags) {
err = -ENOMEM; err = -ENOMEM;
...@@ -4269,19 +4262,48 @@ mlxsw_sp_port_lag_uppers_cleanup(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -4269,19 +4262,48 @@ mlxsw_sp_port_lag_uppers_cleanup(struct mlxsw_sp_port *mlxsw_sp_port,
} }
} }
static int mlxsw_sp_lag_create(struct mlxsw_sp *mlxsw_sp, u16 lag_id) static struct mlxsw_sp_lag *
mlxsw_sp_lag_create(struct mlxsw_sp *mlxsw_sp, struct net_device *lag_dev,
struct netlink_ext_ack *extack)
{ {
char sldr_pl[MLXSW_REG_SLDR_LEN]; char sldr_pl[MLXSW_REG_SLDR_LEN];
struct mlxsw_sp_lag *lag;
u16 lag_id;
int i, err;
for (i = 0; i < mlxsw_sp->max_lag; i++) {
if (!mlxsw_sp->lags[i].dev)
break;
}
if (i == mlxsw_sp->max_lag) {
NL_SET_ERR_MSG_MOD(extack,
"Exceeded number of supported LAG devices");
return ERR_PTR(-EBUSY);
}
lag_id = i;
mlxsw_reg_sldr_lag_create_pack(sldr_pl, lag_id); mlxsw_reg_sldr_lag_create_pack(sldr_pl, lag_id);
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sldr), sldr_pl); err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sldr), sldr_pl);
if (err)
return ERR_PTR(err);
lag = &mlxsw_sp->lags[lag_id];
lag->lag_id = lag_id;
lag->dev = lag_dev;
refcount_set(&lag->ref_count, 1);
return lag;
} }
static int mlxsw_sp_lag_destroy(struct mlxsw_sp *mlxsw_sp, u16 lag_id) static int
mlxsw_sp_lag_destroy(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_lag *lag)
{ {
char sldr_pl[MLXSW_REG_SLDR_LEN]; char sldr_pl[MLXSW_REG_SLDR_LEN];
mlxsw_reg_sldr_lag_destroy_pack(sldr_pl, lag_id); lag->dev = NULL;
mlxsw_reg_sldr_lag_destroy_pack(sldr_pl, lag->lag_id);
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sldr), sldr_pl); return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sldr), sldr_pl);
} }
...@@ -4329,34 +4351,44 @@ static int mlxsw_sp_lag_col_port_disable(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -4329,34 +4351,44 @@ static int mlxsw_sp_lag_col_port_disable(struct mlxsw_sp_port *mlxsw_sp_port,
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(slcor), slcor_pl); return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(slcor), slcor_pl);
} }
static int mlxsw_sp_lag_index_get(struct mlxsw_sp *mlxsw_sp, static struct mlxsw_sp_lag *
struct net_device *lag_dev, mlxsw_sp_lag_find(struct mlxsw_sp *mlxsw_sp, struct net_device *lag_dev)
u16 *p_lag_id)
{ {
struct mlxsw_sp_upper *lag; int i;
int free_lag_id = -1;
u16 max_lag;
int err, i;
err = mlxsw_core_max_lag(mlxsw_sp->core, &max_lag); for (i = 0; i < mlxsw_sp->max_lag; i++) {
if (err) if (!mlxsw_sp->lags[i].dev)
return err; continue;
for (i = 0; i < max_lag; i++) { if (mlxsw_sp->lags[i].dev == lag_dev)
lag = mlxsw_sp_lag_get(mlxsw_sp, i); return &mlxsw_sp->lags[i];
if (lag->ref_count) {
if (lag->dev == lag_dev) {
*p_lag_id = i;
return 0;
}
} else if (free_lag_id < 0) {
free_lag_id = i;
} }
return NULL;
}
static struct mlxsw_sp_lag *
mlxsw_sp_lag_get(struct mlxsw_sp *mlxsw_sp, struct net_device *lag_dev,
struct netlink_ext_ack *extack)
{
struct mlxsw_sp_lag *lag;
lag = mlxsw_sp_lag_find(mlxsw_sp, lag_dev);
if (lag) {
refcount_inc(&lag->ref_count);
return lag;
} }
if (free_lag_id < 0)
return -EBUSY; return mlxsw_sp_lag_create(mlxsw_sp, lag_dev, extack);
*p_lag_id = free_lag_id; }
return 0;
static void
mlxsw_sp_lag_put(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_lag *lag)
{
if (!refcount_dec_and_test(&lag->ref_count))
return;
mlxsw_sp_lag_destroy(mlxsw_sp, lag);
} }
static bool static bool
...@@ -4365,12 +4397,6 @@ mlxsw_sp_master_lag_check(struct mlxsw_sp *mlxsw_sp, ...@@ -4365,12 +4397,6 @@ mlxsw_sp_master_lag_check(struct mlxsw_sp *mlxsw_sp,
struct netdev_lag_upper_info *lag_upper_info, struct netdev_lag_upper_info *lag_upper_info,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
u16 lag_id;
if (mlxsw_sp_lag_index_get(mlxsw_sp, lag_dev, &lag_id) != 0) {
NL_SET_ERR_MSG_MOD(extack, "Exceeded number of supported LAG devices");
return false;
}
if (lag_upper_info->tx_type != NETDEV_LAG_TX_TYPE_HASH) { if (lag_upper_info->tx_type != NETDEV_LAG_TX_TYPE_HASH) {
NL_SET_ERR_MSG_MOD(extack, "LAG device using unsupported Tx type"); NL_SET_ERR_MSG_MOD(extack, "LAG device using unsupported Tx type");
return false; return false;
...@@ -4482,22 +4508,16 @@ static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -4482,22 +4508,16 @@ static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
struct mlxsw_sp_upper *lag; struct mlxsw_sp_lag *lag;
u16 lag_id; u16 lag_id;
u8 port_index; u8 port_index;
int err; int err;
err = mlxsw_sp_lag_index_get(mlxsw_sp, lag_dev, &lag_id); lag = mlxsw_sp_lag_get(mlxsw_sp, lag_dev, extack);
if (err) if (IS_ERR(lag))
return err; return PTR_ERR(lag);
lag = mlxsw_sp_lag_get(mlxsw_sp, lag_id);
if (!lag->ref_count) {
err = mlxsw_sp_lag_create(mlxsw_sp, lag_id);
if (err)
return err;
lag->dev = lag_dev;
}
lag_id = lag->lag_id;
err = mlxsw_sp_port_lag_index_get(mlxsw_sp, lag_id, &port_index); err = mlxsw_sp_port_lag_index_get(mlxsw_sp, lag_id, &port_index);
if (err) if (err)
return err; return err;
...@@ -4515,7 +4535,6 @@ static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -4515,7 +4535,6 @@ static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port,
mlxsw_sp_port->local_port); mlxsw_sp_port->local_port);
mlxsw_sp_port->lag_id = lag_id; mlxsw_sp_port->lag_id = lag_id;
mlxsw_sp_port->lagged = 1; mlxsw_sp_port->lagged = 1;
lag->ref_count++;
err = mlxsw_sp_fid_port_join_lag(mlxsw_sp_port); err = mlxsw_sp_fid_port_join_lag(mlxsw_sp_port);
if (err) if (err)
...@@ -4542,7 +4561,6 @@ static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -4542,7 +4561,6 @@ static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port,
err_router_join: err_router_join:
mlxsw_sp_fid_port_leave_lag(mlxsw_sp_port); mlxsw_sp_fid_port_leave_lag(mlxsw_sp_port);
err_fid_port_join_lag: err_fid_port_join_lag:
lag->ref_count--;
mlxsw_sp_port->lagged = 0; mlxsw_sp_port->lagged = 0;
mlxsw_core_lag_mapping_clear(mlxsw_sp->core, lag_id, mlxsw_core_lag_mapping_clear(mlxsw_sp->core, lag_id,
mlxsw_sp_port->local_port); mlxsw_sp_port->local_port);
...@@ -4550,8 +4568,7 @@ static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -4550,8 +4568,7 @@ static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port,
err_col_port_add: err_col_port_add:
mlxsw_sp_lag_uppers_bridge_leave(mlxsw_sp_port, lag_dev); mlxsw_sp_lag_uppers_bridge_leave(mlxsw_sp_port, lag_dev);
err_lag_uppers_bridge_join: err_lag_uppers_bridge_join:
if (!lag->ref_count) mlxsw_sp_lag_put(mlxsw_sp, lag);
mlxsw_sp_lag_destroy(mlxsw_sp, lag_id);
return err; return err;
} }
...@@ -4560,12 +4577,11 @@ static void mlxsw_sp_port_lag_leave(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -4560,12 +4577,11 @@ static void mlxsw_sp_port_lag_leave(struct mlxsw_sp_port *mlxsw_sp_port,
{ {
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
u16 lag_id = mlxsw_sp_port->lag_id; u16 lag_id = mlxsw_sp_port->lag_id;
struct mlxsw_sp_upper *lag; struct mlxsw_sp_lag *lag;
if (!mlxsw_sp_port->lagged) if (!mlxsw_sp_port->lagged)
return; return;
lag = mlxsw_sp_lag_get(mlxsw_sp, lag_id); lag = &mlxsw_sp->lags[lag_id];
WARN_ON(lag->ref_count == 0);
mlxsw_sp_lag_col_port_remove(mlxsw_sp_port, lag_id); mlxsw_sp_lag_col_port_remove(mlxsw_sp_port, lag_id);
...@@ -4579,13 +4595,11 @@ static void mlxsw_sp_port_lag_leave(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -4579,13 +4595,11 @@ static void mlxsw_sp_port_lag_leave(struct mlxsw_sp_port *mlxsw_sp_port,
mlxsw_sp_fid_port_leave_lag(mlxsw_sp_port); mlxsw_sp_fid_port_leave_lag(mlxsw_sp_port);
if (lag->ref_count == 1) mlxsw_sp_lag_put(mlxsw_sp, lag);
mlxsw_sp_lag_destroy(mlxsw_sp, lag_id);
mlxsw_core_lag_mapping_clear(mlxsw_sp->core, lag_id, mlxsw_core_lag_mapping_clear(mlxsw_sp->core, lag_id,
mlxsw_sp_port->local_port); mlxsw_sp_port->local_port);
mlxsw_sp_port->lagged = 0; mlxsw_sp_port->lagged = 0;
lag->ref_count--;
/* Make sure untagged frames are allowed to ingress */ /* Make sure untagged frames are allowed to ingress */
mlxsw_sp_port_pvid_set(mlxsw_sp_port, MLXSW_SP_DEFAULT_VID, mlxsw_sp_port_pvid_set(mlxsw_sp_port, MLXSW_SP_DEFAULT_VID,
......
...@@ -78,11 +78,6 @@ struct mlxsw_sp_span_entry; ...@@ -78,11 +78,6 @@ struct mlxsw_sp_span_entry;
enum mlxsw_sp_l3proto; enum mlxsw_sp_l3proto;
union mlxsw_sp_l3addr; union mlxsw_sp_l3addr;
struct mlxsw_sp_upper {
struct net_device *dev;
unsigned int ref_count;
};
enum mlxsw_sp_rif_type { enum mlxsw_sp_rif_type {
MLXSW_SP_RIF_TYPE_SUBPORT, MLXSW_SP_RIF_TYPE_SUBPORT,
MLXSW_SP_RIF_TYPE_VLAN, MLXSW_SP_RIF_TYPE_VLAN,
...@@ -136,6 +131,7 @@ struct mlxsw_sp_span_ops; ...@@ -136,6 +131,7 @@ struct mlxsw_sp_span_ops;
struct mlxsw_sp_qdisc_state; struct mlxsw_sp_qdisc_state;
struct mlxsw_sp_mall_entry; struct mlxsw_sp_mall_entry;
struct mlxsw_sp_pgt; struct mlxsw_sp_pgt;
struct mlxsw_sp_lag;
struct mlxsw_sp_port_mapping { struct mlxsw_sp_port_mapping {
u8 module; u8 module;
...@@ -164,7 +160,8 @@ struct mlxsw_sp { ...@@ -164,7 +160,8 @@ struct mlxsw_sp {
const struct mlxsw_bus_info *bus_info; const struct mlxsw_bus_info *bus_info;
unsigned char base_mac[ETH_ALEN]; unsigned char base_mac[ETH_ALEN];
const unsigned char *mac_mask; const unsigned char *mac_mask;
struct mlxsw_sp_upper *lags; struct mlxsw_sp_lag *lags;
u16 max_lag;
struct mlxsw_sp_port_mapping *port_mapping; struct mlxsw_sp_port_mapping *port_mapping;
struct mlxsw_sp_port_mapping_events port_mapping_events; struct mlxsw_sp_port_mapping_events port_mapping_events;
struct rhashtable sample_trigger_ht; struct rhashtable sample_trigger_ht;
...@@ -257,12 +254,6 @@ struct mlxsw_sp_fid_core_ops { ...@@ -257,12 +254,6 @@ struct mlxsw_sp_fid_core_ops {
void (*fini)(struct mlxsw_sp *mlxsw_sp); void (*fini)(struct mlxsw_sp *mlxsw_sp);
}; };
static inline struct mlxsw_sp_upper *
mlxsw_sp_lag_get(struct mlxsw_sp *mlxsw_sp, u16 lag_id)
{
return &mlxsw_sp->lags[lag_id];
}
struct mlxsw_sp_port_pcpu_stats { struct mlxsw_sp_port_pcpu_stats {
u64 rx_packets; u64 rx_packets;
u64 rx_bytes; u64 rx_bytes;
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <linux/rhashtable.h> #include <linux/rhashtable.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/refcount.h>
#include <net/net_namespace.h> #include <net/net_namespace.h>
#include <net/tc_act/tc_vlan.h> #include <net/tc_act/tc_vlan.h>
...@@ -55,7 +56,7 @@ struct mlxsw_sp_acl_ruleset { ...@@ -55,7 +56,7 @@ struct mlxsw_sp_acl_ruleset {
struct rhash_head ht_node; /* Member of acl HT */ struct rhash_head ht_node; /* Member of acl HT */
struct mlxsw_sp_acl_ruleset_ht_key ht_key; struct mlxsw_sp_acl_ruleset_ht_key ht_key;
struct rhashtable rule_ht; struct rhashtable rule_ht;
unsigned int ref_count; refcount_t ref_count;
unsigned int min_prio; unsigned int min_prio;
unsigned int max_prio; unsigned int max_prio;
unsigned long priv[]; unsigned long priv[];
...@@ -99,7 +100,7 @@ static bool ...@@ -99,7 +100,7 @@ static bool
mlxsw_sp_acl_ruleset_is_singular(const struct mlxsw_sp_acl_ruleset *ruleset) mlxsw_sp_acl_ruleset_is_singular(const struct mlxsw_sp_acl_ruleset *ruleset)
{ {
/* We hold a reference on ruleset ourselves */ /* 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, 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, ...@@ -176,7 +177,7 @@ mlxsw_sp_acl_ruleset_create(struct mlxsw_sp *mlxsw_sp,
ruleset = kzalloc(alloc_size, GFP_KERNEL); ruleset = kzalloc(alloc_size, GFP_KERNEL);
if (!ruleset) if (!ruleset)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
ruleset->ref_count = 1; refcount_set(&ruleset->ref_count, 1);
ruleset->ht_key.block = block; ruleset->ht_key.block = block;
ruleset->ht_key.chain_index = chain_index; ruleset->ht_key.chain_index = chain_index;
ruleset->ht_key.ops = ops; ruleset->ht_key.ops = ops;
...@@ -222,13 +223,13 @@ static void mlxsw_sp_acl_ruleset_destroy(struct mlxsw_sp *mlxsw_sp, ...@@ -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) 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, static void mlxsw_sp_acl_ruleset_ref_dec(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_ruleset *ruleset) struct mlxsw_sp_acl_ruleset *ruleset)
{ {
if (--ruleset->ref_count) if (!refcount_dec_and_test(&ruleset->ref_count))
return; return;
mlxsw_sp_acl_ruleset_destroy(mlxsw_sp, ruleset); mlxsw_sp_acl_ruleset_destroy(mlxsw_sp, ruleset);
} }
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <linux/rhashtable.h> #include <linux/rhashtable.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/refcount.h>
#include <net/devlink.h> #include <net/devlink.h>
#include <trace/events/mlxsw.h> #include <trace/events/mlxsw.h>
...@@ -155,7 +156,7 @@ struct mlxsw_sp_acl_tcam_vregion { ...@@ -155,7 +156,7 @@ struct mlxsw_sp_acl_tcam_vregion {
struct mlxsw_sp_acl_tcam_rehash_ctx ctx; struct mlxsw_sp_acl_tcam_rehash_ctx ctx;
} rehash; } rehash;
struct mlxsw_sp *mlxsw_sp; struct mlxsw_sp *mlxsw_sp;
unsigned int ref_count; refcount_t ref_count;
}; };
struct mlxsw_sp_acl_tcam_vchunk; struct mlxsw_sp_acl_tcam_vchunk;
...@@ -176,7 +177,7 @@ 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 */ unsigned int priority; /* Priority within the vregion and group */
struct mlxsw_sp_acl_tcam_vgroup *vgroup; struct mlxsw_sp_acl_tcam_vgroup *vgroup;
struct mlxsw_sp_acl_tcam_vregion *vregion; struct mlxsw_sp_acl_tcam_vregion *vregion;
unsigned int ref_count; refcount_t ref_count;
}; };
struct mlxsw_sp_acl_tcam_entry { struct mlxsw_sp_acl_tcam_entry {
...@@ -769,7 +770,7 @@ mlxsw_sp_acl_tcam_vregion_create(struct mlxsw_sp *mlxsw_sp, ...@@ -769,7 +770,7 @@ mlxsw_sp_acl_tcam_vregion_create(struct mlxsw_sp *mlxsw_sp,
vregion->tcam = tcam; vregion->tcam = tcam;
vregion->mlxsw_sp = mlxsw_sp; vregion->mlxsw_sp = mlxsw_sp;
vregion->vgroup = vgroup; vregion->vgroup = vgroup;
vregion->ref_count = 1; refcount_set(&vregion->ref_count, 1);
vregion->key_info = mlxsw_afk_key_info_get(afk, elusage); vregion->key_info = mlxsw_afk_key_info_get(afk, elusage);
if (IS_ERR(vregion->key_info)) { if (IS_ERR(vregion->key_info)) {
...@@ -856,7 +857,7 @@ mlxsw_sp_acl_tcam_vregion_get(struct mlxsw_sp *mlxsw_sp, ...@@ -856,7 +857,7 @@ mlxsw_sp_acl_tcam_vregion_get(struct mlxsw_sp *mlxsw_sp,
*/ */
return ERR_PTR(-EOPNOTSUPP); return ERR_PTR(-EOPNOTSUPP);
} }
vregion->ref_count++; refcount_inc(&vregion->ref_count);
return vregion; return vregion;
} }
...@@ -871,7 +872,7 @@ static void ...@@ -871,7 +872,7 @@ static void
mlxsw_sp_acl_tcam_vregion_put(struct mlxsw_sp *mlxsw_sp, mlxsw_sp_acl_tcam_vregion_put(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_tcam_vregion *vregion) struct mlxsw_sp_acl_tcam_vregion *vregion)
{ {
if (--vregion->ref_count) if (!refcount_dec_and_test(&vregion->ref_count))
return; return;
mlxsw_sp_acl_tcam_vregion_destroy(mlxsw_sp, vregion); mlxsw_sp_acl_tcam_vregion_destroy(mlxsw_sp, vregion);
} }
...@@ -924,7 +925,7 @@ mlxsw_sp_acl_tcam_vchunk_create(struct mlxsw_sp *mlxsw_sp, ...@@ -924,7 +925,7 @@ mlxsw_sp_acl_tcam_vchunk_create(struct mlxsw_sp *mlxsw_sp,
INIT_LIST_HEAD(&vchunk->ventry_list); INIT_LIST_HEAD(&vchunk->ventry_list);
vchunk->priority = priority; vchunk->priority = priority;
vchunk->vgroup = vgroup; vchunk->vgroup = vgroup;
vchunk->ref_count = 1; refcount_set(&vchunk->ref_count, 1);
vregion = mlxsw_sp_acl_tcam_vregion_get(mlxsw_sp, vgroup, vregion = mlxsw_sp_acl_tcam_vregion_get(mlxsw_sp, vgroup,
priority, elusage); priority, elusage);
...@@ -1008,7 +1009,7 @@ mlxsw_sp_acl_tcam_vchunk_get(struct mlxsw_sp *mlxsw_sp, ...@@ -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, if (WARN_ON(!mlxsw_afk_key_info_subset(vchunk->vregion->key_info,
elusage))) elusage)))
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
vchunk->ref_count++; refcount_inc(&vchunk->ref_count);
return vchunk; return vchunk;
} }
return mlxsw_sp_acl_tcam_vchunk_create(mlxsw_sp, vgroup, return mlxsw_sp_acl_tcam_vchunk_create(mlxsw_sp, vgroup,
...@@ -1019,7 +1020,7 @@ static void ...@@ -1019,7 +1020,7 @@ static void
mlxsw_sp_acl_tcam_vchunk_put(struct mlxsw_sp *mlxsw_sp, mlxsw_sp_acl_tcam_vchunk_put(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_tcam_vchunk *vchunk) struct mlxsw_sp_acl_tcam_vchunk *vchunk)
{ {
if (--vchunk->ref_count) if (!refcount_dec_and_test(&vchunk->ref_count))
return; return;
mlxsw_sp_acl_tcam_vchunk_destroy(mlxsw_sp, vchunk); mlxsw_sp_acl_tcam_vchunk_destroy(mlxsw_sp, vchunk);
} }
......
...@@ -501,7 +501,7 @@ struct mlxsw_sp_rt6 { ...@@ -501,7 +501,7 @@ struct mlxsw_sp_rt6 {
struct mlxsw_sp_lpm_tree { struct mlxsw_sp_lpm_tree {
u8 id; /* tree ID */ u8 id; /* tree ID */
unsigned int ref_count; refcount_t ref_count;
enum mlxsw_sp_l3proto proto; enum mlxsw_sp_l3proto proto;
unsigned long prefix_ref_count[MLXSW_SP_PREFIX_COUNT]; unsigned long prefix_ref_count[MLXSW_SP_PREFIX_COUNT];
struct mlxsw_sp_prefix_usage prefix_usage; struct mlxsw_sp_prefix_usage prefix_usage;
...@@ -578,7 +578,7 @@ mlxsw_sp_lpm_tree_find_unused(struct mlxsw_sp *mlxsw_sp) ...@@ -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++) { for (i = 0; i < mlxsw_sp->router->lpm.tree_count; i++) {
lpm_tree = &mlxsw_sp->router->lpm.trees[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 lpm_tree;
} }
return NULL; return NULL;
...@@ -654,7 +654,7 @@ mlxsw_sp_lpm_tree_create(struct mlxsw_sp *mlxsw_sp, ...@@ -654,7 +654,7 @@ mlxsw_sp_lpm_tree_create(struct mlxsw_sp *mlxsw_sp,
sizeof(lpm_tree->prefix_usage)); sizeof(lpm_tree->prefix_usage));
memset(&lpm_tree->prefix_ref_count, 0, memset(&lpm_tree->prefix_ref_count, 0,
sizeof(lpm_tree->prefix_ref_count)); sizeof(lpm_tree->prefix_ref_count));
lpm_tree->ref_count = 1; refcount_set(&lpm_tree->ref_count, 1);
return lpm_tree; return lpm_tree;
err_left_struct_set: err_left_struct_set:
...@@ -678,7 +678,7 @@ mlxsw_sp_lpm_tree_get(struct mlxsw_sp *mlxsw_sp, ...@@ -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++) { for (i = 0; i < mlxsw_sp->router->lpm.tree_count; i++) {
lpm_tree = &mlxsw_sp->router->lpm.trees[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 && lpm_tree->proto == proto &&
mlxsw_sp_prefix_usage_eq(&lpm_tree->prefix_usage, mlxsw_sp_prefix_usage_eq(&lpm_tree->prefix_usage,
prefix_usage)) { prefix_usage)) {
...@@ -691,13 +691,14 @@ mlxsw_sp_lpm_tree_get(struct mlxsw_sp *mlxsw_sp, ...@@ -691,13 +691,14 @@ mlxsw_sp_lpm_tree_get(struct mlxsw_sp *mlxsw_sp,
static void mlxsw_sp_lpm_tree_hold(struct mlxsw_sp_lpm_tree *lpm_tree) 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, static void mlxsw_sp_lpm_tree_put(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_lpm_tree *lpm_tree) struct mlxsw_sp_lpm_tree *lpm_tree)
{ {
if (--lpm_tree->ref_count == 0) if (!refcount_dec_and_test(&lpm_tree->ref_count))
return;
mlxsw_sp_lpm_tree_destroy(mlxsw_sp, lpm_tree); mlxsw_sp_lpm_tree_destroy(mlxsw_sp, lpm_tree);
} }
......
...@@ -61,7 +61,7 @@ struct mlxsw_sp_bridge_port { ...@@ -61,7 +61,7 @@ struct mlxsw_sp_bridge_port {
struct mlxsw_sp_bridge_device *bridge_device; struct mlxsw_sp_bridge_device *bridge_device;
struct list_head list; struct list_head list;
struct list_head vlans_list; struct list_head vlans_list;
unsigned int ref_count; refcount_t ref_count;
u8 stp_state; u8 stp_state;
unsigned long flags; unsigned long flags;
bool mrouter; bool mrouter;
...@@ -495,7 +495,7 @@ mlxsw_sp_bridge_port_create(struct mlxsw_sp_bridge_device *bridge_device, ...@@ -495,7 +495,7 @@ mlxsw_sp_bridge_port_create(struct mlxsw_sp_bridge_device *bridge_device,
BR_MCAST_FLOOD; BR_MCAST_FLOOD;
INIT_LIST_HEAD(&bridge_port->vlans_list); INIT_LIST_HEAD(&bridge_port->vlans_list);
list_add(&bridge_port->list, &bridge_device->ports_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, err = switchdev_bridge_port_offload(brport_dev, mlxsw_sp_port->dev,
NULL, NULL, NULL, false, extack); NULL, NULL, NULL, false, extack);
...@@ -531,7 +531,7 @@ mlxsw_sp_bridge_port_get(struct mlxsw_sp_bridge *bridge, ...@@ -531,7 +531,7 @@ mlxsw_sp_bridge_port_get(struct mlxsw_sp_bridge *bridge,
bridge_port = mlxsw_sp_bridge_port_find(bridge, brport_dev); bridge_port = mlxsw_sp_bridge_port_find(bridge, brport_dev);
if (bridge_port) { if (bridge_port) {
bridge_port->ref_count++; refcount_inc(&bridge_port->ref_count);
return bridge_port; return bridge_port;
} }
...@@ -558,7 +558,7 @@ static void mlxsw_sp_bridge_port_put(struct mlxsw_sp_bridge *bridge, ...@@ -558,7 +558,7 @@ static void mlxsw_sp_bridge_port_put(struct mlxsw_sp_bridge *bridge,
{ {
struct mlxsw_sp_bridge_device *bridge_device; struct mlxsw_sp_bridge_device *bridge_device;
if (--bridge_port->ref_count != 0) if (!refcount_dec_and_test(&bridge_port->ref_count))
return; return;
bridge_device = bridge_port->bridge_device; bridge_device = bridge_port->bridge_device;
mlxsw_sp_bridge_port_destroy(bridge_port); mlxsw_sp_bridge_port_destroy(bridge_port);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment