octeontx2-af: npc: cn20k: Tear down default MCAM rules explicitly on free

npc_cn20k_dft_rules_free() used the NPC MCAM mbox "free all" path, which
does not match how cn20k tracks default-rule MCAM slots indexes.

Resolve the default-rule indices, then for each valid slot clear the bitmap
entry, drop the PF/VF map, disable the MCAM line, clear the target
function, and npc_cn20k_idx_free(). Remove any matching software mcam_rules
nodes. On hard failure from idx_free, WARN and stop so the box stays up for
analysis.

In npc_mcam_free_all_entries(), prefetch the same default-rule indices and,
on cn20k, skip bitmap clear and idx_free when the scanned entry is one of
those reserved defaults (they are released by npc_cn20k_dft_rules_free).

Fixes: 09d3b7a140 ("octeontx2-af: npc: cn20k: Allocate default MCAM indexes")
Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
Link: https://patch.msgid.link/20260429022722.1110289-10-rkannoth@marvell.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Ratheesh Kannoth
2026-04-29 07:57:21 +05:30
committed by Jakub Kicinski
parent afb474bd4f
commit 013717353c
2 changed files with 82 additions and 28 deletions

View File

@@ -4178,11 +4178,11 @@ static bool npc_is_cgx_or_lbk(struct rvu *rvu, u16 pcifunc)
void npc_cn20k_dft_rules_free(struct rvu *rvu, u16 pcifunc)
{
struct npc_mcam_free_entry_req free_req = { 0 };
struct npc_mcam *mcam = &rvu->hw->mcam;
u16 ptr[4] = {[0 ... 3] = USHRT_MAX};
struct rvu_npc_mcam_rule *rule, *tmp;
unsigned long index;
struct msg_rsp rsp;
u16 ptr[4];
int rc, i;
int blkaddr, rc, i;
void *map;
if (!npc_priv.init_done)
@@ -4240,14 +4240,43 @@ void npc_cn20k_dft_rules_free(struct rvu *rvu, u16 pcifunc)
}
free_rules:
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
if (blkaddr < 0)
return;
for (int i = 0; i < 4; i++) {
if (ptr[i] == USHRT_MAX)
continue;
free_req.hdr.pcifunc = pcifunc;
free_req.all = 1;
rc = rvu_mbox_handler_npc_mcam_free_entry(rvu, &free_req, &rsp);
if (rc)
dev_err(rvu->dev,
"%s: Error deleting default entries (pcifunc=%#x\n",
__func__, pcifunc);
mutex_lock(&mcam->lock);
npc_mcam_clear_bit(mcam, ptr[i]);
mcam->entry2pfvf_map[ptr[i]] = NPC_MCAM_INVALID_MAP;
npc_cn20k_enable_mcam_entry(rvu, blkaddr, ptr[i], false);
mcam->entry2target_pffunc[ptr[i]] = 0x0;
mutex_unlock(&mcam->lock);
rc = npc_cn20k_idx_free(rvu, &ptr[i], 1);
if (rc) {
/* Non recoverable error. Let us WARN and return. Keep system alive to
* enable debugging
*/
WARN(1, "%s Error deleting default entries (pcifunc=%#x) mcam_idx=%u\n",
__func__, pcifunc, ptr[i]);
return;
}
}
mutex_lock(&mcam->lock);
list_for_each_entry_safe(rule, tmp, &mcam->mcam_rules, list) {
for (int i = 0; i < 4; i++) {
if (ptr[i] != rule->entry)
continue;
list_del(&rule->list);
kfree(rule);
break;
}
}
mutex_unlock(&mcam->lock);
}
int npc_cn20k_dft_rules_alloc(struct rvu *rvu, u16 pcifunc)

View File

@@ -2521,33 +2521,58 @@ void npc_mcam_clear_bit(struct npc_mcam *mcam, u16 index)
static void npc_mcam_free_all_entries(struct rvu *rvu, struct npc_mcam *mcam,
int blkaddr, u16 pcifunc)
{
u16 dft_idxs[NPC_DFT_RULE_MAX_ID] = {[0 ... NPC_DFT_RULE_MAX_ID - 1] = USHRT_MAX};
bool cn20k_dft_rl;
u16 index, cntr;
int rc;
npc_cn20k_dft_rules_idx_get(rvu, pcifunc,
&dft_idxs[NPC_DFT_RULE_BCAST_ID],
&dft_idxs[NPC_DFT_RULE_MCAST_ID],
&dft_idxs[NPC_DFT_RULE_PROMISC_ID],
&dft_idxs[NPC_DFT_RULE_UCAST_ID]);
/* Scan all MCAM entries and free the ones mapped to 'pcifunc' */
for (index = 0; index < mcam->bmap_entries; index++) {
if (mcam->entry2pfvf_map[index] == pcifunc) {
if (mcam->entry2pfvf_map[index] != pcifunc)
continue;
cn20k_dft_rl = false;
if (is_cn20k(rvu->pdev)) {
if (dft_idxs[NPC_DFT_RULE_BCAST_ID] == index ||
dft_idxs[NPC_DFT_RULE_MCAST_ID] == index ||
dft_idxs[NPC_DFT_RULE_PROMISC_ID] == index ||
dft_idxs[NPC_DFT_RULE_UCAST_ID] == index) {
cn20k_dft_rl = true;
}
}
/* Disable the entry */
npc_enable_mcam_entry(rvu, mcam, blkaddr, index, false);
if (!cn20k_dft_rl) {
mcam->entry2pfvf_map[index] = NPC_MCAM_INVALID_MAP;
/* Free the entry in bitmap */
npc_mcam_clear_bit(mcam, index);
/* Disable the entry */
npc_enable_mcam_entry(rvu, mcam, blkaddr, index, false);
/* Update entry2counter mapping */
cntr = mcam->entry2cntr_map[index];
if (cntr != NPC_MCAM_INVALID_MAP)
npc_unmap_mcam_entry_and_cntr(rvu, mcam,
blkaddr, index,
cntr);
mcam->entry2target_pffunc[index] = 0x0;
if (is_cn20k(rvu->pdev)) {
rc = npc_cn20k_idx_free(rvu, &index, 1);
if (rc)
dev_err(rvu->dev,
"Failed to free mcam idx=%u pcifunc=%#x\n",
index, pcifunc);
}
}
/* Update entry2counter mapping */
cntr = mcam->entry2cntr_map[index];
if (cntr != NPC_MCAM_INVALID_MAP)
npc_unmap_mcam_entry_and_cntr(rvu, mcam,
blkaddr, index,
cntr);
if (!is_cn20k(rvu->pdev) || cn20k_dft_rl)
continue;
rc = npc_cn20k_idx_free(rvu, &index, 1);
if (rc)
dev_err(rvu->dev,
"Failed to free mcam idx=%u pcifunc=%#x\n",
index, pcifunc);
}
}