Commit bf038f03 authored by Ido Schimmel's avatar Ido Schimmel Committed by Jakub Kicinski
Browse files

mlxsw: spectrum_policer: Add devlink resource support



Expose via devlink-resource the maximum number of single-rate policers
and their current occupancy. Example:

$ devlink resource show pci/0000:01:00.0
...
  name global_policers size 1000 unit entry dpipe_tables none
    resources:
      name single_rate_policers size 968 occ 0 unit entry dpipe_tables none

Signed-off-by: default avatarIdo Schimmel <idosch@mellanox.com>
Reviewed-by: default avatarJiri Pirko <jiri@mellanox.com>
Reviewed-by: default avatarPetr Machata <petrm@mellanox.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 8d3fbae7
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -3352,6 +3352,10 @@ static int mlxsw_sp1_resources_register(struct mlxsw_core *mlxsw_core)
	if (err)
		goto err_resources_counter_register;

	err = mlxsw_sp_policer_resources_register(mlxsw_core);
	if (err)
		goto err_resources_counter_register;

	return 0;

err_resources_counter_register:
@@ -3376,6 +3380,10 @@ static int mlxsw_sp2_resources_register(struct mlxsw_core *mlxsw_core)
	if (err)
		goto err_resources_counter_register;

	err = mlxsw_sp_policer_resources_register(mlxsw_core);
	if (err)
		goto err_resources_counter_register;

	return 0;

err_resources_counter_register:
+3 −0
Original line number Diff line number Diff line
@@ -62,6 +62,8 @@ enum mlxsw_sp_resource_id {
	MLXSW_SP_RESOURCE_COUNTERS,
	MLXSW_SP_RESOURCE_COUNTERS_FLOW,
	MLXSW_SP_RESOURCE_COUNTERS_RIF,
	MLXSW_SP_RESOURCE_GLOBAL_POLICERS,
	MLXSW_SP_RESOURCE_SINGLE_RATE_POLICERS,
};

struct mlxsw_sp_port;
@@ -1227,5 +1229,6 @@ int mlxsw_sp_policer_drops_counter_get(struct mlxsw_sp *mlxsw_sp,
				       u16 policer_index, u64 *p_drops);
int mlxsw_sp_policers_init(struct mlxsw_sp *mlxsw_sp);
void mlxsw_sp_policers_fini(struct mlxsw_sp *mlxsw_sp);
int mlxsw_sp_policer_resources_register(struct mlxsw_core *mlxsw_core);

#endif
+65 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
#include <linux/log2.h>
#include <linux/mutex.h>
#include <linux/netlink.h>
#include <net/devlink.h>

#include "spectrum.h"

@@ -16,6 +17,7 @@ struct mlxsw_sp_policer_family {
	u16 end_index; /* Exclusive */
	struct idr policer_idr;
	struct mutex lock; /* Protects policer_idr */
	atomic_t policers_count;
	const struct mlxsw_sp_policer_family_ops *ops;
};

@@ -67,10 +69,18 @@ static u8 mlxsw_sp_policer_burst_bytes_hw_units(u64 burst_bytes)
	return fls64(bs512) - 1;
}

static u64 mlxsw_sp_policer_single_rate_occ_get(void *priv)
{
	struct mlxsw_sp_policer_family *family = priv;

	return atomic_read(&family->policers_count);
}

static int
mlxsw_sp_policer_single_rate_family_init(struct mlxsw_sp_policer_family *family)
{
	struct mlxsw_core *core = family->mlxsw_sp->core;
	struct devlink *devlink;

	/* CPU policers are allocated from the first N policers in the global
	 * range, so skip them.
@@ -82,12 +92,24 @@ mlxsw_sp_policer_single_rate_family_init(struct mlxsw_sp_policer_family *family)
	family->start_index = MLXSW_CORE_RES_GET(core, MAX_CPU_POLICERS);
	family->end_index = MLXSW_CORE_RES_GET(core, MAX_GLOBAL_POLICERS);

	atomic_set(&family->policers_count, 0);
	devlink = priv_to_devlink(core);
	devlink_resource_occ_get_register(devlink,
					  MLXSW_SP_RESOURCE_SINGLE_RATE_POLICERS,
					  mlxsw_sp_policer_single_rate_occ_get,
					  family);

	return 0;
}

static void
mlxsw_sp_policer_single_rate_family_fini(struct mlxsw_sp_policer_family *family)
{
	struct devlink *devlink = priv_to_devlink(family->mlxsw_sp->core);

	devlink_resource_occ_get_unregister(devlink,
					    MLXSW_SP_RESOURCE_SINGLE_RATE_POLICERS);
	WARN_ON(atomic_read(&family->policers_count) != 0);
}

static int
@@ -104,6 +126,7 @@ mlxsw_sp_policer_single_rate_index_alloc(struct mlxsw_sp_policer_family *family,
	if (id < 0)
		return id;

	atomic_inc(&family->policers_count);
	policer->index = id;

	return 0;
@@ -115,6 +138,8 @@ mlxsw_sp_policer_single_rate_index_free(struct mlxsw_sp_policer_family *family,
{
	struct mlxsw_sp_policer *policer;

	atomic_dec(&family->policers_count);

	mutex_lock(&family->lock);
	policer = idr_remove(&family->policer_idr, policer_index);
	mutex_unlock(&family->lock);
@@ -376,6 +401,46 @@ void mlxsw_sp_policers_fini(struct mlxsw_sp *mlxsw_sp)
	kfree(mlxsw_sp->policer_core);
}

int mlxsw_sp_policer_resources_register(struct mlxsw_core *mlxsw_core)
{
	u64 global_policers, cpu_policers, single_rate_policers;
	struct devlink *devlink = priv_to_devlink(mlxsw_core);
	struct devlink_resource_size_params size_params;
	int err;

	if (!MLXSW_CORE_RES_VALID(mlxsw_core, MAX_GLOBAL_POLICERS) ||
	    !MLXSW_CORE_RES_VALID(mlxsw_core, MAX_CPU_POLICERS))
		return -EIO;

	global_policers = MLXSW_CORE_RES_GET(mlxsw_core, MAX_GLOBAL_POLICERS);
	cpu_policers = MLXSW_CORE_RES_GET(mlxsw_core, MAX_CPU_POLICERS);
	single_rate_policers = global_policers - cpu_policers;

	devlink_resource_size_params_init(&size_params, global_policers,
					  global_policers, 1,
					  DEVLINK_RESOURCE_UNIT_ENTRY);
	err = devlink_resource_register(devlink, "global_policers",
					global_policers,
					MLXSW_SP_RESOURCE_GLOBAL_POLICERS,
					DEVLINK_RESOURCE_ID_PARENT_TOP,
					&size_params);
	if (err)
		return err;

	devlink_resource_size_params_init(&size_params, single_rate_policers,
					  single_rate_policers, 1,
					  DEVLINK_RESOURCE_UNIT_ENTRY);
	err = devlink_resource_register(devlink, "single_rate_policers",
					single_rate_policers,
					MLXSW_SP_RESOURCE_SINGLE_RATE_POLICERS,
					MLXSW_SP_RESOURCE_GLOBAL_POLICERS,
					&size_params);
	if (err)
		return err;

	return 0;
}

static int
mlxsw_sp1_policer_core_init(struct mlxsw_sp_policer_core *policer_core)
{