mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-16 09:02:21 -04:00
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:
committed by
Jakub Kicinski
parent
afb474bd4f
commit
013717353c
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user