Commit 4e527f1e authored by Suman Ghosh's avatar Suman Ghosh Committed by Jakub Kicinski
Browse files

octeontx2-af: npc: cn20k: Add new mailboxes for CN20K silicon



To enable enhanced MCAM capabilities for CN20K, the struct mcam_entry
has been extended to support expanded keyword requirements.
Specifically, the kw and kw_mask arrays have been increased from
a size of 7 to 8 to accommodate the additional keyword field
introduced for CN20K.

To ensure seamless integration while preserving compatibility
with existing platforms, dedicated CN20K-specific mailboxes
have been introduced that leverage the updated struct mcam_entry.
This approach allows CN20K to utilize the extended structure
without impacting current implementations.

This patch identifies the relevant mailboxes and introduces the
following CN20K-specific additions:

New mailboxes added:
1. `NPC_CN20K_MCAM_WRITE_ENTRY`
2. `NPC_CN20K_MCAM_ALLOC_AND_WRITE_ENTRY`
3. `NPC_CN20K_MCAM_READ_ENTRY`
4. `NPC_CN20K_MCAM_READ_BASE_RULE`

Signed-off-by: default avatarSuman Ghosh <sumang@marvell.com>
Signed-off-by: default avatarRatheesh Kannoth <rkannoth@marvell.com>
Link: https://patch.msgid.link/20260224080009.4147301-9-rkannoth@marvell.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent de3f88b4
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -397,6 +397,12 @@ int rvu_alloc_cint_qint_mem(struct rvu *rvu, struct rvu_pfvf *pfvf,
	if (is_rvu_otx2(rvu) || is_cn20k(rvu->pdev))
		return 0;

	/* sanity check */
	cfg = rvu_read64(rvu, BLKADDR_RVUM, RVU_PRIV_PFX_NIXX_CFG(0) |
			 (RVU_AFPF << 16));
	if (!cfg)
		return 0;

	ctx_cfg = rvu_read64(rvu, blkaddr, NIX_AF_CONST3);
	/* Alloc memory for CQINT's HW contexts */
	cfg = rvu_read64(rvu, blkaddr, NIX_AF_CONST2);
@@ -420,5 +426,16 @@ int rvu_alloc_cint_qint_mem(struct rvu *rvu, struct rvu_pfvf *pfvf,
	rvu_write64(rvu, blkaddr, NIX_AF_LFX_QINTS_BASE(nixlf),
		    (u64)pfvf->nix_qints_ctx->iova);

	rvu_write64(rvu, BLKADDR_NIX0, RVU_AF_BAR2_SEL, RVU_AF_BAR2_PFID);
	rvu_write64(rvu, BLKADDR_NIX0,
		    AF_BAR2_ALIASX(0, NIX_GINT_INT_W1S), ALTAF_RDY);
	/* wait for ack */
	err = rvu_poll_reg(rvu, BLKADDR_NIX0,
			   AF_BAR2_ALIASX(0, NIX_GINT_INT), ALTAF_RDY, true);
	if (err)
		rvu->altaf_ready = false;
	else
		rvu->altaf_ready = true;

	return 0;
}
+180 −9
Original line number Diff line number Diff line
@@ -637,9 +637,13 @@ npc_cn20k_clear_mcam_entry(struct rvu *rvu, int blkaddr, int bank, int index)
		    NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W3_EXT(index, bank, 1), 0);
	rvu_write64(rvu, blkaddr,
		    NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W3_EXT(index, bank, 0), 0);

	/* Clear corresponding stats register */
	rvu_write64(rvu, blkaddr,
		    NPC_AF_CN20K_MCAMEX_BANKX_STAT_EXT(index, bank), 0);
}

