Commit 08ab4d74 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'occteontx2-rate-limit-offload'



Subbaraya Sundeep says:

====================
octeontx2: Add ingress ratelimit offload

This patchset adds ingress rate limiting hardware
offload support for CN10K silicons. Police actions
are added for TC matchall and flower filters.
CN10K has ingress rate limiting feature where
a receive queue is mapped to bandwidth profile
and the profile is configured with rate and burst
parameters by software. CN10K hardware supports
three levels of ingress policing or ratelimiting.
Multiple leaf profiles can  point to a single mid
level profile and multiple mid level profile can
point to a single top level one. Only leaf level
profiles are used for configuring rate limiting.

Patch 1 adds the new bandwidth profile contexts
in AF driver similar to other hardware contexts
Patch 2 adds the debugfs changes to dump bandwidth
profile contexts
Patch 3 adds support for police action with TC matchall filter
Patch 4 uses NL_SET_ERR_MSG_MOD for tc code
Patch 5 adds support for police action with TC flower filter
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ad5645d7 68fbff68
Loading
Loading
Loading
Loading
+39 −1
Original line number Diff line number Diff line
@@ -260,7 +260,11 @@ M(NIX_BP_DISABLE, 0x8017, nix_bp_disable, nix_bp_cfg_req, msg_rsp) \
M(NIX_GET_MAC_ADDR, 0x8018, nix_get_mac_addr, msg_req, nix_get_mac_addr_rsp) \
M(NIX_CN10K_AQ_ENQ,	0x8019, nix_cn10k_aq_enq, nix_cn10k_aq_enq_req, \
				nix_cn10k_aq_enq_rsp)			\
M(NIX_GET_HW_INFO,	0x801a, nix_get_hw_info, msg_req, nix_hw_info)
M(NIX_GET_HW_INFO,	0x801c, nix_get_hw_info, msg_req, nix_hw_info)	\
M(NIX_BANDPROF_ALLOC,	0x801d, nix_bandprof_alloc, nix_bandprof_alloc_req, \
				nix_bandprof_alloc_rsp)			    \
M(NIX_BANDPROF_FREE,	0x801e, nix_bandprof_free, nix_bandprof_free_req,   \
				msg_rsp)

/* Messages initiated by AF (range 0xC00 - 0xDFF) */
#define MBOX_UP_CGX_MESSAGES						\
@@ -615,6 +619,9 @@ enum nix_af_status {
	NIX_AF_ERR_PTP_CONFIG_FAIL  = -423,
	NIX_AF_ERR_NPC_KEY_NOT_SUPP = -424,
	NIX_AF_ERR_INVALID_NIXBLK   = -425,
	NIX_AF_ERR_INVALID_BANDPROF = -426,
	NIX_AF_ERR_IPOLICER_NOTSUPP = -427,
	NIX_AF_ERR_BANDPROF_INVAL_REQ  = -428,
};

/* For NIX RX vtag action  */
@@ -683,6 +690,7 @@ struct nix_cn10k_aq_enq_req {
		struct nix_cq_ctx_s cq;
		struct nix_rsse_s   rss;
		struct nix_rx_mce_s mce;
		struct nix_bandprof_s prof;
	};
	union {
		struct nix_cn10k_rq_ctx_s rq_mask;
@@ -690,6 +698,7 @@ struct nix_cn10k_aq_enq_req {
		struct nix_cq_ctx_s cq_mask;
		struct nix_rsse_s   rss_mask;
		struct nix_rx_mce_s mce_mask;
		struct nix_bandprof_s prof_mask;
	};
};

@@ -701,6 +710,7 @@ struct nix_cn10k_aq_enq_rsp {
		struct nix_cq_ctx_s cq;
		struct nix_rsse_s   rss;
		struct nix_rx_mce_s mce;
		struct nix_bandprof_s prof;
	};
};

@@ -716,6 +726,7 @@ struct nix_aq_enq_req {
		struct nix_cq_ctx_s cq;
		struct nix_rsse_s   rss;
		struct nix_rx_mce_s mce;
		u64 prof;
	};
	union {
		struct nix_rq_ctx_s rq_mask;
@@ -723,6 +734,7 @@ struct nix_aq_enq_req {
		struct nix_cq_ctx_s cq_mask;
		struct nix_rsse_s   rss_mask;
		struct nix_rx_mce_s mce_mask;
		u64 prof_mask;
	};
};

@@ -734,6 +746,7 @@ struct nix_aq_enq_rsp {
		struct nix_cq_ctx_s cq;
		struct nix_rsse_s   rss;
		struct nix_rx_mce_s mce;
		u64 prof;
	};
};

@@ -975,6 +988,31 @@ struct nix_hw_info {
	u16 min_mtu;
};

