octeontx2-af: npc: cn20k: Propagate MCAM key-type errors on cn20k

npc_mcam_idx_2_key_type() can fail; callers used to ignore it and still
used kw_type when enabling, configuring, copying, and reading MCAM entries.
That could program or decode hardware with an undefined key type.

Return -EINVAL when key-type lookup fails. Return -EINVAL from
npc_cn20k_copy_mcam_entry() when src and dest key types differ instead of
failing silently.

Change npc_cn20k_{enable,config,copy,read}_mcam_entry() to return int on
success or error. Thread those errors through the cn20k MCAM write and read
mbox handlers, the cn20k baseline steer read path, NPC defrag move
(disable/copy/enable with dev_err and -EFAULT), and the DMAC update path in
rvu_npc_fs.c.

Make npc_copy_mcam_entry() return int so the cn20k branch can return
npc_cn20k_copy_mcam_entry() without a void/int mismatch, and fail
NPC_MCAM_SHIFT_ENTRY when copy fails.

Cc: Suman Ghosh <sumang@marvell.com>
Cc: Dan Carpenter <error27@gmail.com>
Fixes: 6d1e70282f ("octeontx2-af: npc: cn20k: Use common APIs")
Link: https://lore.kernel.org/netdev/adiQJvuKlEhq2ILx@stanley.mountain/
Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
Link: https://patch.msgid.link/20260429022722.1110289-2-rkannoth@marvell.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Ratheesh Kannoth 2026-04-29 07:57:13 +05:30 committed by Jakub Kicinski
parent 75df490c9e
commit aaadccde31
4 changed files with 125 additions and 57 deletions

View File

