diff mbox series

[net-next,04/11] mlxsw: spectrum_policer: Add devlink resource support

Message ID 20200715082733.429610-5-idosch@idosch.org
State Accepted
Delegated to: David Miller
Headers show
Series [net-next,01/11] mlxsw: reg: Add policer bandwidth limits | expand

Commit Message

Ido Schimmel July 15, 2020, 8:27 a.m. UTC
From: Ido Schimmel <idosch@mellanox.com>

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: Ido Schimmel <idosch@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
Reviewed-by: Petr Machata <petrm@mellanox.com>
---
 .../net/ethernet/mellanox/mlxsw/spectrum.c    |  8 +++
 .../net/ethernet/mellanox/mlxsw/spectrum.h    |  3 +
 .../mellanox/mlxsw/spectrum_policer.c         | 65 +++++++++++++++++++
 3 files changed, 76 insertions(+)
diff mbox series

Patch

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index c6ab61818800..519eb44e4097 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -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:
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 82227e87ef7c..defe1d82d83e 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -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
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_policer.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_policer.c
index 74766e936e0a..39052e5c12fd 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_policer.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_policer.c
@@ -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)
 {