Commit c4e39b89 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'knobs-for-npc-default-rule-counters'

Linu Cherian says:

====================
Knobs for NPC default rule counters

Patch 1 introduce _rvu_mcam_remove/add_counter_from/to_rule
by refactoring existing code

Patch 2 adds a devlink param to enable/disable counters for default
rules. Once enabled, counters can

Patch 3 adds documentation for devlink params

v4: https://lore.kernel.org/20241029035739.1981839-1-lcherian@marvell.com
====================

Link: https://patch.msgid.link/20241105125620.2114301-1-lcherian@marvell.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 619e4109 46799a41
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -40,6 +40,27 @@ The ``octeontx2 AF`` driver implements the following driver-specific parameters.
     - runtime
     - Use to set the quantum which hardware uses for scheduling among transmit queues.
       Hardware uses weighted DWRR algorithm to schedule among all transmit queues.
   * - ``npc_mcam_high_zone_percent``
     - u8
     - runtime
     - Use to set the number of high priority zone entries in NPC MCAM that can be allocated
       by a user, out of the three priority zone categories high, mid and low.
   * - ``npc_def_rule_cntr``
     - bool
     - runtime
     - Use to enable or disable hit counters for the default rules in NPC MCAM.
       Its not guaranteed that counters gets enabled and mapped to all the default rules,
       since the counters are scarce and driver follows a best effort approach.
       The default rule serves as the primary packet steering rule for a specific PF or VF,
       based on its DMAC address which is installed by AF driver as part of its initialization.
       Sample command to read hit counters for default rule from debugfs is as follows,
       cat /sys/kernel/debug/cn10k/npc/mcam_rules
   * - ``nix_maxlf``
     - u16
     - runtime
     - Use to set the maximum number of LFs in NIX hardware block. This would be useful
       to increase the availability of default resources allocated to enabled LFs like
       MCAM entries for example.

The ``octeontx2 PF`` driver implements the following driver-specific parameters.

