octeontx2-af: npc: cn20k: Index management

In CN20K silicon, the MCAM is divided vertically into two banks.
Each bank has a depth of 8192.

The MCAM is divided horizontally into 32 subbanks, with each subbank
having a depth of 256.

Each subbank can accommodate either x2 keys or x4 keys. x2 keys are
256 bits in size, and x4 keys are 512 bits in size.

    Bank1                   Bank0
    |-----------------------------|
    |               |             | subbank 31 { depth 256 }
    |               |             |
    |-----------------------------|
    |               |             | subbank 30
    |               |             |
    ------------------------------
    ...............................

    |-----------------------------|
    |               |             | subbank 0
    |               |             |
    ------------------------------|

This patch implements the following allocation schemes in NPC.
The allocation API accepts reference (ref), limit, contig, priority,
and count values. For example, specifying ref=100, limit=200,
contig=1, priority=LOW, and count=20 will allocate 20 contiguous
MCAM entries between entries 100 and 200.

1. Contiguous allocation with ref, limit, and priority.
2. Non-contiguous allocation with ref, limit, and priority.
3. Non-contiguous allocation without ref.
4. Contiguous allocation without ref.

Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
Link: https://patch.msgid.link/20260224080009.4147301-2-rkannoth@marvell.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
master
Ratheesh Kannoth 2026-02-24 13:29:57 +05:30 committed by Jakub Kicinski
parent ded4a02e7d
commit 1396771b0b
10 changed files with 1943 additions and 6 deletions

View File

@ -13,4 +13,4 @@ rvu_af-y := cgx.o rvu.o rvu_cgx.o rvu_npa.o rvu_nix.o \
rvu_cpt.o rvu_devlink.o rpm.o rvu_cn10k.o rvu_switch.o \
rvu_sdp.o rvu_npc_hash.o mcs.o mcs_rvu_if.o mcs_cnf10kb.o \
rvu_rep.o cn20k/mbox_init.o cn20k/nix.o cn20k/debugfs.o \
cn20k/npa.o
cn20k/npa.o cn20k/npc.o

View File

@ -11,7 +11,19 @@
#include <linux/pci.h>
#include "struct.h"
#include "rvu.h"
#include "debugfs.h"
#include "cn20k/npc.h"
int npc_cn20k_debugfs_init(struct rvu *rvu)
{
return 0;
}
void npc_cn20k_debugfs_deinit(struct rvu *rvu)
{
debugfs_remove_recursive(rvu->rvu_dbg.npc);
}
void print_nix_cn20k_sq_ctx(struct seq_file *m,
struct nix_cn20k_sq_ctx_s *sq_ctx)

View File