@ -798,7 +798,7 @@ void npc_cn20k_load_mkex_profile(struct rvu *rvu, int blkaddr,
iounmap(mkex_prfl_addr);
}
void
int
npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkaddr,
int index, bool enable)
{
@ -808,7 +808,9 @@ npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkaddr,
u64 cfg, hw_prio;
u8 kw_type;
npc_mcam_idx_2_key_type(rvu, index, &kw_type);
if (npc_mcam_idx_2_key_type(rvu, index, &kw_type))
return -EINVAL;
if (kw_type == NPC_MCAM_KEY_X2) {
cfg = rvu_read64(rvu, blkaddr,
NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(mcam_idx,
@ -819,7 +821,7 @@ npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkaddr,
rvu_write64(rvu, blkaddr,
NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(mcam_idx, bank),
cfg);
return;
return 0;
}
/* For NPC_CN20K_MCAM_KEY_X4 keys, both the banks
@ -836,6 +838,8 @@ npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkaddr,
NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(mcam_idx, bank),
cfg);
}
return 0;
}
void
@ -1042,9 +1046,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 cn20k_mcam_entry *entry,
bool enable, u8 hw_prio, u8 req_kw_type)
int npc_cn20k_config_mcam_entry(struct rvu *rvu, int blkaddr, int index,
u8 intf, struct cn20k_mcam_entry *entry,
bool enable, u8 hw_prio, u8 req_kw_type)
{
struct npc_mcam *mcam = &rvu->hw->mcam;
int mcam_idx = index % mcam->banksize;
@ -1052,10 +1056,13 @@ void npc_cn20k_config_mcam_entry(struct rvu *rvu, int blkaddr, int index,
int kw = 0;
u8 kw_type;
/* Disable before mcam entry update */
npc_cn20k_enable_mcam_entry(rvu, blkaddr, index, false);
if (npc_mcam_idx_2_key_type(rvu, index, &kw_type))
return -EINVAL;
/* Disable before mcam entry update */
if (npc_cn20k_enable_mcam_entry(rvu, blkaddr, index, false))
return -EINVAL;
npc_mcam_idx_2_key_type(rvu, index, &kw_type);
/* CAM1 takes the comparison value and
* CAM0 specifies match for a bit in key being '0' or '1' or 'dontcare'.
* CAM1<n> = 0 & CAM0<n> = 1 => match if key<n> = 0
@ -1120,9 +1127,11 @@ void npc_cn20k_config_mcam_entry(struct rvu *rvu, int blkaddr, int index,
/* PF installing VF rule */
npc_cn20k_set_mcam_bank_cfg(rvu, blkaddr, mcam_idx, bank,
kw_type, enable, hw_prio);
return 0;
}
void npc_cn20k_copy_mcam_entry(struct rvu *rvu, int blkaddr, u16 src, u16 dest)
int npc_cn20k_copy_mcam_entry(struct rvu *rvu, int blkaddr, u16 src, u16 dest)
{
struct npc_mcam *mcam = &rvu->hw->mcam;
u64 cfg, sreg, dreg, soff, doff;
@ -1132,10 +1141,15 @@ void npc_cn20k_copy_mcam_entry(struct rvu *rvu, int blkaddr, u16 src, u16 dest)
dbank = npc_get_bank(mcam, dest);
sbank = npc_get_bank(mcam, src);
npc_mcam_idx_2_key_type(rvu, src, &src_kwtype);
npc_mcam_idx_2_key_type(rvu, dest, &dest_kwtype);
if (npc_mcam_idx_2_key_type(rvu, src, &src_kwtype))
return -EINVAL;
if (npc_mcam_idx_2_key_type(rvu, dest, &dest_kwtype))
return -EINVAL;
if (src_kwtype != dest_kwtype)
return;
return -EINVAL;
src &= (mcam->banksize - 1);
dest &= (mcam->banksize - 1);
@ -1170,6 +1184,8 @@ void npc_cn20k_copy_mcam_entry(struct rvu *rvu, int blkaddr, u16 src, u16 dest)
if (src_kwtype == NPC_MCAM_KEY_X2)
break;
}
return 0;
}
static void npc_cn20k_fill_entryword(struct cn20k_mcam_entry *entry, int idx,
@ -1179,16 +1195,17 @@ static void npc_cn20k_fill_entryword(struct cn20k_mcam_entry *entry, int idx,
entry->kw_mask[idx] = cam1 ^ cam0;
}
void npc_cn20k_read_mcam_entry(struct rvu *rvu, int blkaddr, u16 index,
struct cn20k_mcam_entry *entry,
u8 *intf, u8 *ena, u8 *hw_prio)
int npc_cn20k_read_mcam_entry(struct rvu *rvu, int blkaddr, u16 index,
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;
int kw = 0, bank;
u8 kw_type;
npc_mcam_idx_2_key_type(rvu, index, &kw_type);
if (npc_mcam_idx_2_key_type(rvu, index, &kw_type))
return -EINVAL;
bank = npc_get_bank(mcam, index);
index &= (mcam->banksize - 1);
@ -1298,6 +1315,8 @@ void npc_cn20k_read_mcam_entry(struct rvu *rvu, int blkaddr, u16 index,
cfg = rvu_read64(rvu, blkaddr,
NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(index, 0, 1));
entry->vtag_action = cfg;
return 0;
}
int rvu_mbox_handler_npc_cn20k_mcam_write_entry(struct rvu *rvu,
@ -1335,11 +1354,10 @@ int rvu_mbox_handler_npc_cn20k_mcam_write_entry(struct rvu *rvu,
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, req->req_kw_type);
rc = npc_cn20k_config_mcam_entry(rvu, blkaddr, req->entry, nix_intf,
&req->entry_data, req->enable_entry,
req->hw_prio, req->req_kw_type);
rc = 0;
exit:
mutex_unlock(&mcam->lock);
return rc;
@ -1361,11 +1379,13 @@ int rvu_mbox_handler_npc_cn20k_mcam_read_entry(struct rvu *rvu,
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);
if (rc)
goto fail;
rc = npc_cn20k_read_mcam_entry(rvu, blkaddr, req->entry,
&rsp->entry_data, &rsp->intf,
&rsp->enable, &rsp->hw_prio);
fail:
mutex_unlock(&mcam->lock);
return rc;
}
@ -1375,11 +1395,13 @@ int rvu_mbox_handler_npc_cn20k_mcam_alloc_and_write_entry(struct rvu *rvu,
struct npc_mcam_alloc_and_write_entry_rsp *rsp)
{
struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, req->hdr.pcifunc);
struct npc_mcam_free_entry_req free_req = { 0 };
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;
struct msg_rsp free_rsp;
int blkaddr, rc, err;
u8 nix_intf;
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
@ -1415,12 +1437,23 @@ int rvu_mbox_handler_npc_cn20k_mcam_alloc_and_write_entry(struct rvu *rvu,
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, req->req_kw_type);
rc = npc_cn20k_config_mcam_entry(rvu, blkaddr, entry, nix_intf,
&req->entry_data, req->enable_entry,
req->hw_prio, req->req_kw_type);
mutex_unlock(&mcam->lock);
if (rc) {
free_req.hdr.pcifunc = req->hdr.pcifunc;
free_req.entry = entry_rsp.entry;
err = rvu_mbox_handler_npc_mcam_free_entry(rvu, &free_req, &free_rsp);
if (err)
dev_err(rvu->dev,
"%s: Error to free mcam idx %u\n",
__func__, entry_rsp.entry);
return rc;
}
rsp->entry = entry_rsp.entry;
return 0;
}
@ -1480,9 +1513,9 @@ int rvu_mbox_handler_npc_cn20k_read_base_steer_rule(struct rvu *rvu,
read_entry:
/* Read the mcam entry */
npc_cn20k_read_mcam_entry(rvu, blkaddr, index,
&rsp->entry, &intf,
&enable, &hw_prio);
rc = npc_cn20k_read_mcam_entry(rvu, blkaddr, index,
&rsp->entry, &intf,
&enable, &hw_prio);
mutex_unlock(&mcam->lock);
out:
return rc;
@ -3607,9 +3640,30 @@ int npc_defrag_move_vdx_to_free(struct rvu *rvu,
NPC_AF_CN20K_MCAMEX_BANKX_STAT_EXT(midx,
bank));
npc_cn20k_enable_mcam_entry(rvu, blkaddr, old_midx, false);
npc_cn20k_copy_mcam_entry(rvu, blkaddr, old_midx, new_midx);
npc_cn20k_enable_mcam_entry(rvu, blkaddr, new_midx, true);
/* If bug happened during copy/enable mcam, then there is a bug in allocation
* algorithm itself. There is no point in rewinding and returning, as it
* will face further issue. Return error after printing error
*/
if (npc_cn20k_enable_mcam_entry(rvu, blkaddr, old_midx, false)) {
dev_err(rvu->dev,
"%s: Error happened while disabling old_mid=%u\n",
__func__, old_midx);
return -EFAULT;
}
if (npc_cn20k_copy_mcam_entry(rvu, blkaddr, old_midx, new_midx)) {
dev_err(rvu->dev,
"%s: Error happened while copying old_midx=%u new_midx=%u\n",
__func__, old_midx, new_midx);
return -EFAULT;
}
if (npc_cn20k_enable_mcam_entry(rvu, blkaddr, new_midx, true)) {
dev_err(rvu->dev,
"%s: Error happened while enabling new_mid=%u\n",
__func__, new_midx);
return -EFAULT;
}
midx = new_midx % mcam->banksize;
bank = new_midx / mcam->banksize;

View File

@ -320,16 +320,16 @@ void npc_cn20k_dft_rules_free(struct rvu *rvu, u16 pcifunc);
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 cn20k_mcam_entry *entry,
bool enable, u8 hw_prio, u8 req_kw_type);
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 cn20k_mcam_entry *entry, u8 *intf,
u8 *ena, u8 *hw_prio);
int npc_cn20k_config_mcam_entry(struct rvu *rvu, int blkaddr, int index,
u8 intf, struct cn20k_mcam_entry *entry,
bool enable, u8 hw_prio, u8 req_kw_type);
int npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkaddr,
int index, bool enable);
int npc_cn20k_copy_mcam_entry(struct rvu *rvu, int blkaddr,
u16 src, u16 dest);
int npc_cn20k_read_mcam_entry(struct rvu *rvu, int blkaddr, u16 index,
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);