+7 −1
Original line number Diff line number Diff line
@@ -525,6 +525,7 @@ struct rvu {
	struct mutex		alias_lock; /* Serialize bar2 alias access */
	int			vfs; /* Number of VFs attached to RVU */
	u16			vf_devid; /* VF devices id */
	bool			def_rule_cntr_en;
	int			nix_blkaddr[MAX_NIX_BLKS];

	/* Mbox */
@@ -960,7 +961,11 @@ void rvu_npc_disable_default_entries(struct rvu *rvu, u16 pcifunc, int nixlf);
void rvu_npc_enable_default_entries(struct rvu *rvu, u16 pcifunc, int nixlf);
void rvu_npc_update_flowkey_alg_idx(struct rvu *rvu, u16 pcifunc, int nixlf,
				    int group, int alg_idx, int mcam_index);

void __rvu_mcam_remove_counter_from_rule(struct rvu *rvu, u16 pcifunc,
					 struct rvu_npc_mcam_rule *rule);
void __rvu_mcam_add_counter_to_rule(struct rvu *rvu, u16 pcifunc,
				    struct rvu_npc_mcam_rule *rule,
				    struct npc_install_flow_rsp *rsp);
void rvu_npc_get_mcam_entry_alloc_info(struct rvu *rvu, u16 pcifunc,
				       int blkaddr, int *alloc_cnt,
				       int *enable_cnt);
@@ -985,6 +990,7 @@ void npc_set_mcam_action(struct rvu *rvu, struct npc_mcam *mcam,
void npc_read_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
			 int blkaddr, u16 src, struct mcam_entry *entry,
			 u8 *intf, u8 *ena);
int npc_config_cntr_default_entries(struct rvu *rvu, bool enable);
bool is_cgx_config_permitted(struct rvu *rvu, u16 pcifunc);
bool is_mac_feature_supported(struct rvu *rvu, int pf, int feature);
u32  rvu_cgx_get_fifolen(struct rvu *rvu);
+32 −0
Original line number Diff line number Diff line
@@ -1238,6 +1238,7 @@ enum rvu_af_dl_param_id {
	RVU_AF_DEVLINK_PARAM_ID_DWRR_MTU,
	RVU_AF_DEVLINK_PARAM_ID_NPC_MCAM_ZONE_PERCENT,
	RVU_AF_DEVLINK_PARAM_ID_NPC_EXACT_FEATURE_DISABLE,
	RVU_AF_DEVLINK_PARAM_ID_NPC_DEF_RULE_CNTR_ENABLE,
	RVU_AF_DEVLINK_PARAM_ID_NIX_MAXLF,
};

@@ -1358,6 +1359,32 @@ static int rvu_af_dl_npc_mcam_high_zone_percent_validate(struct devlink *devlink
	return 0;
}

static int rvu_af_dl_npc_def_rule_cntr_get(struct devlink *devlink, u32 id,
					   struct devlink_param_gset_ctx *ctx)
{
	struct rvu_devlink *rvu_dl = devlink_priv(devlink);
	struct rvu *rvu = rvu_dl->rvu;

	ctx->val.vbool = rvu->def_rule_cntr_en;

	return 0;
}

static int rvu_af_dl_npc_def_rule_cntr_set(struct devlink *devlink, u32 id,
					   struct devlink_param_gset_ctx *ctx,
					   struct netlink_ext_ack *extack)
{
	struct rvu_devlink *rvu_dl = devlink_priv(devlink);
	struct rvu *rvu = rvu_dl->rvu;
	int err;

	err = npc_config_cntr_default_entries(rvu, ctx->val.vbool);
	if (!err)
		rvu->def_rule_cntr_en = ctx->val.vbool;

	return err;
}

static int rvu_af_dl_nix_maxlf_get(struct devlink *devlink, u32 id,
				   struct devlink_param_gset_ctx *ctx)
{
@@ -1444,6 +1471,11 @@ static const struct devlink_param rvu_af_dl_params[] = {
			     rvu_af_dl_npc_mcam_high_zone_percent_get,
			     rvu_af_dl_npc_mcam_high_zone_percent_set,
			     rvu_af_dl_npc_mcam_high_zone_percent_validate),
	DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_NPC_DEF_RULE_CNTR_ENABLE,
			     "npc_def_rule_cntr", DEVLINK_PARAM_TYPE_BOOL,
			     BIT(DEVLINK_PARAM_CMODE_RUNTIME),
			     rvu_af_dl_npc_def_rule_cntr_get,
			     rvu_af_dl_npc_def_rule_cntr_set, NULL),
	DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_NIX_MAXLF,
			     "nix_maxlf", DEVLINK_PARAM_TYPE_U16,
			     BIT(DEVLINK_PARAM_CMODE_RUNTIME),
+121 −11
Original line number Diff line number Diff line
@@ -2691,6 +2691,49 @@ void npc_mcam_rsrcs_reserve(struct rvu *rvu, int blkaddr, int entry_idx)
	npc_mcam_set_bit(mcam, entry_idx);
}

int npc_config_cntr_default_entries(struct rvu *rvu, bool enable)
{
	struct npc_mcam *mcam = &rvu->hw->mcam;
	struct npc_install_flow_rsp rsp;
	struct rvu_npc_mcam_rule *rule;
	int blkaddr;

	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
	if (blkaddr < 0)
		return -EINVAL;

	mutex_lock(&mcam->lock);
	list_for_each_entry(rule, &mcam->mcam_rules, list) {
		if (!is_mcam_entry_enabled(rvu, mcam, blkaddr, rule->entry))
			continue;
		if (!rule->default_rule)
			continue;
		if (enable && !rule->has_cntr) { /* Alloc and map new counter */
			__rvu_mcam_add_counter_to_rule(rvu, rule->owner,
						       rule, &rsp);
			if (rsp.counter < 0) {
				dev_err(rvu->dev,
					"%s: Failed to allocate cntr for default rule (err=%d)\n",
					__func__, rsp.counter);
				break;
			}
			npc_map_mcam_entry_and_cntr(rvu, mcam, blkaddr,
						    rule->entry, rsp.counter);
			/* Reset counter before use */
			rvu_write64(rvu, blkaddr,
				    NPC_AF_MATCH_STATX(rule->cntr), 0x0);
		}

		/* Free and unmap counter */
		if (!enable && rule->has_cntr)
			__rvu_mcam_remove_counter_from_rule(rvu, rule->owner,
							    rule);
	}
	mutex_unlock(&mcam->lock);

	return 0;
}

