octeontx2-af: NPC: Clear Unicast rule on nixlf detach
authorHariprasad Kelam <hkelam@marvell.com>
Tue, 20 May 2025 06:09:52 +0000 (11:39 +0530)
committerDavid S. Miller <davem@davemloft.net>
Sun, 25 May 2025 14:06:53 +0000 (15:06 +0100)
The AF driver assigns reserved MCAM entries (for unicast, broadcast,
etc.) based on the NIXLF number. When a NIXLF is detached, these entries
are disabled.

For example,

         PF           NIXLF
        --------------------
         PF0             0
         SDP-VF0         1

If the user unbinds both PF0 and SDP-VF0 interfaces and then binds them in
reverse order

         PF            NIXLF
        ---------------------
         SDP-VF0         0
         PF0             1

In this scenario, the PF0 unicast entry is getting corrupted because
the MCAM entry contains stale data (SDP-VF0 ucast data)

This patch resolves the issue by clearing the unicast MCAM entry during
NIXLF detach

Signed-off-by: Hariprasad Kelam <hkelam@marvell.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/marvell/octeontx2/af/rvu.c
drivers/net/ethernet/marvell/octeontx2/af/rvu.h
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c

index 511eb5b2a2d434977d914a4cd63faf2d5f626909..19a5f0da4c7f38aad415aa6e81ae33f9e07a67ae 100644 (file)
@@ -1393,8 +1393,6 @@ static void rvu_detach_block(struct rvu *rvu, int pcifunc, int blktype)
        if (blkaddr < 0)
                return;
 
-       if (blktype == BLKTYPE_NIX)
-               rvu_nix_reset_mac(pfvf, pcifunc);
 
        block = &hw->block[blkaddr];
 
@@ -1407,6 +1405,10 @@ static void rvu_detach_block(struct rvu *rvu, int pcifunc, int blktype)
                if (lf < 0) /* This should never happen */
                        continue;
 
+               if (blktype == BLKTYPE_NIX) {
+                       rvu_nix_reset_mac(pfvf, pcifunc);
+                       rvu_npc_clear_ucast_entry(rvu, pcifunc, lf);
+               }
                /* Disable the LF */
                rvu_write64(rvu, blkaddr, block->lfcfg_reg |
                            (lf << block->lfshift), 0x00ULL);
index 147d7f5c1fcc0c91a0faad9fd4e905640a0f17d1..48f66292ad5c5f6f47c414edff674211467a2f60 100644 (file)
@@ -994,6 +994,8 @@ void rvu_npc_get_mcam_entry_alloc_info(struct rvu *rvu, u16 pcifunc,
 void rvu_npc_get_mcam_counter_alloc_info(struct rvu *rvu, u16 pcifunc,
                                         int blkaddr, int *alloc_cnt,
                                         int *enable_cnt);
+void rvu_npc_clear_ucast_entry(struct rvu *rvu, int pcifunc, int nixlf);
+
 bool is_npc_intf_tx(u8 intf);
 bool is_npc_intf_rx(u8 intf);
 bool is_npc_interface_valid(struct rvu *rvu, u8 intf);
index 6296a3cdabbb1f13b05ac42e7941caed462b91b3..da15bb4511788d643334a2805eb05692296ecf4a 100644 (file)
@@ -1107,6 +1107,7 @@ void npc_enadis_default_mce_entry(struct rvu *rvu, u16 pcifunc,
 static void npc_enadis_default_entries(struct rvu *rvu, u16 pcifunc,
                                       int nixlf, bool enable)
 {
+       struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
        struct npc_mcam *mcam = &rvu->hw->mcam;
        int index, blkaddr;
 
@@ -1115,9 +1116,12 @@ static void npc_enadis_default_entries(struct rvu *rvu, u16 pcifunc,
                return;
 
        /* Ucast MCAM match entry of this PF/VF */
-       index = npc_get_nixlf_mcam_index(mcam, pcifunc,
-                                        nixlf, NIXLF_UCAST_ENTRY);
-       npc_enable_mcam_entry(rvu, mcam, blkaddr, index, enable);
+       if (npc_is_feature_supported(rvu, BIT_ULL(NPC_DMAC),
+                                    pfvf->nix_rx_intf)) {
+               index = npc_get_nixlf_mcam_index(mcam, pcifunc,
+                                                nixlf, NIXLF_UCAST_ENTRY);
+               npc_enable_mcam_entry(rvu, mcam, blkaddr, index, enable);
+       }
 
        /* Nothing to do for VFs, on platforms where pkt replication
         * is not supported
@@ -3570,3 +3574,33 @@ int rvu_mbox_handler_npc_mcam_entry_stats(struct rvu *rvu,
 
        return 0;
 }
+
+void rvu_npc_clear_ucast_entry(struct rvu *rvu, int pcifunc, int nixlf)
+{
+       struct npc_mcam *mcam = &rvu->hw->mcam;
+       struct rvu_npc_mcam_rule *rule;
+       int ucast_idx, blkaddr;
+
+       blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
+       if (blkaddr < 0)
+               return;
+
+       ucast_idx = npc_get_nixlf_mcam_index(mcam, pcifunc,
+                                            nixlf, NIXLF_UCAST_ENTRY);
+
+       npc_enable_mcam_entry(rvu, mcam, blkaddr, ucast_idx, false);
+
+       npc_set_mcam_action(rvu, mcam, blkaddr, ucast_idx, 0);
+
+       npc_clear_mcam_entry(rvu, mcam, blkaddr, ucast_idx);
+
+       mutex_lock(&mcam->lock);
+       list_for_each_entry(rule, &mcam->mcam_rules, list) {
+               if (rule->entry == ucast_idx) {
+                       list_del(&rule->list);
+                       kfree(rule);
+                       break;
+               }
+       }
+       mutex_unlock(&mcam->lock);
+}