static void npc_cn20k_get_keyword(struct mcam_entry *entry, int idx,
static void npc_cn20k_get_keyword(struct cn20k_mcam_entry *entry, int idx,
				  u64 *cam0, u64 *cam1)
{
	u64 kw_mask;
@@ -679,7 +683,7 @@ static void npc_cn20k_get_keyword(struct mcam_entry *entry, int idx,
 */
static void npc_cn20k_config_kw_x2(struct rvu *rvu, struct npc_mcam *mcam,
				   int blkaddr, int index, u8 intf,
				   struct mcam_entry *entry,
				   struct cn20k_mcam_entry *entry,
				   int bank, u8 kw_type, int kw)
{
	u64 intf_ext = 0, intf_ext_mask = 0;
@@ -751,7 +755,8 @@ static void npc_cn20k_config_kw_x2(struct rvu *rvu, struct npc_mcam *mcam,

static void npc_cn20k_config_kw_x4(struct rvu *rvu, struct npc_mcam *mcam,
				   int blkaddr, int index, u8 intf,
				   struct mcam_entry *entry, u8 kw_type)
				   struct cn20k_mcam_entry *entry,
				   u8 kw_type)
{
	int kw = 0, bank;

@@ -789,9 +794,9 @@ npc_cn20k_set_mcam_bank_cfg(struct rvu *rvu, int blkaddr, int mcam_idx,
	}
}

void
npc_cn20k_config_mcam_entry(struct rvu *rvu, int blkaddr, int index, u8 intf,
			    struct mcam_entry *entry, bool enable, u8 hw_prio)
void npc_cn20k_config_mcam_entry(struct rvu *rvu, int blkaddr, int index,
				 u8 intf, struct cn20k_mcam_entry *entry,
				 bool enable, u8 hw_prio)
{
	struct npc_mcam *mcam = &rvu->hw->mcam;
	int mcam_idx = index % mcam->banksize;
@@ -906,7 +911,7 @@ void npc_cn20k_copy_mcam_entry(struct rvu *rvu, int blkaddr, u16 src, u16 dest)
	}
}

static void npc_cn20k_fill_entryword(struct mcam_entry *entry, int idx,
static void npc_cn20k_fill_entryword(struct cn20k_mcam_entry *entry, int idx,
				     u64 cam0, u64 cam1)
{
	entry->kw[idx] = cam1;
@@ -914,8 +919,8 @@ static void npc_cn20k_fill_entryword(struct mcam_entry *entry, int idx,
}

void npc_cn20k_read_mcam_entry(struct rvu *rvu, int blkaddr, u16 index,
			       struct mcam_entry *entry, u8 *intf, u8 *ena,
			       u8 *hw_prio)
			       struct cn20k_mcam_entry *entry,
			       u8 *intf, u8 *ena, u8 *hw_prio)
{
	struct npc_mcam *mcam = &rvu->hw->mcam;
	u64 cam0, cam1, bank_cfg, cfg;
@@ -1034,6 +1039,172 @@ void npc_cn20k_read_mcam_entry(struct rvu *rvu, int blkaddr, u16 index,
	entry->vtag_action = cfg;
}

int rvu_mbox_handler_npc_cn20k_mcam_write_entry(struct rvu *rvu,
						struct npc_cn20k_mcam_write_entry_req *req,
						struct msg_rsp *rsp)
{
	struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, req->hdr.pcifunc);
	struct npc_mcam *mcam = &rvu->hw->mcam;
	u16 pcifunc = req->hdr.pcifunc;
	int blkaddr, rc;
	u8 nix_intf;

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

	mutex_lock(&mcam->lock);
	rc = npc_mcam_verify_entry(mcam, pcifunc, req->entry);
	if (rc)
		goto exit;

	if (!is_npc_interface_valid(rvu, req->intf)) {
		rc = NPC_MCAM_INVALID_REQ;
		goto exit;
	}

	if (is_npc_intf_tx(req->intf))
		nix_intf = pfvf->nix_tx_intf;
	else
		nix_intf = pfvf->nix_rx_intf;

	/* For AF installed rules, the nix_intf should be set to target NIX */
	if (is_pffunc_af(req->hdr.pcifunc))
		nix_intf = req->intf;

	npc_cn20k_config_mcam_entry(rvu, blkaddr, req->entry, nix_intf,
				    &req->entry_data, req->enable_entry,
				    req->hw_prio);

	rc = 0;
exit:
	mutex_unlock(&mcam->lock);
	return rc;
}

int rvu_mbox_handler_npc_cn20k_mcam_read_entry(struct rvu *rvu,
					       struct npc_mcam_read_entry_req *req,
					       struct npc_cn20k_mcam_read_entry_rsp *rsp)
{
	struct npc_mcam *mcam = &rvu->hw->mcam;
	u16 pcifunc = req->hdr.pcifunc;
	int blkaddr, rc;

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

	mutex_lock(&mcam->lock);
	rc = npc_mcam_verify_entry(mcam, pcifunc, req->entry);
	if (!rc)
		npc_cn20k_read_mcam_entry(rvu, blkaddr, req->entry,
					  &rsp->entry_data, &rsp->intf,
					  &rsp->enable, &rsp->hw_prio);

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

int rvu_mbox_handler_npc_cn20k_mcam_alloc_and_write_entry(struct rvu *rvu,
							  struct npc_cn20k_mcam_alloc_and_write_entry_req *req,
							  struct npc_mcam_alloc_and_write_entry_rsp *rsp)
{
	struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, req->hdr.pcifunc);
	struct npc_mcam_alloc_entry_req entry_req;
	struct npc_mcam_alloc_entry_rsp entry_rsp;
	struct npc_mcam *mcam = &rvu->hw->mcam;
	u16 entry = NPC_MCAM_ENTRY_INVALID;
	int blkaddr, rc;
	u8 nix_intf;

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

	if (!is_npc_interface_valid(rvu, req->intf))
		return NPC_MCAM_INVALID_REQ;

	/* Try to allocate a MCAM entry */
	entry_req.hdr.pcifunc = req->hdr.pcifunc;
	entry_req.contig = true;
	entry_req.ref_prio = req->ref_prio;
	entry_req.ref_entry = req->ref_entry;
	entry_req.count = 1;

	rc = rvu_mbox_handler_npc_mcam_alloc_entry(rvu,
						   &entry_req, &entry_rsp);
	if (rc)
		return rc;

	if (!entry_rsp.count)
		return NPC_MCAM_ALLOC_FAILED;

	/* entry_req.count is 1, so single entry is allocated */
	entry = entry_rsp.entry;
	mutex_lock(&mcam->lock);

	if (is_npc_intf_tx(req->intf))
		nix_intf = pfvf->nix_tx_intf;
	else
		nix_intf = pfvf->nix_rx_intf;

	npc_cn20k_config_mcam_entry(rvu, blkaddr, entry, nix_intf,
				    &req->entry_data, req->enable_entry,
				    req->hw_prio);

	mutex_unlock(&mcam->lock);

	rsp->entry = entry;
	return 0;
}

int rvu_mbox_handler_npc_cn20k_read_base_steer_rule(struct rvu *rvu,
						    struct msg_req *req,
						    struct npc_cn20k_mcam_read_base_rule_rsp *rsp)
{
	struct npc_mcam *mcam = &rvu->hw->mcam;
	int index, blkaddr, nixlf, rc = 0;
	u16 pcifunc = req->hdr.pcifunc;
	u8 intf, enable, hw_prio;
	struct rvu_pfvf *pfvf;

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

	/* Return the channel number in case of PF */
	if (!(pcifunc & RVU_PFVF_FUNC_MASK)) {
		pfvf = rvu_get_pfvf(rvu, pcifunc);
		rsp->entry.kw[0] = pfvf->rx_chan_base;
		rsp->entry.kw_mask[0] = 0xFFFULL;
		goto out;
	}

	/* Find the pkt steering rule installed by PF to this VF */
	mutex_lock(&mcam->lock);
	for (index = 0; index < mcam->bmap_entries; index++) {
		if (mcam->entry2target_pffunc[index] == pcifunc)
			goto read_entry;
	}

	rc = nix_get_nixlf(rvu, pcifunc, &nixlf, NULL);
	if (rc < 0) {
		mutex_unlock(&mcam->lock);
		goto out;
	}
	/* Read the default ucast entry if there is no pkt steering rule */
	index = npc_get_nixlf_mcam_index(mcam, pcifunc, nixlf,
					 NIXLF_UCAST_ENTRY);
read_entry:
	/* Read the mcam entry */
	npc_cn20k_read_mcam_entry(rvu, blkaddr, index,
				  &rsp->entry, &intf,
				  &enable, &hw_prio);
	mutex_unlock(&mcam->lock);
out:
	return rc;
}

static u8 npc_map2cn20k_flag(u8 flag)
{
	switch (flag) {
+4 −3
Original line number Diff line number Diff line
@@ -296,15 +296,16 @@ int npc_cn20k_dft_rules_idx_get(struct rvu *rvu, u16 pcifunc, u16 *bcast,
				u16 *mcast, u16 *promisc, u16 *ucast);

void npc_cn20k_config_mcam_entry(struct rvu *rvu, int blkaddr, int index,
				 u8 intf, struct mcam_entry *entry,
				 u8 intf,
				 struct cn20k_mcam_entry *entry,
				 bool enable, u8 hw_prio);
void npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkaddr,
				 int index, bool enable);
void npc_cn20k_copy_mcam_entry(struct rvu *rvu, int blkaddr,
			       u16 src, u16 dest);
void npc_cn20k_read_mcam_entry(struct rvu *rvu, int blkaddr, u16 index,
			       struct mcam_entry *entry, u8 *intf, u8 *ena,
			       u8 *hw_prio);
			       struct cn20k_mcam_entry *entry, u8 *intf,
			       u8 *ena, u8 *hw_prio);
void npc_cn20k_clear_mcam_entry(struct rvu *rvu, int blkaddr,
				int bank, int index);
int npc_mcam_idx_2_key_type(struct rvu *rvu, u16 mcam_idx, u8 *key_type);
+7 −0
Original line number Diff line number Diff line
@@ -78,6 +78,13 @@
#define RVU_MBOX_VF_INT_ENA_W1C			(0x38)

#define RVU_MBOX_VF_VFAF_TRIGX(a)		(0x2000 | (a) << 3)

#define NIX_GINT_INT                           (0x200)
#define NIX_GINT_INT_W1S                       (0x208)

#define ALTAF_FLR                              BIT_ULL(0)
#define ALTAF_RDY                              BIT_ULL(1)

/* NPC registers */
#define NPC_AF_INTFX_EXTRACTORX_CFG(a, b) \
	(0x20c000ull | (a) << 16 | (b) << 8)
+55 −3
Original line number Diff line number Diff line
@@ -287,6 +287,17 @@ M(NPC_CN20K_MCAM_GET_FREE_COUNT, 0x6015, npc_cn20k_get_fcnt, \
				 msg_req, npc_cn20k_get_fcnt_rsp)	\
M(NPC_CN20K_GET_KEX_CFG, 0x6016, npc_cn20k_get_kex_cfg,			\
				   msg_req, npc_cn20k_get_kex_cfg_rsp)	\
M(NPC_CN20K_MCAM_WRITE_ENTRY,	0x6017, npc_cn20k_mcam_write_entry,	\
				 npc_cn20k_mcam_write_entry_req, msg_rsp)  \
M(NPC_CN20K_MCAM_ALLOC_AND_WRITE_ENTRY, 0x6018,				   \
npc_cn20k_mcam_alloc_and_write_entry,					   \
				npc_cn20k_mcam_alloc_and_write_entry_req,  \
				npc_mcam_alloc_and_write_entry_rsp)  \
M(NPC_CN20K_MCAM_READ_ENTRY,	0x6019, npc_cn20k_mcam_read_entry,	\
				  npc_mcam_read_entry_req,		\
				  npc_cn20k_mcam_read_entry_rsp)	\
M(NPC_CN20K_MCAM_READ_BASE_RULE, 0x601a, npc_cn20k_read_base_steer_rule,       \
				   msg_req, npc_cn20k_mcam_read_base_rule_rsp) \
/* NIX mbox IDs (range 0x8000 - 0xFFFF) */				\
M(NIX_LF_ALLOC,		0x8000, nix_lf_alloc,				\
				 nix_lf_alloc_req, nix_lf_alloc_rsp)	\
@@ -1570,13 +1581,32 @@ struct mcam_entry_mdata {
};

struct mcam_entry {
#define NPC_MAX_KWS_IN_KEY	8 /* Number of keywords in max keywidth */
#define NPC_MAX_KWS_IN_KEY	7 /* Number of keywords in max keywidth */
	u64	kw[NPC_MAX_KWS_IN_KEY];
	u64	kw_mask[NPC_MAX_KWS_IN_KEY];
	u64	action;
	u64	vtag_action;
};

struct cn20k_mcam_entry {
#define NPC_CN20K_MAX_KWS_IN_KEY	8
	u64	kw[NPC_CN20K_MAX_KWS_IN_KEY];
	u64	kw_mask[NPC_CN20K_MAX_KWS_IN_KEY];
	u64	action;
	u64	vtag_action;
};

struct npc_cn20k_mcam_write_entry_req {
	struct mbox_msghdr hdr;
	struct cn20k_mcam_entry entry_data;
	u16 entry;	 /* MCAM entry to write this match key */
	u16 cntr;	 /* Counter for this MCAM entry */
	u8  intf;	 /* Rx or Tx interface */
	u8  enable_entry;/* Enable this MCAM entry ? */
	u8  hw_prio;	 /* hardware priority, valid for cn20k */
	u64 reserved;	 /* reserved for future use */
};

struct npc_mcam_write_entry_req {
	struct mbox_msghdr hdr;
	struct mcam_entry entry_data;
@@ -1649,8 +1679,30 @@ struct npc_mcam_alloc_and_write_entry_req {
	u8  intf;	 /* Rx or Tx interface */
	u8  enable_entry;/* Enable this MCAM entry ? */
	u8  alloc_cntr;  /* Allocate counter and map ? */
	/* hardware priority, supported for cn20k */
	u8 hw_prio;
};

struct npc_cn20k_mcam_alloc_and_write_entry_req {
	struct mbox_msghdr hdr;
	struct cn20k_mcam_entry entry_data;
	u16 ref_entry;
	u8  ref_prio;    /* Lower or higher w.r.t ref_entry */
	u8  intf;	 /* Rx or Tx interface */
	u8  enable_entry;/* Enable this MCAM entry ? */
	u8  hw_prio;	 /* hardware priority, valid for cn20k */
	u16 reserved[4]; /* reserved for future use */
};

struct npc_cn20k_mcam_read_entry_rsp {
	struct mbox_msghdr hdr;
	struct cn20k_mcam_entry entry_data;
	u8 intf;
	u8 enable;
	u8 hw_prio; /* valid for cn20k */
};

struct npc_cn20k_mcam_read_base_rule_rsp {
	struct mbox_msghdr hdr;
	struct cn20k_mcam_entry entry;
};

struct npc_mcam_alloc_and_write_entry_rsp {
Loading