int rvu_mbox_handler_npc_mcam_alloc_entry(struct rvu *rvu,
					  struct npc_mcam_alloc_entry_req *req,
					  struct npc_mcam_alloc_entry_rsp *rsp)
@@ -2975,7 +3018,7 @@ int rvu_mbox_handler_npc_mcam_shift_entry(struct rvu *rvu,
	return rc;
}

int rvu_mbox_handler_npc_mcam_alloc_counter(struct rvu *rvu,
static int __npc_mcam_alloc_counter(struct rvu *rvu,
				    struct npc_mcam_alloc_counter_req *req,
				    struct npc_mcam_alloc_counter_rsp *rsp)
{
@@ -2998,11 +3041,9 @@ int rvu_mbox_handler_npc_mcam_alloc_counter(struct rvu *rvu,
	if (!req->contig && req->count > NPC_MAX_NONCONTIG_COUNTERS)
		return NPC_MCAM_INVALID_REQ;

	mutex_lock(&mcam->lock);

	/* Check if unused counters are available or not */
	if (!rvu_rsrc_free_count(&mcam->counters)) {
		mutex_unlock(&mcam->lock);
		return NPC_MCAM_ALLOC_FAILED;
	}

@@ -3035,12 +3076,27 @@ int rvu_mbox_handler_npc_mcam_alloc_counter(struct rvu *rvu,
		}
	}

	mutex_unlock(&mcam->lock);
	return 0;
}

int rvu_mbox_handler_npc_mcam_free_counter(struct rvu *rvu,
		struct npc_mcam_oper_counter_req *req, struct msg_rsp *rsp)
int rvu_mbox_handler_npc_mcam_alloc_counter(struct rvu *rvu,
			struct npc_mcam_alloc_counter_req *req,
			struct npc_mcam_alloc_counter_rsp *rsp)
{
	struct npc_mcam *mcam = &rvu->hw->mcam;
	int err;

	mutex_lock(&mcam->lock);

	err = __npc_mcam_alloc_counter(rvu, req, rsp);

	mutex_unlock(&mcam->lock);
	return err;
}

static int __npc_mcam_free_counter(struct rvu *rvu,
				   struct npc_mcam_oper_counter_req *req,
				   struct msg_rsp *rsp)
{
	struct npc_mcam *mcam = &rvu->hw->mcam;
	u16 index, entry = 0;
@@ -3050,10 +3106,8 @@ int rvu_mbox_handler_npc_mcam_free_counter(struct rvu *rvu,
	if (blkaddr < 0)
		return NPC_MCAM_INVALID_REQ;

	mutex_lock(&mcam->lock);
	err = npc_mcam_verify_counter(mcam, req->hdr.pcifunc, req->cntr);
	if (err) {
		mutex_unlock(&mcam->lock);
		return err;
	}

@@ -3077,10 +3131,66 @@ int rvu_mbox_handler_npc_mcam_free_counter(struct rvu *rvu,
					      index, req->cntr);
	}

	mutex_unlock(&mcam->lock);
	return 0;
}

int rvu_mbox_handler_npc_mcam_free_counter(struct rvu *rvu,
		struct npc_mcam_oper_counter_req *req, struct msg_rsp *rsp)
{
	struct npc_mcam *mcam = &rvu->hw->mcam;
	int err;

	mutex_lock(&mcam->lock);

	err = __npc_mcam_free_counter(rvu, req, rsp);

	mutex_unlock(&mcam->lock);

	return err;
}

void __rvu_mcam_remove_counter_from_rule(struct rvu *rvu, u16 pcifunc,
					 struct rvu_npc_mcam_rule *rule)
{
	struct npc_mcam_oper_counter_req free_req = { 0 };
	struct msg_rsp free_rsp;

	if (!rule->has_cntr)
		return;

	free_req.hdr.pcifunc = pcifunc;
	free_req.cntr = rule->cntr;

	__npc_mcam_free_counter(rvu, &free_req, &free_rsp);
	rule->has_cntr = false;
}

void __rvu_mcam_add_counter_to_rule(struct rvu *rvu, u16 pcifunc,
				    struct rvu_npc_mcam_rule *rule,
				    struct npc_install_flow_rsp *rsp)
{
	struct npc_mcam_alloc_counter_req cntr_req = { 0 };
	struct npc_mcam_alloc_counter_rsp cntr_rsp = { 0 };
	int err;

	cntr_req.hdr.pcifunc = pcifunc;
	cntr_req.contig = true;
	cntr_req.count = 1;

	/* we try to allocate a counter to track the stats of this
	 * rule. If counter could not be allocated then proceed
	 * without counter because counters are limited than entries.
	 */
	err = __npc_mcam_alloc_counter(rvu, &cntr_req, &cntr_rsp);
	if (!err && cntr_rsp.count) {
		rule->cntr = cntr_rsp.cntr;
		rule->has_cntr = true;
		rsp->counter = rule->cntr;
	} else {
		rsp->counter = err;
	}
}

int rvu_mbox_handler_npc_mcam_unmap_counter(struct rvu *rvu,
		struct npc_mcam_unmap_counter_req *req, struct msg_rsp *rsp)
{
+9 −27
Original line number Diff line number Diff line
@@ -1081,44 +1081,26 @@ static void rvu_mcam_add_rule(struct npc_mcam *mcam,
static void rvu_mcam_remove_counter_from_rule(struct rvu *rvu, u16 pcifunc,
					      struct rvu_npc_mcam_rule *rule)
{
	struct npc_mcam_oper_counter_req free_req = { 0 };
	struct msg_rsp free_rsp;
	struct npc_mcam *mcam = &rvu->hw->mcam;

	if (!rule->has_cntr)
		return;
	mutex_lock(&mcam->lock);

	free_req.hdr.pcifunc = pcifunc;
	free_req.cntr = rule->cntr;
	__rvu_mcam_remove_counter_from_rule(rvu, pcifunc, rule);

	rvu_mbox_handler_npc_mcam_free_counter(rvu, &free_req, &free_rsp);
	rule->has_cntr = false;
	mutex_unlock(&mcam->lock);
}

static void rvu_mcam_add_counter_to_rule(struct rvu *rvu, u16 pcifunc,
					 struct rvu_npc_mcam_rule *rule,
					 struct npc_install_flow_rsp *rsp)
{
	struct npc_mcam_alloc_counter_req cntr_req = { 0 };
	struct npc_mcam_alloc_counter_rsp cntr_rsp = { 0 };
	int err;
	struct npc_mcam *mcam = &rvu->hw->mcam;

	cntr_req.hdr.pcifunc = pcifunc;
	cntr_req.contig = true;
	cntr_req.count = 1;
	mutex_lock(&mcam->lock);

	/* we try to allocate a counter to track the stats of this
	 * rule. If counter could not be allocated then proceed
	 * without counter because counters are limited than entries.
	 */
	err = rvu_mbox_handler_npc_mcam_alloc_counter(rvu, &cntr_req,
						      &cntr_rsp);
	if (!err && cntr_rsp.count) {
		rule->cntr = cntr_rsp.cntr;
		rule->has_cntr = true;
		rsp->counter = rule->cntr;
	} else {
		rsp->counter = err;
	}
	__rvu_mcam_add_counter_to_rule(rvu, pcifunc, rule, rsp);

	mutex_unlock(&mcam->lock);
}

static int npc_mcast_update_action_index(struct rvu *rvu, struct npc_install_flow_req *req,