mlxsw: spectrum_trap: Store all trap policer data in one array
Instead of maintaining an array of policers and a linked list, only maintain an array. Signed-off-by: Ido Schimmel <idosch@mellanox.com> Reviewed-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
85d4ec5925
commit
cc678f4dbc
@ -13,9 +13,8 @@
|
|||||||
#include "spectrum_trap.h"
|
#include "spectrum_trap.h"
|
||||||
|
|
||||||
struct mlxsw_sp_trap_policer_item {
|
struct mlxsw_sp_trap_policer_item {
|
||||||
|
struct devlink_trap_policer policer;
|
||||||
u16 hw_id;
|
u16 hw_id;
|
||||||
u32 id;
|
|
||||||
struct list_head list; /* Member of policer_item_list */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* All driver-specific traps must be documented in
|
/* All driver-specific traps must be documented in
|
||||||
@ -182,8 +181,11 @@ static void mlxsw_sp_rx_exception_listener(struct sk_buff *skb, u8 local_port,
|
|||||||
1 << MLXSW_REG_QPCR_LOWEST_CBS)
|
1 << MLXSW_REG_QPCR_LOWEST_CBS)
|
||||||
|
|
||||||
/* Ordered by policer identifier */
|
/* Ordered by policer identifier */
|
||||||
static const struct devlink_trap_policer mlxsw_sp_trap_policers_arr[] = {
|
static const struct mlxsw_sp_trap_policer_item
|
||||||
MLXSW_SP_TRAP_POLICER(1, 10 * 1024, 128),
|
mlxsw_sp_trap_policer_items_arr[] = {
|
||||||
|
{
|
||||||
|
.policer = MLXSW_SP_TRAP_POLICER(1, 10 * 1024, 128),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct devlink_trap_group mlxsw_sp_trap_groups_arr[] = {
|
static const struct devlink_trap_group mlxsw_sp_trap_groups_arr[] = {
|
||||||
@ -319,12 +321,12 @@ static const u16 mlxsw_sp_listener_devlink_map[] = {
|
|||||||
static struct mlxsw_sp_trap_policer_item *
|
static struct mlxsw_sp_trap_policer_item *
|
||||||
mlxsw_sp_trap_policer_item_lookup(struct mlxsw_sp *mlxsw_sp, u32 id)
|
mlxsw_sp_trap_policer_item_lookup(struct mlxsw_sp *mlxsw_sp, u32 id)
|
||||||
{
|
{
|
||||||
struct mlxsw_sp_trap_policer_item *policer_item;
|
|
||||||
struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
|
struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
|
||||||
|
int i;
|
||||||
|
|
||||||
list_for_each_entry(policer_item, &trap->policer_item_list, list) {
|
for (i = 0; i < trap->policers_count; i++) {
|
||||||
if (policer_item->id == id)
|
if (trap->policer_items_arr[i].policer.id == id)
|
||||||
return policer_item;
|
return &trap->policer_items_arr[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -352,72 +354,102 @@ static int mlxsw_sp_trap_dummy_group_init(struct mlxsw_sp *mlxsw_sp)
|
|||||||
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(htgt), htgt_pl);
|
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(htgt), htgt_pl);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mlxsw_sp_trap_policers_init(struct mlxsw_sp *mlxsw_sp)
|
static int mlxsw_sp_trap_policer_items_arr_init(struct mlxsw_sp *mlxsw_sp)
|
||||||
{
|
{
|
||||||
struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
|
size_t elem_size = sizeof(struct mlxsw_sp_trap_policer_item);
|
||||||
|
u64 arr_size = ARRAY_SIZE(mlxsw_sp_trap_policer_items_arr);
|
||||||
struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
|
struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
|
||||||
u64 free_policers = 0;
|
u64 free_policers = 0;
|
||||||
u32 last_id = 0;
|
u32 last_id;
|
||||||
int err, i;
|
int i;
|
||||||
|
|
||||||
for_each_clear_bit(i, trap->policers_usage, trap->max_policers)
|
for_each_clear_bit(i, trap->policers_usage, trap->max_policers)
|
||||||
free_policers++;
|
free_policers++;
|
||||||
|
|
||||||
if (ARRAY_SIZE(mlxsw_sp_trap_policers_arr) > free_policers) {
|
if (arr_size > free_policers) {
|
||||||
dev_err(mlxsw_sp->bus_info->dev, "Exceeded number of supported packet trap policers\n");
|
dev_err(mlxsw_sp->bus_info->dev, "Exceeded number of supported packet trap policers\n");
|
||||||
return -ENOBUFS;
|
return -ENOBUFS;
|
||||||
}
|
}
|
||||||
|
|
||||||
trap->policers_arr = kcalloc(free_policers,
|
trap->policer_items_arr = kcalloc(free_policers, elem_size, GFP_KERNEL);
|
||||||
sizeof(struct devlink_trap_policer),
|
if (!trap->policer_items_arr)
|
||||||
GFP_KERNEL);
|
|
||||||
if (!trap->policers_arr)
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
trap->policers_count = free_policers;
|
trap->policers_count = free_policers;
|
||||||
|
|
||||||
for (i = 0; i < free_policers; i++) {
|
/* Initialize policer items array with pre-defined policers. */
|
||||||
const struct devlink_trap_policer *policer;
|
memcpy(trap->policer_items_arr, mlxsw_sp_trap_policer_items_arr,
|
||||||
|
elem_size * arr_size);
|
||||||
|
|
||||||
if (i < ARRAY_SIZE(mlxsw_sp_trap_policers_arr)) {
|
/* Initialize policer items array with the rest of the available
|
||||||
policer = &mlxsw_sp_trap_policers_arr[i];
|
* policers.
|
||||||
trap->policers_arr[i] = *policer;
|
*/
|
||||||
last_id = policer->id;
|
last_id = mlxsw_sp_trap_policer_items_arr[arr_size - 1].policer.id;
|
||||||
} else {
|
for (i = arr_size; i < trap->policers_count; i++) {
|
||||||
/* Use parameters set for first policer and override
|
const struct mlxsw_sp_trap_policer_item *policer_item;
|
||||||
* relevant ones.
|
|
||||||
*/
|
/* Use parameters set for first policer and override
|
||||||
policer = &mlxsw_sp_trap_policers_arr[0];
|
* relevant ones.
|
||||||
trap->policers_arr[i] = *policer;
|
*/
|
||||||
trap->policers_arr[i].id = ++last_id;
|
policer_item = &mlxsw_sp_trap_policer_items_arr[0];
|
||||||
trap->policers_arr[i].init_rate = 1;
|
trap->policer_items_arr[i] = *policer_item;
|
||||||
trap->policers_arr[i].init_burst = 16;
|
trap->policer_items_arr[i].policer.id = ++last_id;
|
||||||
}
|
trap->policer_items_arr[i].policer.init_rate = 1;
|
||||||
|
trap->policer_items_arr[i].policer.init_burst = 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
INIT_LIST_HEAD(&trap->policer_item_list);
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
err = devlink_trap_policers_register(devlink, trap->policers_arr,
|
static void mlxsw_sp_trap_policer_items_arr_fini(struct mlxsw_sp *mlxsw_sp)
|
||||||
trap->policers_count);
|
{
|
||||||
|
kfree(mlxsw_sp->trap->policer_items_arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mlxsw_sp_trap_policers_init(struct mlxsw_sp *mlxsw_sp)
|
||||||
|
{
|
||||||
|
struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
|
||||||
|
const struct mlxsw_sp_trap_policer_item *policer_item;
|
||||||
|
struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
|
||||||
|
int err, i;
|
||||||
|
|
||||||
|
err = mlxsw_sp_trap_policer_items_arr_init(mlxsw_sp);
|
||||||
if (err)
|
if (err)
|
||||||
goto err_trap_policers_register;
|
return err;
|
||||||
|
|
||||||
|
for (i = 0; i < trap->policers_count; i++) {
|
||||||
|
policer_item = &trap->policer_items_arr[i];
|
||||||
|
err = devlink_trap_policers_register(devlink,
|
||||||
|
&policer_item->policer, 1);
|
||||||
|
if (err)
|
||||||
|
goto err_trap_policer_register;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_trap_policers_register:
|
err_trap_policer_register:
|
||||||
kfree(trap->policers_arr);
|
for (i--; i >= 0; i--) {
|
||||||
|
policer_item = &trap->policer_items_arr[i];
|
||||||
|
devlink_trap_policers_unregister(devlink,
|
||||||
|
&policer_item->policer, 1);
|
||||||
|
}
|
||||||
|
mlxsw_sp_trap_policer_items_arr_fini(mlxsw_sp);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mlxsw_sp_trap_policers_fini(struct mlxsw_sp *mlxsw_sp)
|
static void mlxsw_sp_trap_policers_fini(struct mlxsw_sp *mlxsw_sp)
|
||||||
{
|
{
|
||||||
struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
|
struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
|
||||||
|
const struct mlxsw_sp_trap_policer_item *policer_item;
|
||||||
struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
|
struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
|
||||||
|
int i;
|
||||||
|
|
||||||
devlink_trap_policers_unregister(devlink, trap->policers_arr,
|
for (i = trap->policers_count - 1; i >= 0; i--) {
|
||||||
trap->policers_count);
|
policer_item = &trap->policer_items_arr[i];
|
||||||
WARN_ON(!list_empty(&trap->policer_item_list));
|
devlink_trap_policers_unregister(devlink,
|
||||||
kfree(trap->policers_arr);
|
&policer_item->policer, 1);
|
||||||
|
}
|
||||||
|
mlxsw_sp_trap_policer_items_arr_fini(mlxsw_sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mlxsw_sp_devlink_traps_init(struct mlxsw_sp *mlxsw_sp)
|
int mlxsw_sp_devlink_traps_init(struct mlxsw_sp *mlxsw_sp)
|
||||||
@ -608,10 +640,10 @@ int mlxsw_sp_trap_group_set(struct mlxsw_core *mlxsw_core,
|
|||||||
return __mlxsw_sp_trap_group_init(mlxsw_core, group, policer_id);
|
return __mlxsw_sp_trap_group_init(mlxsw_core, group, policer_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct mlxsw_sp_trap_policer_item *
|
static int
|
||||||
mlxsw_sp_trap_policer_item_init(struct mlxsw_sp *mlxsw_sp, u32 id)
|
mlxsw_sp_trap_policer_item_init(struct mlxsw_sp *mlxsw_sp,
|
||||||
|
struct mlxsw_sp_trap_policer_item *policer_item)
|
||||||
{
|
{
|
||||||
struct mlxsw_sp_trap_policer_item *policer_item;
|
|
||||||
struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
|
struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
|
||||||
u16 hw_id;
|
u16 hw_id;
|
||||||
|
|
||||||
@ -621,27 +653,19 @@ mlxsw_sp_trap_policer_item_init(struct mlxsw_sp *mlxsw_sp, u32 id)
|
|||||||
*/
|
*/
|
||||||
hw_id = find_first_zero_bit(trap->policers_usage, trap->max_policers);
|
hw_id = find_first_zero_bit(trap->policers_usage, trap->max_policers);
|
||||||
if (WARN_ON(hw_id == trap->max_policers))
|
if (WARN_ON(hw_id == trap->max_policers))
|
||||||
return ERR_PTR(-ENOBUFS);
|
return -ENOBUFS;
|
||||||
|
|
||||||
policer_item = kzalloc(sizeof(*policer_item), GFP_KERNEL);
|
|
||||||
if (!policer_item)
|
|
||||||
return ERR_PTR(-ENOMEM);
|
|
||||||
|
|
||||||
__set_bit(hw_id, trap->policers_usage);
|
__set_bit(hw_id, trap->policers_usage);
|
||||||
policer_item->hw_id = hw_id;
|
policer_item->hw_id = hw_id;
|
||||||
policer_item->id = id;
|
|
||||||
list_add_tail(&policer_item->list, &trap->policer_item_list);
|
|
||||||
|
|
||||||
return policer_item;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mlxsw_sp_trap_policer_item_fini(struct mlxsw_sp *mlxsw_sp,
|
mlxsw_sp_trap_policer_item_fini(struct mlxsw_sp *mlxsw_sp,
|
||||||
struct mlxsw_sp_trap_policer_item *policer_item)
|
struct mlxsw_sp_trap_policer_item *policer_item)
|
||||||
{
|
{
|
||||||
list_del(&policer_item->list);
|
|
||||||
__clear_bit(policer_item->hw_id, mlxsw_sp->trap->policers_usage);
|
__clear_bit(policer_item->hw_id, mlxsw_sp->trap->policers_usage);
|
||||||
kfree(policer_item);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mlxsw_sp_trap_policer_bs(u64 burst, u8 *p_burst_size,
|
static int mlxsw_sp_trap_policer_bs(u64 burst, u8 *p_burst_size,
|
||||||
@ -684,9 +708,13 @@ int mlxsw_sp_trap_policer_init(struct mlxsw_core *mlxsw_core,
|
|||||||
struct mlxsw_sp_trap_policer_item *policer_item;
|
struct mlxsw_sp_trap_policer_item *policer_item;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
policer_item = mlxsw_sp_trap_policer_item_init(mlxsw_sp, policer->id);
|
policer_item = mlxsw_sp_trap_policer_item_lookup(mlxsw_sp, policer->id);
|
||||||
if (IS_ERR(policer_item))
|
if (WARN_ON(!policer_item))
|
||||||
return PTR_ERR(policer_item);
|
return -EINVAL;
|
||||||
|
|
||||||
|
err = mlxsw_sp_trap_policer_item_init(mlxsw_sp, policer_item);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
err = __mlxsw_sp_trap_policer_set(mlxsw_sp, policer_item->hw_id,
|
err = __mlxsw_sp_trap_policer_set(mlxsw_sp, policer_item->hw_id,
|
||||||
policer->init_rate,
|
policer->init_rate,
|
||||||
|
@ -8,9 +8,8 @@
|
|||||||
#include <net/devlink.h>
|
#include <net/devlink.h>
|
||||||
|
|
||||||
struct mlxsw_sp_trap {
|
struct mlxsw_sp_trap {
|
||||||
struct devlink_trap_policer *policers_arr; /* Registered policers */
|
struct mlxsw_sp_trap_policer_item *policer_items_arr;
|
||||||
u64 policers_count; /* Number of registered policers */
|
u64 policers_count; /* Number of registered policers */
|
||||||
struct list_head policer_item_list;
|
|
||||||
u64 max_policers;
|
u64 max_policers;
|
||||||
unsigned long policers_usage[]; /* Usage bitmap */
|
unsigned long policers_usage[]; /* Usage bitmap */
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user