View File

@ -241,7 +241,10 @@ void npc_enable_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
if (index < 0 || index >= mcam->banksize * mcam->banks)
return;
return npc_cn20k_enable_mcam_entry(rvu, blkaddr, index, enable);
if (npc_cn20k_enable_mcam_entry(rvu, blkaddr, index, enable))
dev_err(rvu->dev, "Error to %s mcam %u entry\n",
enable ? "enable" : "disable", index);
return;
}
index &= (mcam->banksize - 1);
@ -589,8 +592,8 @@ void npc_read_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
NPC_AF_MCAMEX_BANKX_CFG(src, sbank)) & 1;
}
static void npc_copy_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
int blkaddr, u16 src, u16 dest)
static int npc_copy_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
int blkaddr, u16 src, u16 dest)
{
int dbank = npc_get_bank(mcam, dest);
int sbank = npc_get_bank(mcam, src);
@ -630,6 +633,7 @@ static void npc_copy_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
NPC_AF_MCAMEX_BANKX_CFG(src, sbank));
rvu_write64(rvu, blkaddr,
NPC_AF_MCAMEX_BANKX_CFG(dest, dbank), cfg);
return 0;
}
u64 npc_get_mcam_action(struct rvu *rvu, struct npc_mcam *mcam,
@ -3266,7 +3270,10 @@ int rvu_mbox_handler_npc_mcam_shift_entry(struct rvu *rvu,
npc_enable_mcam_entry(rvu, mcam, blkaddr, new_entry, false);
/* Copy rule from old entry to new entry */
npc_copy_mcam_entry(rvu, mcam, blkaddr, old_entry, new_entry);
if (npc_copy_mcam_entry(rvu, mcam, blkaddr, old_entry, new_entry)) {
rc = NPC_MCAM_INVALID_REQ;
break;
}
/* Copy counter mapping, if any */
cntr = mcam->entry2cntr_map[old_entry];
@ -3284,7 +3291,8 @@ int rvu_mbox_handler_npc_mcam_shift_entry(struct rvu *rvu,
/* If shift has failed then report the failed index */
if (index != req->shift_count) {
rc = NPC_MCAM_PERM_DENIED;
if (!rc)
rc = NPC_MCAM_PERM_DENIED;
rsp->failed_entry_idx = index;
}

View File

@ -1980,13 +1980,15 @@ static int npc_update_dmac_value(struct rvu *rvu, int npcblkaddr,
ether_addr_copy(rule->packet.dmac, pfvf->mac_addr);
if (is_cn20k(rvu->pdev))
npc_cn20k_read_mcam_entry(rvu, npcblkaddr, rule->entry,
cn20k_entry, &intf,
&enable, &hw_prio);
else
if (is_cn20k(rvu->pdev)) {
if (npc_cn20k_read_mcam_entry(rvu, npcblkaddr, rule->entry,
cn20k_entry, &intf,
&enable, &hw_prio))
return -EINVAL;
} else {
npc_read_mcam_entry(rvu, mcam, npcblkaddr, rule->entry,
entry, &intf, &enable);
}
npc_update_entry(rvu, NPC_DMAC, &mdata,
ether_addr_to_u64(pfvf->mac_addr), 0,
@ -2038,8 +2040,12 @@ void npc_mcam_enable_flows(struct rvu *rvu, u16 target)
continue;
}
if (rule->vfvlan_cfg)
npc_update_dmac_value(rvu, blkaddr, rule, pfvf);
if (rule->vfvlan_cfg) {
if (npc_update_dmac_value(rvu, blkaddr, rule, pfvf))
dev_err(rvu->dev,
"Update dmac failed for %u, target=%#x\n",
rule->entry, target);
}
if (rule->rx_action.op == NIX_RX_ACTION_DEFAULT) {
if (!def_ucast_rule)