@ -16,6 +16,9 @@
#include "struct.h"
#include "../mbox.h"
int npc_cn20k_debugfs_init(struct rvu *rvu);
void npc_cn20k_debugfs_deinit(struct rvu *rvu);
void print_nix_cn20k_sq_ctx(struct seq_file *m,
struct nix_cn20k_sq_ctx_s *sq_ctx);
void print_nix_cn20k_cq_ctx(struct seq_file *m,

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,110 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Marvell RVU Admin Function driver
*
* Copyright (C) 2026 Marvell.
*
*/
#ifndef NPC_CN20K_H
#define NPC_CN20K_H
#define MAX_NUM_BANKS 2
#define MAX_NUM_SUB_BANKS 32
#define MAX_SUBBANK_DEPTH 256
/**
* enum npc_subbank_flag - NPC subbank status
*
* subbank flag indicates whether the subbank is free
* or used.
*
* @NPC_SUBBANK_FLAG_UNINIT: Subbank is not initialized.
* @NPC_SUBBANK_FLAG_FREE: Subbank is free.
* @NPC_SUBBANK_FLAG_USED: Subbank is used.
*/
enum npc_subbank_flag {
NPC_SUBBANK_FLAG_UNINIT,
NPC_SUBBANK_FLAG_FREE = BIT(0),
NPC_SUBBANK_FLAG_USED = BIT(1),
};
/**
* struct npc_subbank - Subbank fields.
* @b0b: Subbanks bottom index for bank0
* @b1b: Subbanks bottom index for bank1
* @b0t: Subbanks top index for bank0
* @b1t: Subbanks top index for bank1
* @flags: Subbank flags
* @lock: Mutex lock for flags and rsrc mofiication
* @b0map: Bitmap map for bank0 indexes
* @b1map: Bitmap map for bank1 indexes
* @idx: Subbank index
* @arr_idx: Index to the free array or used array
* @free_cnt: Number of free slots in the subbank.
* @key_type: X4 or X2 subbank.
*
* MCAM resource is divided horizontally into multiple subbanks and
* Resource allocation from each subbank is managed by this data
* structure.
*/
struct npc_subbank {
u16 b0t, b0b, b1t, b1b;
enum npc_subbank_flag flags;
struct mutex lock; /* Protect subbank resources */
DECLARE_BITMAP(b0map, MAX_SUBBANK_DEPTH);
DECLARE_BITMAP(b1map, MAX_SUBBANK_DEPTH);
u16 idx;
u16 arr_idx;
u16 free_cnt;
u8 key_type;
};
/**
* struct npc_priv_t - NPC private structure.
* @bank_depth: Total entries in each bank.
* @num_banks: Number of banks.
* @num_subbanks: Number of subbanks.
* @subbank_depth: Depth of subbank.
* @kw: Kex configured key type.
* @sb: Subbank array.
* @xa_sb_used: Array of used subbanks.
* @xa_sb_free: Array of free subbanks.
* @xa_pf2idx_map: PF to mcam index map.
* @xa_idx2pf_map: Mcam index to PF map.
* @xa_pf_map: Pcifunc to index map.
* @pf_cnt: Number of PFs.
* @init_done: Indicates MCAM initialization is done.
*
* This structure is populated during probing time by reading
* HW csr registers.
*/
struct npc_priv_t {
int bank_depth;
const int num_banks;
int num_subbanks;
int subbank_depth;
u8 kw;
struct npc_subbank *sb;
struct xarray xa_sb_used;
struct xarray xa_sb_free;
struct xarray *xa_pf2idx_map;
struct xarray xa_idx2pf_map;
struct xarray xa_pf_map;
int pf_cnt;
bool init_done;
};
struct rvu;
struct npc_priv_t *npc_priv_get(void);
int npc_cn20k_init(struct rvu *rvu);
void npc_cn20k_deinit(struct rvu *rvu);
void npc_cn20k_subbank_calc_free(struct rvu *rvu, int *x2_free,
int *x4_free, int *sb_free);
int npc_cn20k_ref_idx_alloc(struct rvu *rvu, int pcifunc, int key_type,
int prio, u16 *mcam_idx, int ref, int limit,
bool contig, int count);
int npc_cn20k_idx_free(struct rvu *rvu, u16 *mcam_idx, int count);
#endif /* NPC_CN20K_H */

View File

@ -77,5 +77,8 @@
#define RVU_MBOX_VF_INT_ENA_W1S (0x30)
#define RVU_MBOX_VF_INT_ENA_W1C (0x38)
/* NPC registers */
#define NPC_AF_MCAM_SECTIONX_CFG_EXT(a) (0xf000000ull | (a) << 3)
#define RVU_MBOX_VF_VFAF_TRIGX(a) (0x2000 | (a) << 3)
#endif /* RVU_MBOX_REG_H */

View File

@ -177,10 +177,6 @@ enum nix_scheduler {
#define NIX_TX_ACTIONOP_MCAST (0x3ull)
#define NIX_TX_ACTIONOP_DROP_VIOL (0x5ull)
#define NPC_MCAM_KEY_X1 0
#define NPC_MCAM_KEY_X2 1
#define NPC_MCAM_KEY_X4 2
#define NIX_INTFX_RX(a) (0x0ull | (a) << 1)
#define NIX_INTFX_TX(a) (0x1ull | (a) << 1)

View File

@ -52,6 +52,14 @@
#define MBOX_DIR_PFVF_UP 6 /* PF sends messages to VF */
#define MBOX_DIR_VFPF_UP 7 /* VF replies to PF */
enum {
NPC_MCAM_KEY_X1 = 0,
NPC_MCAM_KEY_DYN = NPC_MCAM_KEY_X1,
NPC_MCAM_KEY_X2,
NPC_MCAM_KEY_X4,
NPC_MCAM_KEY_MAX,
};
enum {
TYPE_AFVF,
TYPE_AFPF,
@ -275,6 +283,8 @@ M(NPC_GET_FIELD_HASH_INFO, 0x6013, npc_get_field_hash_info,
M(NPC_GET_FIELD_STATUS, 0x6014, npc_get_field_status, \
npc_get_field_status_req, \
npc_get_field_status_rsp) \
M(NPC_CN20K_MCAM_GET_FREE_COUNT, 0x6015, npc_cn20k_get_fcnt, \
msg_req, npc_cn20k_get_fcnt_rsp) \
/* NIX mbox IDs (range 0x8000 - 0xFFFF) */ \
M(NIX_LF_ALLOC, 0x8000, nix_lf_alloc, \
nix_lf_alloc_req, nix_lf_alloc_rsp) \
@ -1797,6 +1807,14 @@ struct npc_mcam_read_entry_rsp {
u8 enable;
};
/* Available entries to use */
struct npc_cn20k_get_fcnt_rsp {
struct mbox_msghdr hdr;
int free_x2;
int free_x4;
int free_subbanks;
};
struct npc_mcam_read_base_rule_rsp {
struct mbox_msghdr hdr;
struct mcam_entry entry;

View File

@ -3745,6 +3745,9 @@ static void rvu_dbg_npc_init(struct rvu *rvu)
debugfs_create_file("rx_miss_act_stats", 0444, rvu->rvu_dbg.npc, rvu,
&rvu_dbg_npc_rx_miss_act_fops);
if (is_cn20k(rvu->pdev))
npc_cn20k_debugfs_init(rvu);
if (!rvu->hw->cap.npc_exact_match_enabled)
return;

View File

@ -16,6 +16,7 @@
#include "cgx.h"
#include "npc_profile.h"
#include "rvu_npc_hash.h"
#include "cn20k/npc.h"
#define RSVD_MCAM_ENTRIES_PER_PF 3 /* Broadcast, Promisc and AllMulticast */
#define RSVD_MCAM_ENTRIES_PER_NIXLF 1 /* Ucast for LFs */
@ -2162,6 +2163,9 @@ int rvu_npc_init(struct rvu *rvu)
npc_load_mkex_profile(rvu, blkaddr, def_pfl_name);
}
if (is_cn20k(rvu->pdev))
return npc_cn20k_init(rvu);
return 0;
}
@ -2177,6 +2181,9 @@ void rvu_npc_freemem(struct rvu *rvu)
else
kfree(rvu->kpu_fwdata);
mutex_destroy(&mcam->lock);
if (is_cn20k(rvu->pdev))
npc_cn20k_deinit(rvu);
}
void rvu_npc_get_mcam_entry_alloc_info(struct rvu *rvu, u16 pcifunc,
@ -3032,7 +3039,6 @@ static int __npc_mcam_alloc_counter(struct rvu *rvu,
if (!req->contig && req->count > NPC_MAX_NONCONTIG_COUNTERS)
return NPC_MCAM_INVALID_REQ;
/* Check if unused counters are available or not */
if (!rvu_rsrc_free_count(&mcam->counters)) {
return NPC_MCAM_ALLOC_FAILED;