octeontx2-af: NPC: Clear Unicast rule on nixlf detach

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>
This commit is contained in:
Hariprasad Kelam
2025-05-20 11:39:52 +05:30
committed by David S. Miller
parent 819aad967d
commit bb91f7547f
3 changed files with 43 additions and 5 deletions

View 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);

View 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);

View 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);
}