]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
octeontx2-af: npc: cn20k: Tear down default MCAM rules explicitly on free
authorRatheesh Kannoth <rkannoth@marvell.com>
Wed, 29 Apr 2026 02:27:21 +0000 (07:57 +0530)
committerJakub Kicinski <kuba@kernel.org>
Fri, 1 May 2026 01:50:17 +0000 (18:50 -0700)
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: 09d3b7a1403f ("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>
drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c

index b3f34b84c1149930b6e7d5db6ecbc0279d941c0c..1129565a01bdf46108a9c5697c4f66d8dcaaaf84 100644 (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)
index 44ca65efc80f094dc3069af93a21f85c7f0d4f8b..5d349d131fdb63a4ed44d84d455be7eb4e8d320b 100644 (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);
        }
 }