struct nix_bandprof_alloc_req {
	struct mbox_msghdr hdr;
	/* Count of profiles needed per layer */
	u16 prof_count[BAND_PROF_NUM_LAYERS];
};

struct nix_bandprof_alloc_rsp {
	struct mbox_msghdr hdr;
	u16 prof_count[BAND_PROF_NUM_LAYERS];

	/* There is no need to allocate morethan 1 bandwidth profile
	 * per RQ of a PF_FUNC's NIXLF. So limit the maximum
	 * profiles to 64 per PF_FUNC.
	 */
#define MAX_BANDPROF_PER_PFFUNC	64
	u16 prof_idx[BAND_PROF_NUM_LAYERS][MAX_BANDPROF_PER_PFFUNC];
};

struct nix_bandprof_free_req {
	struct mbox_msghdr hdr;
	u8 free_all;
	u16 prof_count[BAND_PROF_NUM_LAYERS];
	u16 prof_idx[BAND_PROF_NUM_LAYERS][MAX_BANDPROF_PER_PFFUNC];
};

/* NPC mbox message structs */

#define NPC_MCAM_ENTRY_INVALID	0xFFFF
+8 −0
Original line number Diff line number Diff line
@@ -184,6 +184,14 @@ int rvu_rsrc_free_count(struct rsrc_bmap *rsrc)
	return (rsrc->max - used);
}

bool is_rsrc_free(struct rsrc_bmap *rsrc, int id)
{
	if (!rsrc->bmap)
		return false;

	return !test_bit(id, rsrc->bmap);
}

int rvu_alloc_bitmap(struct rsrc_bmap *rsrc)
{
	rsrc->bmap = kcalloc(BITS_TO_LONGS(rsrc->max),
+16 −0
Original line number Diff line number Diff line
@@ -296,6 +296,13 @@ struct nix_txvlan {
	struct mutex rsrc_lock; /* Serialize resource alloc/free */
};

struct nix_ipolicer {
	struct rsrc_bmap band_prof;
	u16 *pfvf_map;
	u16 *match_id;
	u16 *ref_count;
};

struct nix_hw {
	int blkaddr;
	struct rvu *rvu;
@@ -305,6 +312,7 @@ struct nix_hw {
	struct nix_mark_format mark_format;
	struct nix_lso lso;
	struct nix_txvlan txvlan;
	struct nix_ipolicer *ipolicer;
};

/* RVU block's capabilities or functionality,
@@ -322,6 +330,7 @@ struct hw_cap {
	bool	nix_rx_multicast;	 /* Rx packet replication support */
	bool	per_pf_mbox_regs; /* PF mbox specified in per PF registers ? */
	bool	programmable_chans; /* Channels programmable ? */
	bool	ipolicer;
};

struct rvu_hwinfo {
@@ -587,6 +596,7 @@ static inline bool is_rvu_fwdata_valid(struct rvu *rvu)
int rvu_alloc_bitmap(struct rsrc_bmap *rsrc);
int rvu_alloc_rsrc(struct rsrc_bmap *rsrc);
void rvu_free_rsrc(struct rsrc_bmap *rsrc, int id);
bool is_rsrc_free(struct rsrc_bmap *rsrc, int id);
int rvu_rsrc_free_count(struct rsrc_bmap *rsrc);
int rvu_alloc_rsrc_contig(struct rsrc_bmap *rsrc, int nrsrc);
bool rvu_rsrc_check_contig(struct rsrc_bmap *rsrc, int nrsrc);
@@ -672,6 +682,12 @@ int rvu_get_next_nix_blkaddr(struct rvu *rvu, int blkaddr);
void rvu_nix_reset_mac(struct rvu_pfvf *pfvf, int pcifunc);
int nix_get_struct_ptrs(struct rvu *rvu, u16 pcifunc,
			struct nix_hw **nix_hw, int *blkaddr);
int rvu_nix_setup_ratelimit_aggr(struct rvu *rvu, u16 pcifunc,
				 u16 rq_idx, u16 match_id);
int nix_aq_context_read(struct rvu *rvu, struct nix_hw *nix_hw,
			struct nix_cn10k_aq_enq_req *aq_req,
			struct nix_cn10k_aq_enq_rsp *aq_rsp,
			u16 pcifunc, u8 ctype, u32 qidx);

/* NPC APIs */
int rvu_npc_init(struct rvu *rvu);
+163 −0
Original line number Diff line number Diff line
@@ -1632,6 +1632,165 @@ static int rvu_dbg_nix_qsize_display(struct seq_file *filp, void *unused)

RVU_DEBUG_SEQ_FOPS(nix_qsize, nix_qsize_display, nix_qsize_write);

static void print_band_prof_ctx(struct seq_file *m,
				struct nix_bandprof_s *prof)
{
	char *str;

	switch (prof->pc_mode) {
	case NIX_RX_PC_MODE_VLAN:
		str = "VLAN";
		break;
	case NIX_RX_PC_MODE_DSCP:
		str = "DSCP";
		break;
	case NIX_RX_PC_MODE_GEN:
		str = "Generic";
		break;
	case NIX_RX_PC_MODE_RSVD:
		str = "Reserved";
		break;
	}
	seq_printf(m, "W0: pc_mode\t\t%s\n", str);
	str = (prof->icolor == 3) ? "Color blind" :
		(prof->icolor == 0) ? "Green" :
		(prof->icolor == 1) ? "Yellow" : "Red";
	seq_printf(m, "W0: icolor\t\t%s\n", str);
	seq_printf(m, "W0: tnl_ena\t\t%d\n", prof->tnl_ena);
	seq_printf(m, "W0: peir_exponent\t%d\n", prof->peir_exponent);
	seq_printf(m, "W0: pebs_exponent\t%d\n", prof->pebs_exponent);
	seq_printf(m, "W0: cir_exponent\t%d\n", prof->cir_exponent);
	seq_printf(m, "W0: cbs_exponent\t%d\n", prof->cbs_exponent);
	seq_printf(m, "W0: peir_mantissa\t%d\n", prof->peir_mantissa);
	seq_printf(m, "W0: pebs_mantissa\t%d\n", prof->pebs_mantissa);
	seq_printf(m, "W0: cir_mantissa\t%d\n", prof->cir_mantissa);

	seq_printf(m, "W1: cbs_mantissa\t%d\n", prof->cbs_mantissa);
	str = (prof->lmode == 0) ? "byte" : "packet";
	seq_printf(m, "W1: lmode\t\t%s\n", str);
	seq_printf(m, "W1: l_select\t\t%d\n", prof->l_sellect);
	seq_printf(m, "W1: rdiv\t\t%d\n", prof->rdiv);
	seq_printf(m, "W1: adjust_exponent\t%d\n", prof->adjust_exponent);
	seq_printf(m, "W1: adjust_mantissa\t%d\n", prof->adjust_mantissa);
	str = (prof->gc_action == 0) ? "PASS" :
		(prof->gc_action == 1) ? "DROP" : "RED";
	seq_printf(m, "W1: gc_action\t\t%s\n", str);
	str = (prof->yc_action == 0) ? "PASS" :
		(prof->yc_action == 1) ? "DROP" : "RED";
	seq_printf(m, "W1: yc_action\t\t%s\n", str);
	str = (prof->rc_action == 0) ? "PASS" :
		(prof->rc_action == 1) ? "DROP" : "RED";
	seq_printf(m, "W1: rc_action\t\t%s\n", str);
	seq_printf(m, "W1: meter_algo\t\t%d\n", prof->meter_algo);
	seq_printf(m, "W1: band_prof_id\t%d\n", prof->band_prof_id);
	seq_printf(m, "W1: hl_en\t\t%d\n", prof->hl_en);

	seq_printf(m, "W2: ts\t\t\t%lld\n", (u64)prof->ts);
	seq_printf(m, "W3: pe_accum\t\t%d\n", prof->pe_accum);
	seq_printf(m, "W3: c_accum\t\t%d\n", prof->c_accum);
	seq_printf(m, "W4: green_pkt_pass\t%lld\n",
		   (u64)prof->green_pkt_pass);
	seq_printf(m, "W5: yellow_pkt_pass\t%lld\n",
		   (u64)prof->yellow_pkt_pass);
	seq_printf(m, "W6: red_pkt_pass\t%lld\n", (u64)prof->red_pkt_pass);
	seq_printf(m, "W7: green_octs_pass\t%lld\n",
		   (u64)prof->green_octs_pass);
	seq_printf(m, "W8: yellow_octs_pass\t%lld\n",
		   (u64)prof->yellow_octs_pass);
	seq_printf(m, "W9: red_octs_pass\t%lld\n", (u64)prof->red_octs_pass);
	seq_printf(m, "W10: green_pkt_drop\t%lld\n",
		   (u64)prof->green_pkt_drop);
	seq_printf(m, "W11: yellow_pkt_drop\t%lld\n",
		   (u64)prof->yellow_pkt_drop);
	seq_printf(m, "W12: red_pkt_drop\t%lld\n", (u64)prof->red_pkt_drop);
	seq_printf(m, "W13: green_octs_drop\t%lld\n",
		   (u64)prof->green_octs_drop);
	seq_printf(m, "W14: yellow_octs_drop\t%lld\n",
		   (u64)prof->yellow_octs_drop);
	seq_printf(m, "W15: red_octs_drop\t%lld\n", (u64)prof->red_octs_drop);
	seq_puts(m, "==============================\n");
}

static int rvu_dbg_nix_band_prof_ctx_display(struct seq_file *m, void *unused)
{
	struct nix_hw *nix_hw = m->private;
	struct nix_cn10k_aq_enq_req aq_req;
	struct nix_cn10k_aq_enq_rsp aq_rsp;
	struct rvu *rvu = nix_hw->rvu;
	struct nix_ipolicer *ipolicer;
	int layer, prof_idx, idx, rc;
	u16 pcifunc;
	char *str;

	for (layer = 0; layer < BAND_PROF_NUM_LAYERS; layer++) {
		if (layer == BAND_PROF_INVAL_LAYER)
			continue;
		str = (layer == BAND_PROF_LEAF_LAYER) ? "Leaf" :
			(layer == BAND_PROF_MID_LAYER) ? "Mid" : "Top";

		seq_printf(m, "\n%s bandwidth profiles\n", str);
		seq_puts(m, "=======================\n");

		ipolicer = &nix_hw->ipolicer[layer];

		for (idx = 0; idx < ipolicer->band_prof.max; idx++) {
			if (is_rsrc_free(&ipolicer->band_prof, idx))
				continue;

			prof_idx = (idx & 0x3FFF) | (layer << 14);
			rc = nix_aq_context_read(rvu, nix_hw, &aq_req, &aq_rsp,
						 0x00, NIX_AQ_CTYPE_BANDPROF,
						 prof_idx);
			if (rc) {
				dev_err(rvu->dev,
					"%s: Failed to fetch context of %s profile %d, err %d\n",
					__func__, str, idx, rc);
				return 0;
			}
			seq_printf(m, "\n%s bandwidth profile:: %d\n", str, idx);
			pcifunc = ipolicer->pfvf_map[idx];
			if (!(pcifunc & RVU_PFVF_FUNC_MASK))
				seq_printf(m, "Allocated to :: PF %d\n",
					   rvu_get_pf(pcifunc));
			else
				seq_printf(m, "Allocated to :: PF %d VF %d\n",
					   rvu_get_pf(pcifunc),
					   (pcifunc & RVU_PFVF_FUNC_MASK) - 1);
			print_band_prof_ctx(m, &aq_rsp.prof);
		}
	}
	return 0;
}

RVU_DEBUG_SEQ_FOPS(nix_band_prof_ctx, nix_band_prof_ctx_display, NULL);

static int rvu_dbg_nix_band_prof_rsrc_display(struct seq_file *m, void *unused)
{
	struct nix_hw *nix_hw = m->private;
	struct nix_ipolicer *ipolicer;
	int layer;
	char *str;

	seq_puts(m, "\nBandwidth profile resource free count\n");
	seq_puts(m, "=====================================\n");
	for (layer = 0; layer < BAND_PROF_NUM_LAYERS; layer++) {
		if (layer == BAND_PROF_INVAL_LAYER)
			continue;
		str = (layer == BAND_PROF_LEAF_LAYER) ? "Leaf" :
			(layer == BAND_PROF_MID_LAYER) ? "Mid " : "Top ";

		ipolicer = &nix_hw->ipolicer[layer];
		seq_printf(m, "%s :: Max: %4d  Free: %4d\n", str,
			   ipolicer->band_prof.max,
			   rvu_rsrc_free_count(&ipolicer->band_prof));
	}
	seq_puts(m, "=====================================\n");

	return 0;
}

RVU_DEBUG_SEQ_FOPS(nix_band_prof_rsrc, nix_band_prof_rsrc_display, NULL);

static void rvu_dbg_nix_init(struct rvu *rvu, int blkaddr)
{
	struct nix_hw *nix_hw;
@@ -1664,6 +1823,10 @@ static void rvu_dbg_nix_init(struct rvu *rvu, int blkaddr)
			    &rvu_dbg_nix_ndc_rx_hits_miss_fops);
	debugfs_create_file("qsize", 0600, rvu->rvu_dbg.nix, rvu,
			    &rvu_dbg_nix_qsize_fops);
	debugfs_create_file("ingress_policer_ctx", 0600, rvu->rvu_dbg.nix, nix_hw,
			    &rvu_dbg_nix_band_prof_ctx_fops);
	debugfs_create_file("ingress_policer_rsrc", 0600, rvu->rvu_dbg.nix, nix_hw,
			    &rvu_dbg_nix_band_prof_rsrc_fops);
}

static void rvu_dbg_npa_init(struct rvu *rvu)
+617 −2

File changed.

Preview size limit exceeded, changes collapsed.

Loading