mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 18:13:41 +02:00
Merge branch 'npc-hw-block-support-for-cn20k'
Ratheesh Kannoth says: ==================== NPC HW block support for cn20k This patchset adds comprehensive support for the CN20K NPC architecture. CN20K introduces significant changes in MCAM layout, parser design, KPM/KPU mapping, index management, virtual index handling, and dynamic rule installation. The patches update the AF, PF/VF, and common layers to correctly support these new capabilities while preserving compatibility with previous silicon variants. MCAM on CN20K differs from older designs: the hardware now contains two vertical banks of depth 8192, and thirty-two horizontal subbanks of depth 256. Each subbank can be configured as x2 or x4, enabling 256-bit or 512-bit key storage. Several allocation models are added to support this layout, including contiguous and non-contiguous allocation with or without reference ranges and priorities. Parser and extraction logic are also enhanced. CN20K introduces a new profile model where up to twenty-four extractors may be configured for each parsing profile. A new KPM profile scheme is added, grouping sixteen KPUs into eight KPM profiles, each formed by two KPUs. Support is added for default index allocation for CN20K-specific MCAM entry structures, virtual index allocation, improved defragmentation, and TC rule installation by allowing the AF driver to determine required x2/x4 rule width during flow install. ==================== Link: https://patch.msgid.link/20260224080009.4147301-1-rkannoth@marvell.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
d578b47293
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -11,7 +11,280 @@
|
|||
#include <linux/pci.h>
|
||||
|
||||
#include "struct.h"
|
||||
#include "rvu.h"
|
||||
#include "debugfs.h"
|
||||
#include "cn20k/npc.h"
|
||||
|
||||
static int npc_mcam_layout_show(struct seq_file *s, void *unused)
|
||||
{
|
||||
int i, j, sbd, idx0, idx1, vidx0, vidx1;
|
||||
struct npc_priv_t *npc_priv;
|
||||
char buf0[32], buf1[32];
|
||||
struct npc_subbank *sb;
|
||||
unsigned int bw0, bw1;
|
||||
bool v0, v1;
|
||||
int pf1, pf2;
|
||||
bool e0, e1;
|
||||
void *map;
|
||||
|
||||
npc_priv = s->private;
|
||||
|
||||
sbd = npc_priv->subbank_depth;
|
||||
|
||||
for (i = npc_priv->num_subbanks - 1; i >= 0; i--) {
|
||||
sb = &npc_priv->sb[i];
|
||||
mutex_lock(&sb->lock);
|
||||
|
||||
if (sb->flags & NPC_SUBBANK_FLAG_FREE)
|
||||
goto next;
|
||||
|
||||
bw0 = bitmap_weight(sb->b0map, npc_priv->subbank_depth);
|
||||
if (sb->key_type == NPC_MCAM_KEY_X4) {
|
||||
seq_printf(s, "\n\nsubbank:%u, x4, free=%u, used=%u\n",
|
||||
sb->idx, sb->free_cnt, bw0);
|
||||
|
||||
for (j = sbd - 1; j >= 0; j--) {
|
||||
if (!test_bit(j, sb->b0map))
|
||||
continue;
|
||||
|
||||
idx0 = sb->b0b + j;
|
||||
map = xa_load(&npc_priv->xa_idx2pf_map, idx0);
|
||||
pf1 = xa_to_value(map);
|
||||
|
||||
map = xa_load(&npc_priv->xa_idx2vidx_map, idx0);
|
||||
if (map) {
|
||||
vidx0 = xa_to_value(map);
|
||||
snprintf(buf0, sizeof(buf0),
|
||||
"v:%u", vidx0);
|
||||
}
|
||||
|
||||
seq_printf(s, "\t%u(%#x) %s\n", idx0, pf1,
|
||||
map ? buf0 : " ");
|
||||
}
|
||||
goto next;
|
||||
}
|
||||
|
||||
bw1 = bitmap_weight(sb->b1map, npc_priv->subbank_depth);
|
||||
seq_printf(s, "\n\nsubbank:%u, x2, free=%u, used=%u\n",
|
||||
sb->idx, sb->free_cnt, bw0 + bw1);
|
||||
seq_printf(s, "bank1(%u)\t\tbank0(%u)\n", bw1, bw0);
|
||||
|
||||
for (j = sbd - 1; j >= 0; j--) {
|
||||
e0 = test_bit(j, sb->b0map);
|
||||
e1 = test_bit(j, sb->b1map);
|
||||
|
||||
if (!e1 && !e0)
|
||||
continue;
|
||||
|
||||
if (e1 && e0) {
|
||||
idx0 = sb->b0b + j;
|
||||
map = xa_load(&npc_priv->xa_idx2pf_map, idx0);
|
||||
pf1 = xa_to_value(map);
|
||||
|
||||
map = xa_load(&npc_priv->xa_idx2vidx_map, idx0);
|
||||
v0 = !!map;
|
||||
if (v0) {
|
||||
vidx0 = xa_to_value(map);
|
||||
snprintf(buf0, sizeof(buf0), "v:%05u",
|
||||
vidx0);
|
||||
}
|
||||
|
||||
idx1 = sb->b1b + j;
|
||||
map = xa_load(&npc_priv->xa_idx2pf_map, idx1);
|
||||
pf2 = xa_to_value(map);
|
||||
|
||||
map = xa_load(&npc_priv->xa_idx2vidx_map, idx1);
|
||||
v1 = !!map;
|
||||
if (v1) {
|
||||
vidx1 = xa_to_value(map);
|
||||
snprintf(buf1, sizeof(buf1), "v:%05u",
|
||||
vidx1);
|
||||
}
|
||||
|
||||
seq_printf(s, "%05u(%#x) %s\t\t%05u(%#x) %s\n",
|
||||
idx1, pf2, v1 ? buf1 : " ",
|
||||
idx0, pf1, v0 ? buf0 : " ");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (e0) {
|
||||
idx0 = sb->b0b + j;
|
||||
map = xa_load(&npc_priv->xa_idx2pf_map, idx0);
|
||||
pf1 = xa_to_value(map);
|
||||
|
||||
map = xa_load(&npc_priv->xa_idx2vidx_map, idx0);
|
||||
if (map) {
|
||||
vidx0 = xa_to_value(map);
|
||||
snprintf(buf0, sizeof(buf0), "v:%05u",
|
||||
vidx0);
|
||||
}
|
||||
|
||||
seq_printf(s, "\t\t \t\t%05u(%#x) %s\n", idx0,
|
||||
pf1, map ? buf0 : " ");
|
||||
continue;
|
||||
}
|
||||
|
||||
idx1 = sb->b1b + j;
|
||||
map = xa_load(&npc_priv->xa_idx2pf_map, idx1);
|
||||
pf1 = xa_to_value(map);
|
||||
map = xa_load(&npc_priv->xa_idx2vidx_map, idx1);
|
||||
if (map) {
|
||||
vidx1 = xa_to_value(map);
|
||||
snprintf(buf1, sizeof(buf1), "v:%05u", vidx1);
|
||||
}
|
||||
|
||||
seq_printf(s, "%05u(%#x) %s\n", idx1, pf1,
|
||||
map ? buf1 : " ");
|
||||
}
|
||||
next:
|
||||
mutex_unlock(&sb->lock);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_SHOW_ATTRIBUTE(npc_mcam_layout);
|
||||
|
||||
static int npc_mcam_default_show(struct seq_file *s, void *unused)
|
||||
{
|
||||
struct npc_priv_t *npc_priv;
|
||||
unsigned long index;
|
||||
u16 ptr[4], pcifunc;
|
||||
struct rvu *rvu;
|
||||
int rc, i;
|
||||
void *map;
|
||||
|
||||
npc_priv = npc_priv_get();
|
||||
rvu = s->private;
|
||||
|
||||
seq_puts(s, "\npcifunc\tBcast\tmcast\tpromisc\tucast\n");
|
||||
|
||||
xa_for_each(&npc_priv->xa_pf_map, index, map) {
|
||||
pcifunc = index;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ptr); i++)
|
||||
ptr[i] = USHRT_MAX;
|
||||
|
||||
rc = npc_cn20k_dft_rules_idx_get(rvu, pcifunc, &ptr[0],
|
||||
&ptr[1], &ptr[2], &ptr[3]);
|
||||
if (rc)
|
||||
continue;
|
||||
|
||||
seq_printf(s, "%#x\t", pcifunc);
|
||||
for (i = 0; i < ARRAY_SIZE(ptr); i++) {
|
||||
if (ptr[i] != USHRT_MAX)
|
||||
seq_printf(s, "%u\t", ptr[i]);
|
||||
else
|
||||
seq_puts(s, "\t");
|
||||
}
|
||||
seq_puts(s, "\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
DEFINE_SHOW_ATTRIBUTE(npc_mcam_default);
|
||||
|
||||
static int npc_vidx2idx_map_show(struct seq_file *s, void *unused)
|
||||
{
|
||||
struct npc_priv_t *npc_priv;
|
||||
unsigned long index, start;
|
||||
struct xarray *xa;
|
||||
void *map;
|
||||
|
||||
npc_priv = s->private;
|
||||
start = npc_priv->bank_depth * 2;
|
||||
xa = &npc_priv->xa_vidx2idx_map;
|
||||
|
||||
seq_puts(s, "\nvidx\tmcam_idx\n");
|
||||
|
||||
xa_for_each_start(xa, index, map, start)
|
||||
seq_printf(s, "%lu\t%lu\n", index, xa_to_value(map));
|
||||
return 0;
|
||||
}
|
||||
DEFINE_SHOW_ATTRIBUTE(npc_vidx2idx_map);
|
||||
|
||||
static int npc_idx2vidx_map_show(struct seq_file *s, void *unused)
|
||||
{
|
||||
struct npc_priv_t *npc_priv;
|
||||
unsigned long index;
|
||||
struct xarray *xa;
|
||||
void *map;
|
||||
|
||||
npc_priv = s->private;
|
||||
xa = &npc_priv->xa_idx2vidx_map;
|
||||
|
||||
seq_puts(s, "\nmidx\tvidx\n");
|
||||
|
||||
xa_for_each(xa, index, map)
|
||||
seq_printf(s, "%lu\t%lu\n", index, xa_to_value(map));
|
||||
return 0;
|
||||
}
|
||||
DEFINE_SHOW_ATTRIBUTE(npc_idx2vidx_map);
|
||||
|
||||
static int npc_defrag_show(struct seq_file *s, void *unused)
|
||||
{
|
||||
struct npc_defrag_show_node *node;
|
||||
struct npc_priv_t *npc_priv;
|
||||
u16 sbd, bdm;
|
||||
|
||||
npc_priv = s->private;
|
||||
bdm = npc_priv->bank_depth - 1;
|
||||
sbd = npc_priv->subbank_depth;
|
||||
|
||||
seq_puts(s, "\nold(sb) -> new(sb)\t\tvidx\n");
|
||||
|
||||
mutex_lock(&npc_priv->lock);
|
||||
list_for_each_entry(node, &npc_priv->defrag_lh, list)
|
||||
seq_printf(s, "%u(%u)\t%u(%u)\t%u\n", node->old_midx,
|
||||
(node->old_midx & bdm) / sbd,
|
||||
node->new_midx,
|
||||
(node->new_midx & bdm) / sbd,
|
||||
node->vidx);
|
||||
mutex_unlock(&npc_priv->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_SHOW_ATTRIBUTE(npc_defrag);
|
||||
|
||||
int npc_cn20k_debugfs_init(struct rvu *rvu)
|
||||
{
|
||||
struct npc_priv_t *npc_priv = npc_priv_get();
|
||||
struct dentry *npc_dentry;
|
||||
|
||||
npc_dentry = debugfs_create_file("mcam_layout", 0444, rvu->rvu_dbg.npc,
|
||||
npc_priv, &npc_mcam_layout_fops);
|
||||
|
||||
if (!npc_dentry)
|
||||
return -EFAULT;
|
||||
|
||||
npc_dentry = debugfs_create_file("mcam_default", 0444, rvu->rvu_dbg.npc,
|
||||
rvu, &npc_mcam_default_fops);
|
||||
|
||||
if (!npc_dentry)
|
||||
return -EFAULT;
|
||||
|
||||
npc_dentry = debugfs_create_file("vidx2idx", 0444, rvu->rvu_dbg.npc,
|
||||
npc_priv, &npc_vidx2idx_map_fops);
|
||||
if (!npc_dentry)
|
||||
return -EFAULT;
|
||||
|
||||
npc_dentry = debugfs_create_file("idx2vidx", 0444, rvu->rvu_dbg.npc,
|
||||
npc_priv, &npc_idx2vidx_map_fops);
|
||||
if (!npc_dentry)
|
||||
return -EFAULT;
|
||||
|
||||
npc_dentry = debugfs_create_file("defrag", 0444, rvu->rvu_dbg.npc,
|
||||
npc_priv, &npc_defrag_fops);
|
||||
if (!npc_dentry)
|
||||
return -EFAULT;
|
||||
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -397,6 +397,12 @@ int rvu_alloc_cint_qint_mem(struct rvu *rvu, struct rvu_pfvf *pfvf,
|
|||
if (is_rvu_otx2(rvu) || is_cn20k(rvu->pdev))
|
||||
return 0;
|
||||
|
||||
/* sanity check */
|
||||
cfg = rvu_read64(rvu, BLKADDR_RVUM, RVU_PRIV_PFX_NIXX_CFG(0) |
|
||||
(RVU_AFPF << 16));
|
||||
if (!cfg)
|
||||
return 0;
|
||||
|
||||
ctx_cfg = rvu_read64(rvu, blkaddr, NIX_AF_CONST3);
|
||||
/* Alloc memory for CQINT's HW contexts */
|
||||
cfg = rvu_read64(rvu, blkaddr, NIX_AF_CONST2);
|
||||
|
|
@ -420,5 +426,16 @@ int rvu_alloc_cint_qint_mem(struct rvu *rvu, struct rvu_pfvf *pfvf,
|
|||
rvu_write64(rvu, blkaddr, NIX_AF_LFX_QINTS_BASE(nixlf),
|
||||
(u64)pfvf->nix_qints_ctx->iova);
|
||||
|
||||
rvu_write64(rvu, BLKADDR_NIX0, RVU_AF_BAR2_SEL, RVU_AF_BAR2_PFID);
|
||||
rvu_write64(rvu, BLKADDR_NIX0,
|
||||
AF_BAR2_ALIASX(0, NIX_GINT_INT_W1S), ALTAF_RDY);
|
||||
/* wait for ack */
|
||||
err = rvu_poll_reg(rvu, BLKADDR_NIX0,
|
||||
AF_BAR2_ALIASX(0, NIX_GINT_INT), ALTAF_RDY, true);
|
||||
if (err)
|
||||
rvu->altaf_ready = false;
|
||||
else
|
||||
rvu->altaf_ready = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
4522
drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
Normal file
4522
drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
Normal file
File diff suppressed because it is too large
Load Diff
340
drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h
Normal file
340
drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h
Normal file
|
|
@ -0,0 +1,340 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Marvell RVU Admin Function driver
|
||||
*
|
||||
* Copyright (C) 2026 Marvell.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef NPC_CN20K_H
|
||||
#define NPC_CN20K_H
|
||||
|
||||
#define MKEX_CN20K_SIGN 0x19bbfdbd160
|
||||
|
||||
#define MAX_NUM_BANKS 2
|
||||
#define MAX_NUM_SUB_BANKS 32
|
||||
#define MAX_SUBBANK_DEPTH 256
|
||||
|
||||
/* strtoull of "mkexprof" with base:36 */
|
||||
#define MKEX_END_SIGN 0xdeadbeef
|
||||
|
||||
#define NPC_CN20K_BYTESM GENMASK_ULL(18, 16)
|
||||
#define NPC_CN20K_PARSE_NIBBLE GENMASK_ULL(22, 0)
|
||||
#define NPC_CN20K_TOTAL_NIBBLE 23
|
||||
|
||||
#define CN20K_SET_EXTR_LT(intf, extr, ltype, cfg) \
|
||||
rvu_write64(rvu, BLKADDR_NPC, \
|
||||
NPC_AF_INTFX_EXTRACTORX_LTX_CFG(intf, extr, ltype), cfg)
|
||||
|
||||
#define CN20K_GET_KEX_CFG(intf) \
|
||||
rvu_read64(rvu, BLKADDR_NPC, NPC_AF_INTFX_KEX_CFG(intf))
|
||||
|
||||
#define CN20K_GET_EXTR_LID(intf, extr) \
|
||||
rvu_read64(rvu, BLKADDR_NPC, \
|
||||
NPC_AF_INTFX_EXTRACTORX_CFG(intf, extr))
|
||||
|
||||
#define CN20K_SET_EXTR_LT(intf, extr, ltype, cfg) \
|
||||
rvu_write64(rvu, BLKADDR_NPC, \
|
||||
NPC_AF_INTFX_EXTRACTORX_LTX_CFG(intf, extr, ltype), cfg)
|
||||
|
||||
#define CN20K_GET_EXTR_LT(intf, extr, ltype) \
|
||||
rvu_read64(rvu, BLKADDR_NPC, \
|
||||
NPC_AF_INTFX_EXTRACTORX_LTX_CFG(intf, extr, ltype))
|
||||
|
||||
/* NPC_PARSE_KEX_S nibble definitions for each field */
|
||||
#define NPC_CN20K_PARSE_NIBBLE_CHAN GENMASK_ULL(2, 0)
|
||||
#define NPC_CN20K_PARSE_NIBBLE_ERRLEV BIT_ULL(3)
|
||||
#define NPC_CN20K_PARSE_NIBBLE_ERRCODE GENMASK_ULL(5, 4)
|
||||
#define NPC_CN20K_PARSE_NIBBLE_L2L3_BCAST BIT_ULL(6)
|
||||
#define NPC_CN20K_PARSE_NIBBLE_LA_FLAGS BIT_ULL(7)
|
||||
#define NPC_CN20K_PARSE_NIBBLE_LA_LTYPE BIT_ULL(8)
|
||||
#define NPC_CN20K_PARSE_NIBBLE_LB_FLAGS BIT_ULL(9)
|
||||
#define NPC_CN20K_PARSE_NIBBLE_LB_LTYPE BIT_ULL(10)
|
||||
#define NPC_CN20K_PARSE_NIBBLE_LC_FLAGS BIT_ULL(11)
|
||||
#define NPC_CN20K_PARSE_NIBBLE_LC_LTYPE BIT_ULL(12)
|
||||
#define NPC_CN20K_PARSE_NIBBLE_LD_FLAGS BIT_ULL(13)
|
||||
#define NPC_CN20K_PARSE_NIBBLE_LD_LTYPE BIT_ULL(14)
|
||||
#define NPC_CN20K_PARSE_NIBBLE_LE_FLAGS BIT_ULL(15)
|
||||
#define NPC_CN20K_PARSE_NIBBLE_LE_LTYPE BIT_ULL(16)
|
||||
#define NPC_CN20K_PARSE_NIBBLE_LF_FLAGS BIT_ULL(17)
|
||||
#define NPC_CN20K_PARSE_NIBBLE_LF_LTYPE BIT_ULL(18)
|
||||
#define NPC_CN20K_PARSE_NIBBLE_LG_FLAGS BIT_ULL(19)
|
||||
#define NPC_CN20K_PARSE_NIBBLE_LG_LTYPE BIT_ULL(20)
|
||||
#define NPC_CN20K_PARSE_NIBBLE_LH_FLAGS BIT_ULL(21)
|
||||
#define NPC_CN20K_PARSE_NIBBLE_LH_LTYPE BIT_ULL(22)
|
||||
|
||||
/* Rx parse key extract nibble enable */
|
||||
#define NPC_CN20K_PARSE_NIBBLE_INTF_RX (NPC_CN20K_PARSE_NIBBLE_CHAN | \
|
||||
NPC_CN20K_PARSE_NIBBLE_L2L3_BCAST | \
|
||||
NPC_CN20K_PARSE_NIBBLE_LA_LTYPE | \
|
||||
NPC_CN20K_PARSE_NIBBLE_LB_LTYPE | \
|
||||
NPC_CN20K_PARSE_NIBBLE_LC_FLAGS | \
|
||||
NPC_CN20K_PARSE_NIBBLE_LC_LTYPE | \
|
||||
NPC_CN20K_PARSE_NIBBLE_LD_LTYPE | \
|
||||
NPC_CN20K_PARSE_NIBBLE_LE_LTYPE)
|
||||
|
||||
/* Tx parse key extract nibble enable */
|
||||
#define NPC_CN20K_PARSE_NIBBLE_INTF_TX (NPC_CN20K_PARSE_NIBBLE_LA_LTYPE | \
|
||||
NPC_CN20K_PARSE_NIBBLE_LB_LTYPE | \
|
||||
NPC_CN20K_PARSE_NIBBLE_LC_LTYPE | \
|
||||
NPC_CN20K_PARSE_NIBBLE_LD_LTYPE | \
|
||||
NPC_CN20K_PARSE_NIBBLE_LE_LTYPE)
|
||||
|
||||
/**
|
||||
* 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),
|
||||
};
|
||||
|
||||
/**
|
||||
* enum npc_dft_rule_id - Default rule type
|
||||
*
|
||||
* Mcam default rule type.
|
||||
*
|
||||
* @NPC_DFT_RULE_START_ID: Not used
|
||||
* @NPC_DFT_RULE_PROMISC_ID: promiscuous rule
|
||||
* @NPC_DFT_RULE_MCAST_ID: multicast rule
|
||||
* @NPC_DFT_RULE_BCAST_ID: broadcast rule
|
||||
* @NPC_DFT_RULE_UCAST_ID: unicast rule
|
||||
* @NPC_DFT_RULE_MAX_ID: Maximum index.
|
||||
*/
|
||||
enum npc_dft_rule_id {
|
||||
NPC_DFT_RULE_START_ID = 1,
|
||||
NPC_DFT_RULE_PROMISC_ID = NPC_DFT_RULE_START_ID,
|
||||
NPC_DFT_RULE_MCAST_ID,
|
||||
NPC_DFT_RULE_BCAST_ID,
|
||||
NPC_DFT_RULE_UCAST_ID,
|
||||
NPC_DFT_RULE_MAX_ID,
|
||||
};
|
||||
|
||||
/**
|
||||
* 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_defrag_show_node - Defragmentation show node
|
||||
* @old_midx: Old mcam index.
|
||||
* @new_midx: New mcam index.
|
||||
* @vidx: Virtual index
|
||||
* @list: Linked list of these nodes
|
||||
*
|
||||
* This structure holds information on last defragmentation
|
||||
* executed on mcam resource.
|
||||
*/
|
||||
struct npc_defrag_show_node {
|
||||
u16 old_midx;
|
||||
u16 new_midx;
|
||||
u16 vidx;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @xa_pf2dfl_rmap: PF to default rule index map.
|
||||
* @xa_idx2vidx_map: Mcam index to virtual index map.
|
||||
* @xa_vidx2idx_map: virtual index to mcam index map.
|
||||
* @defrag_lh: Defrag list head.
|
||||
* @lock: Lock for defrag list
|
||||
*
|
||||
* 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;
|
||||
struct xarray xa_pf2dfl_rmap;
|
||||
struct xarray xa_idx2vidx_map;
|
||||
struct xarray xa_vidx2idx_map;
|
||||
struct list_head defrag_lh;
|
||||
struct mutex lock; /* protect defrag nodes */
|
||||
int pf_cnt;
|
||||
bool init_done;
|
||||
};
|
||||
|
||||
struct npc_kpm_action0 {
|
||||
#if defined(__BIG_ENDIAN_BITFIELD)
|
||||
u64 rsvd_63_57 : 7;
|
||||
u64 byp_count : 3;
|
||||
u64 capture_ena : 1;
|
||||
u64 parse_done : 1;
|
||||
u64 next_state : 8;
|
||||
u64 rsvd_43 : 1;
|
||||
u64 capture_lid : 3;
|
||||
u64 capture_ltype : 4;
|
||||
u64 rsvd_32_35 : 4;
|
||||
u64 capture_flags : 4;
|
||||
u64 ptr_advance : 8;
|
||||
u64 var_len_offset : 8;
|
||||
u64 var_len_mask : 8;
|
||||
u64 var_len_right : 1;
|
||||
u64 var_len_shift : 3;
|
||||
#else
|
||||
u64 var_len_shift : 3;
|
||||
u64 var_len_right : 1;
|
||||
u64 var_len_mask : 8;
|
||||
u64 var_len_offset : 8;
|
||||
u64 ptr_advance : 8;
|
||||
u64 capture_flags : 4;
|
||||
u64 rsvd_32_35 : 4;
|
||||
u64 capture_ltype : 4;
|
||||
u64 capture_lid : 3;
|
||||
u64 rsvd_43 : 1;
|
||||
u64 next_state : 8;
|
||||
u64 parse_done : 1;
|
||||
u64 capture_ena : 1;
|
||||
u64 byp_count : 3;
|
||||
u64 rsvd_63_57 : 7;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct npc_mcam_kex_extr {
|
||||
/* MKEX Profle Header */
|
||||
u64 mkex_sign; /* "mcam-kex-profile" (8 bytes/ASCII characters) */
|
||||
u8 name[MKEX_NAME_LEN]; /* MKEX Profile name */
|
||||
u64 cpu_model; /* Format as profiled by CPU hardware */
|
||||
u64 kpu_version; /* KPU firmware/profile version */
|
||||
u64 reserved; /* Reserved for extension */
|
||||
|
||||
/* MKEX Profle Data */
|
||||
u64 keyx_cfg[NPC_MAX_INTF]; /* NPC_AF_INTF(0..1)_KEX_CFG */
|
||||
#define NPC_MAX_EXTRACTOR 24
|
||||
/* MKEX Extractor data */
|
||||
u64 intf_extr_lid[NPC_MAX_INTF][NPC_MAX_EXTRACTOR];
|
||||
/* KEX configuration per extractor */
|
||||
u64 intf_extr_lt[NPC_MAX_INTF][NPC_MAX_EXTRACTOR][NPC_MAX_LT];
|
||||
} __packed;
|
||||
|
||||
struct npc_cn20k_kpu_profile_fwdata {
|
||||
#define KPU_SIGN 0x00666f727075706b
|
||||
#define KPU_NAME_LEN 32
|
||||
/* Maximum number of custom KPU entries supported by
|
||||
* the built-in profile.
|
||||
*/
|
||||
#define KPU_CN20K_MAX_CST_ENT 6
|
||||
/* KPU Profle Header */
|
||||
__le64 signature; /* "kpuprof\0" (8 bytes/ASCII characters) */
|
||||
u8 name[KPU_NAME_LEN]; /* KPU Profile name */
|
||||
__le64 version; /* KPU profile version */
|
||||
u8 kpus;
|
||||
u8 reserved[7];
|
||||
|
||||
/* Default MKEX profile to be used with this KPU profile. May be
|
||||
* overridden with mkex_profile module parameter.
|
||||
* Format is same as for the MKEX profile to streamline processing.
|
||||
*/
|
||||
struct npc_mcam_kex_extr mkex;
|
||||
/* LTYPE values for specific HW offloaded protocols. */
|
||||
struct npc_lt_def_cfg lt_def;
|
||||
/* Dynamically sized data:
|
||||
* Custom KPU CAM and ACTION configuration entries.
|
||||
* struct npc_kpu_fwdata kpu[kpus];
|
||||
*/
|
||||
u8 data[];
|
||||
} __packed;
|
||||
|
||||
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, bool virt);
|
||||
int npc_cn20k_idx_free(struct rvu *rvu, u16 *mcam_idx, int count);
|
||||
void npc_cn20k_parser_profile_init(struct rvu *rvu, int blkaddr);
|
||||
struct npc_mcam_kex_extr *npc_mkex_extr_default_get(void);
|
||||
void npc_cn20k_load_mkex_profile(struct rvu *rvu, int blkaddr,
|
||||
const char *mkex_profile);
|
||||
int npc_cn20k_apply_custom_kpu(struct rvu *rvu,
|
||||
struct npc_kpu_profile_adapter *profile);
|
||||
|
||||
void
|
||||
npc_cn20k_update_action_entries_n_flags(struct rvu *rvu,
|
||||
struct npc_kpu_profile_adapter *pfl);
|
||||
|
||||
int npc_cn20k_dft_rules_alloc(struct rvu *rvu, u16 pcifunc);
|
||||
void npc_cn20k_dft_rules_free(struct rvu *rvu, u16 pcifunc);
|
||||
|
||||
int npc_cn20k_dft_rules_idx_get(struct rvu *rvu, u16 pcifunc, u16 *bcast,
|
||||
u16 *mcast, u16 *promisc, u16 *ucast);
|
||||
|
||||
void npc_cn20k_config_mcam_entry(struct rvu *rvu, int blkaddr, int index,
|
||||
u8 intf, struct cn20k_mcam_entry *entry,
|
||||
bool enable, u8 hw_prio, u8 req_kw_type);
|
||||
void npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkaddr,
|
||||
int index, bool enable);
|
||||
void npc_cn20k_copy_mcam_entry(struct rvu *rvu, int blkaddr,
|
||||
u16 src, u16 dest);
|
||||
void npc_cn20k_read_mcam_entry(struct rvu *rvu, int blkaddr, u16 index,
|
||||
struct cn20k_mcam_entry *entry, u8 *intf,
|
||||
u8 *ena, u8 *hw_prio);
|
||||
void npc_cn20k_clear_mcam_entry(struct rvu *rvu, int blkaddr,
|
||||
int bank, int index);
|
||||
int npc_mcam_idx_2_key_type(struct rvu *rvu, u16 mcam_idx, u8 *key_type);
|
||||
u16 npc_cn20k_vidx2idx(u16 index);
|
||||
u16 npc_cn20k_idx2vidx(u16 idx);
|
||||
int npc_cn20k_defrag(struct rvu *rvu);
|
||||
|
||||
#endif /* NPC_CN20K_H */
|
||||
|
|
@ -78,4 +78,69 @@
|
|||
#define RVU_MBOX_VF_INT_ENA_W1C (0x38)
|
||||
|
||||
#define RVU_MBOX_VF_VFAF_TRIGX(a) (0x2000 | (a) << 3)
|
||||
|
||||
#define NIX_GINT_INT (0x200)
|
||||
#define NIX_GINT_INT_W1S (0x208)
|
||||
|
||||
#define ALTAF_FLR BIT_ULL(0)
|
||||
#define ALTAF_RDY BIT_ULL(1)
|
||||
|
||||
/* NPC registers */
|
||||
#define NPC_AF_INTFX_EXTRACTORX_CFG(a, b) \
|
||||
(0x20c000ull | (a) << 16 | (b) << 8)
|
||||
#define NPC_AF_INTFX_EXTRACTORX_LTX_CFG(a, b, c) \
|
||||
(0x204000ull | (a) << 16 | (b) << 8 | (c) << 3)
|
||||
#define NPC_AF_KPMX_ENTRYX_CAMX(a, b, c) \
|
||||
(0x20000ull | (a) << 12 | (b) << 3 | (c) << 16)
|
||||
#define NPC_AF_KPMX_ENTRYX_ACTION0(a, b) \
|
||||
(0x40000ull | (a) << 12 | (b) << 3)
|
||||
#define NPC_AF_KPMX_ENTRYX_ACTION1(a, b) \
|
||||
(0x50000ull | (a) << 12 | (b) << 3)
|
||||
#define NPC_AF_KPMX_ENTRY_DISX(a, b) (0x60000ull | (a) << 12 | (b) << 3)
|
||||
#define NPC_AF_KPM_PASS2_CFG 0x10210
|
||||
#define NPC_AF_KPMX_PASS2_OFFSET(a) (0x60040ull | (a) << 12)
|
||||
#define NPC_AF_MCAM_SECTIONX_CFG_EXT(a) (0xf000000ull | (a) << 3)
|
||||
|
||||
#define NPC_AF_CN20K_MCAMEX_BANKX_CAMX_INTF_EXT(a, b, c) ({ \
|
||||
u64 offset; \
|
||||
offset = (0x8000000ull | (a) << 4 | (b) << 20 | (c) << 3); \
|
||||
offset; })
|
||||
|
||||
#define NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W0_EXT(a, b, c) ({ \
|
||||
u64 offset; \
|
||||
offset = (0x9000000ull | (a) << 4 | (b) << 20 | (c) << 3); \
|
||||
offset; })
|
||||
|
||||
#define NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W1_EXT(a, b, c) ({ \
|
||||
u64 offset; \
|
||||
offset = (0x9400000ull | (a) << 4 | (b) << 20 | (c) << 3); \
|
||||
offset; })
|
||||
|
||||
#define NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W2_EXT(a, b, c) ({ \
|
||||
u64 offset; \
|
||||
offset = (0x9800000ull | (a) << 4 | (b) << 20 | (c) << 3); \
|
||||
offset; })
|
||||
|
||||
#define NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W3_EXT(a, b, c) ({ \
|
||||
u64 offset; \
|
||||
offset = (0x9c00000ull | (a) << 4 | (b) << 20 | (c) << 3); \
|
||||
offset; })
|
||||
|
||||
#define NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(a, b) ({ \
|
||||
u64 offset; \
|
||||
offset = (0xa000000ull | (a) << 4 | (b) << 20); \
|
||||
offset; })
|
||||
|
||||
#define NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(a, b, c) ({ \
|
||||
u64 offset; \
|
||||
offset = (0xc000000ull | (a) << 4 | (b) << 20 | (c) << 22); \
|
||||
offset; })
|
||||
|
||||
#define NPC_AF_INTFX_MISS_ACTX(a, b) (0xf003000 | (a) << 6 | (b) << 4)
|
||||
|
||||
#define NPC_AF_CN20K_MCAMEX_BANKX_STAT_EXT(a, b) ({ \
|
||||
u64 offset; \
|
||||
offset = (0xb000000ull | (a) << 4 | (b) << 20); \
|
||||
offset; })
|
||||
|
||||
#endif /* RVU_MBOX_REG_H */
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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,33 @@ 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) \
|
||||
M(NPC_CN20K_GET_KEX_CFG, 0x6016, npc_cn20k_get_kex_cfg, \
|
||||
msg_req, npc_cn20k_get_kex_cfg_rsp) \
|
||||
M(NPC_CN20K_MCAM_WRITE_ENTRY, 0x6017, npc_cn20k_mcam_write_entry, \
|
||||
npc_cn20k_mcam_write_entry_req, msg_rsp) \
|
||||
M(NPC_CN20K_MCAM_ALLOC_AND_WRITE_ENTRY, 0x6018, \
|
||||
npc_cn20k_mcam_alloc_and_write_entry, \
|
||||
npc_cn20k_mcam_alloc_and_write_entry_req, \
|
||||
npc_mcam_alloc_and_write_entry_rsp) \
|
||||
M(NPC_CN20K_MCAM_READ_ENTRY, 0x6019, npc_cn20k_mcam_read_entry, \
|
||||
npc_mcam_read_entry_req, \
|
||||
npc_cn20k_mcam_read_entry_rsp) \
|
||||
M(NPC_CN20K_MCAM_READ_BASE_RULE, 0x601a, npc_cn20k_read_base_steer_rule, \
|
||||
msg_req, npc_cn20k_mcam_read_base_rule_rsp) \
|
||||
M(NPC_MCAM_DEFRAG, 0x601b, npc_defrag, \
|
||||
msg_req, \
|
||||
msg_rsp) \
|
||||
M(NPC_MCAM_GET_NUM_KWS, 0x601c, npc_get_num_kws, \
|
||||
npc_get_num_kws_req, \
|
||||
npc_get_num_kws_rsp) \
|
||||
M(NPC_MCAM_GET_DFT_RL_IDXS, 0x601d, npc_get_dft_rl_idxs, \
|
||||
msg_req, \
|
||||
npc_get_dft_rl_idxs_rsp)\
|
||||
M(NPC_MCAM_GET_NPC_PFL_INFO, 0x601e, npc_get_pfl_info, \
|
||||
msg_req, \
|
||||
npc_get_pfl_info_rsp) \
|
||||
/* NIX mbox IDs (range 0x8000 - 0xFFFF) */ \
|
||||
M(NIX_LF_ALLOC, 0x8000, nix_lf_alloc, \
|
||||
nix_lf_alloc_req, nix_lf_alloc_rsp) \
|
||||
|
|
@ -1527,9 +1562,11 @@ struct npc_mcam_alloc_entry_req {
|
|||
#define NPC_MCAM_ANY_PRIO 0
|
||||
#define NPC_MCAM_LOWER_PRIO 1
|
||||
#define NPC_MCAM_HIGHER_PRIO 2
|
||||
u8 priority; /* Lower or higher w.r.t ref_entry */
|
||||
u8 ref_prio; /* Lower or higher w.r.t ref_entry */
|
||||
u16 ref_entry;
|
||||
u16 count; /* Number of entries requested */
|
||||
u8 kw_type; /* entry key type, valid for cn20k */
|
||||
u8 virt; /* Request virtual index */
|
||||
};
|
||||
|
||||
struct npc_mcam_alloc_entry_rsp {
|
||||
|
|
@ -1548,14 +1585,47 @@ struct npc_mcam_free_entry_req {
|
|||
u8 all; /* If all entries allocated to this PFVF to be freed */
|
||||
};
|
||||
|
||||
struct mcam_entry_mdata {
|
||||
u64 *kw;
|
||||
u64 *kw_mask;
|
||||
u64 *action;
|
||||
u64 *vtag_action;
|
||||
u8 max_kw;
|
||||
};
|
||||
|
||||
enum npc_kws_in_key_sz {
|
||||
NPC_KWS_IN_KEY_SZ_7 = 7,
|
||||
NPC_KWS_IN_KEY_SZ_8 = 8,
|
||||
NPC_KWS_IN_KEY_SZ_MAX,
|
||||
};
|
||||
|
||||
struct mcam_entry {
|
||||
#define NPC_MAX_KWS_IN_KEY 7 /* Number of keywords in max keywidth */
|
||||
u64 kw[NPC_MAX_KWS_IN_KEY];
|
||||
u64 kw_mask[NPC_MAX_KWS_IN_KEY];
|
||||
u64 kw[NPC_KWS_IN_KEY_SZ_7];
|
||||
u64 kw_mask[NPC_KWS_IN_KEY_SZ_7];
|
||||
u64 action;
|
||||
u64 vtag_action;
|
||||
};
|
||||
|
||||
struct cn20k_mcam_entry {
|
||||
u64 kw[NPC_KWS_IN_KEY_SZ_8];
|
||||
u64 kw_mask[NPC_KWS_IN_KEY_SZ_8];
|
||||
u64 action;
|
||||
u64 vtag_action;
|
||||
u64 action2;
|
||||
};
|
||||
|
||||
struct npc_cn20k_mcam_write_entry_req {
|
||||
struct mbox_msghdr hdr;
|
||||
struct cn20k_mcam_entry entry_data;
|
||||
u16 entry; /* MCAM entry to write this match key */
|
||||
u16 cntr; /* Counter for this MCAM entry */
|
||||
u8 intf; /* Rx or Tx interface */
|
||||
u8 enable_entry;/* Enable this MCAM entry ? */
|
||||
u8 hw_prio; /* hardware priority, valid for cn20k */
|
||||
u8 req_kw_type; /* Type of kw which should be written */
|
||||
u64 reserved; /* reserved for future use */
|
||||
};
|
||||
|
||||
struct npc_mcam_write_entry_req {
|
||||
struct mbox_msghdr hdr;
|
||||
struct mcam_entry entry_data;
|
||||
|
|
@ -1564,6 +1634,8 @@ struct npc_mcam_write_entry_req {
|
|||
u8 intf; /* Rx or Tx interface */
|
||||
u8 enable_entry;/* Enable this MCAM entry ? */
|
||||
u8 set_cntr; /* Set counter for this entry ? */
|
||||
u8 hw_prio; /* hardware priority, valid for cn20k */
|
||||
u64 reserved; /* reserved for future use */
|
||||
};
|
||||
|
||||
/* Enable/Disable a given entry */
|
||||
|
|
@ -1622,12 +1694,38 @@ struct npc_mcam_alloc_and_write_entry_req {
|
|||
struct mbox_msghdr hdr;
|
||||
struct mcam_entry entry_data;
|
||||
u16 ref_entry;
|
||||
u8 priority; /* Lower or higher w.r.t ref_entry */
|
||||
u8 ref_prio; /* Lower or higher w.r.t ref_entry */
|
||||
u8 intf; /* Rx or Tx interface */
|
||||
u8 enable_entry;/* Enable this MCAM entry ? */
|
||||
u8 alloc_cntr; /* Allocate counter and map ? */
|
||||
};
|
||||
|
||||
struct npc_cn20k_mcam_alloc_and_write_entry_req {
|
||||
struct mbox_msghdr hdr;
|
||||
struct cn20k_mcam_entry entry_data;
|
||||
u16 ref_entry;
|
||||
u8 ref_prio; /* Lower or higher w.r.t ref_entry */
|
||||
u8 intf; /* Rx or Tx interface */
|
||||
u8 enable_entry;/* Enable this MCAM entry ? */
|
||||
u8 hw_prio; /* hardware priority, valid for cn20k */
|
||||
u8 virt; /* Allocate virtual index */
|
||||
u8 req_kw_type; /* Key type to be written */
|
||||
u16 reserved[4]; /* reserved for future use */
|
||||
};
|
||||
|
||||
struct npc_cn20k_mcam_read_entry_rsp {
|
||||
struct mbox_msghdr hdr;
|
||||
struct cn20k_mcam_entry entry_data;
|
||||
u8 intf;
|
||||
u8 enable;
|
||||
u8 hw_prio; /* valid for cn20k */
|
||||
};
|
||||
|
||||
struct npc_cn20k_mcam_read_base_rule_rsp {
|
||||
struct mbox_msghdr hdr;
|
||||
struct cn20k_mcam_entry entry;
|
||||
};
|
||||
|
||||
struct npc_mcam_alloc_and_write_entry_rsp {
|
||||
struct mbox_msghdr hdr;
|
||||
u16 entry;
|
||||
|
|
@ -1653,6 +1751,19 @@ struct npc_get_kex_cfg_rsp {
|
|||
u8 mkex_pfl_name[MKEX_NAME_LEN];
|
||||
};
|
||||
|
||||
struct npc_cn20k_get_kex_cfg_rsp {
|
||||
struct mbox_msghdr hdr;
|
||||
u64 rx_keyx_cfg; /* NPC_AF_INTF(0)_KEX_CFG */
|
||||
u64 tx_keyx_cfg; /* NPC_AF_INTF(1)_KEX_CFG */
|
||||
#define NPC_MAX_EXTRACTOR 24
|
||||
/* MKEX Extractor data */
|
||||
u64 intf_extr_lid[NPC_MAX_INTF][NPC_MAX_EXTRACTOR];
|
||||
/* KEX configuration per extractor */
|
||||
u64 intf_extr_lt[NPC_MAX_INTF][NPC_MAX_EXTRACTOR][NPC_MAX_LT];
|
||||
#define MKEX_NAME_LEN 128
|
||||
u8 mkex_pfl_name[MKEX_NAME_LEN];
|
||||
};
|
||||
|
||||
struct ptp_get_cap_rsp {
|
||||
struct mbox_msghdr hdr;
|
||||
#define PTP_CAP_HW_ATOMIC_UPDATE BIT_ULL(0)
|
||||
|
|
@ -1765,11 +1876,53 @@ struct npc_install_flow_req {
|
|||
u8 vtag1_op;
|
||||
/* old counter value */
|
||||
u16 cntr_val;
|
||||
u8 hw_prio;
|
||||
u8 req_kw_type; /* Key type to be written */
|
||||
u8 alloc_entry; /* only for cn20k */
|
||||
/* For now use any priority, once AF driver is changed to
|
||||
* allocate least priority entry instead of mid zone then make
|
||||
* NPC_MCAM_LEAST_PRIO as 3
|
||||
*/
|
||||
#define NPC_MCAM_LEAST_PRIO NPC_MCAM_ANY_PRIO
|
||||
u16 ref_prio;
|
||||
u16 ref_entry;
|
||||
};
|
||||
|
||||
struct npc_install_flow_rsp {
|
||||
struct mbox_msghdr hdr;
|
||||
int counter; /* negative if no counter else counter number */
|
||||
u16 entry;
|
||||
u8 kw_type;
|
||||
};
|
||||
|
||||
struct npc_get_num_kws_req {
|
||||
struct mbox_msghdr hdr;
|
||||
struct npc_install_flow_req fl;
|
||||
u32 rsvd[4];
|
||||
};
|
||||
|
||||
struct npc_get_num_kws_rsp {
|
||||
struct mbox_msghdr hdr;
|
||||
int kws;
|
||||
u32 rsvd[4];
|
||||
};
|
||||
|
||||
struct npc_get_dft_rl_idxs_rsp {
|
||||
struct mbox_msghdr hdr;
|
||||
u16 bcast;
|
||||
u16 mcast;
|
||||
u16 promisc;
|
||||
u16 ucast;
|
||||
u16 vf_ucast;
|
||||
u16 rsvd[7];
|
||||
};
|
||||
|
||||
struct npc_get_pfl_info_rsp {
|
||||
struct mbox_msghdr hdr;
|
||||
u16 x4_slots;
|
||||
u8 kw_type;
|
||||
u8 rsvd1[3];
|
||||
u32 rsvd2[4];
|
||||
};
|
||||
|
||||
struct npc_delete_flow_req {
|
||||
|
|
@ -1795,6 +1948,15 @@ struct npc_mcam_read_entry_rsp {
|
|||
struct mcam_entry entry_data;
|
||||
u8 intf;
|
||||
u8 enable;
|
||||
u8 hw_prio; /* valid for cn20k */
|
||||
};
|
||||
|
||||
/* 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 {
|
||||
|
|
|
|||
|
|
@ -429,6 +429,7 @@ struct nix_rx_action {
|
|||
|
||||
/* NPC_AF_INTFX_KEX_CFG field masks */
|
||||
#define NPC_PARSE_NIBBLE GENMASK_ULL(30, 0)
|
||||
#define NPC_TOTAL_NIBBLE 31
|
||||
|
||||
/* NPC_PARSE_KEX_S nibble definitions for each field */
|
||||
#define NPC_PARSE_NIBBLE_CHAN GENMASK_ULL(2, 0)
|
||||
|
|
@ -643,6 +644,7 @@ struct rvu_npc_mcam_rule {
|
|||
u16 chan;
|
||||
u16 chan_mask;
|
||||
u8 lxmb;
|
||||
u8 hw_prio;
|
||||
};
|
||||
|
||||
#endif /* NPC_H */
|
||||
|
|
|
|||
|
|
@ -321,6 +321,18 @@ enum npc_kpu_lb_lflag {
|
|||
NPC_F_LB_L_FDSA,
|
||||
};
|
||||
|
||||
enum npc_cn20k_kpu_lc_uflag {
|
||||
NPC_CN20K_F_LC_U_MPLS_IN_IP = 0x20,
|
||||
NPC_CN20K_F_LC_U_IP6_TUN_IP6 = 0x40,
|
||||
NPC_CN20K_F_LC_U_IP6_MPLS_IN_IP = 0x80,
|
||||
};
|
||||
|
||||
enum npc_cn20k_kpu_lc_lflag {
|
||||
NPC_CN20K_F_LC_L_IP_FRAG = 2,
|
||||
NPC_CN20K_F_LC_L_IP6_FRAG,
|
||||
NPC_CN20K_F_LC_L_6TO4,
|
||||
};
|
||||
|
||||
enum npc_kpu_lc_uflag {
|
||||
NPC_F_LC_U_UNK_PROTO = 0x10,
|
||||
NPC_F_LC_U_IP_FRAG = 0x20,
|
||||
|
|
@ -489,7 +501,7 @@ enum NPC_ERRLEV_E {
|
|||
0, 0, 0, 0, \
|
||||
}
|
||||
|
||||
static struct npc_kpu_profile_action ikpu_action_entries[] = {
|
||||
static struct npc_kpu_profile_action ikpu_action_entries[] __maybe_unused = {
|
||||
{
|
||||
NPC_ERRLEV_RE, NPC_EC_NOERR,
|
||||
12, 16, 20, 0, 0,
|
||||
|
|
@ -1068,7 +1080,7 @@ static struct npc_kpu_profile_action ikpu_action_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile_cam kpu1_cam_entries[] = {
|
||||
static struct npc_kpu_profile_cam kpu1_cam_entries[] __maybe_unused = {
|
||||
NPC_KPU_NOP_CAM,
|
||||
NPC_KPU_NOP_CAM,
|
||||
NPC_KPU_NOP_CAM,
|
||||
|
|
@ -1878,7 +1890,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile_cam kpu2_cam_entries[] = {
|
||||
static struct npc_kpu_profile_cam kpu2_cam_entries[] __maybe_unused = {
|
||||
NPC_KPU_NOP_CAM,
|
||||
NPC_KPU_NOP_CAM,
|
||||
NPC_KPU_NOP_CAM,
|
||||
|
|
@ -2823,7 +2835,7 @@ static struct npc_kpu_profile_cam kpu2_cam_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile_cam kpu3_cam_entries[] = {
|
||||
static struct npc_kpu_profile_cam kpu3_cam_entries[] __maybe_unused = {
|
||||
NPC_KPU_NOP_CAM,
|
||||
NPC_KPU_NOP_CAM,
|
||||
NPC_KPU_NOP_CAM,
|
||||
|
|
@ -3804,7 +3816,7 @@ static struct npc_kpu_profile_cam kpu3_cam_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile_cam kpu4_cam_entries[] = {
|
||||
static struct npc_kpu_profile_cam kpu4_cam_entries[] __maybe_unused = {
|
||||
NPC_KPU_NOP_CAM,
|
||||
NPC_KPU_NOP_CAM,
|
||||
NPC_KPU_NOP_CAM,
|
||||
|
|
@ -4119,7 +4131,7 @@ static struct npc_kpu_profile_cam kpu4_cam_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile_cam kpu5_cam_entries[] = {
|
||||
static struct npc_kpu_profile_cam kpu5_cam_entries[] __maybe_unused = {
|
||||
NPC_KPU_NOP_CAM,
|
||||
NPC_KPU_NOP_CAM,
|
||||
NPC_KPU_NOP_CAM,
|
||||
|
|
@ -5172,7 +5184,7 @@ static struct npc_kpu_profile_cam kpu5_cam_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile_cam kpu6_cam_entries[] = {
|
||||
static struct npc_kpu_profile_cam kpu6_cam_entries[] __maybe_unused = {
|
||||
NPC_KPU_NOP_CAM,
|
||||
NPC_KPU_NOP_CAM,
|
||||
NPC_KPU_NOP_CAM,
|
||||
|
|
@ -5901,7 +5913,7 @@ static struct npc_kpu_profile_cam kpu6_cam_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile_cam kpu7_cam_entries[] = {
|
||||
static struct npc_kpu_profile_cam kpu7_cam_entries[] __maybe_unused = {
|
||||
NPC_KPU_NOP_CAM,
|
||||
NPC_KPU_NOP_CAM,
|
||||
NPC_KPU_NOP_CAM,
|
||||
|
|
@ -6252,7 +6264,7 @@ static struct npc_kpu_profile_cam kpu7_cam_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile_cam kpu8_cam_entries[] = {
|
||||
static struct npc_kpu_profile_cam kpu8_cam_entries[] __maybe_unused = {
|
||||
NPC_KPU_NOP_CAM,
|
||||
NPC_KPU_NOP_CAM,
|
||||
NPC_KPU_NOP_CAM,
|
||||
|
|
@ -7089,7 +7101,7 @@ static struct npc_kpu_profile_cam kpu8_cam_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile_cam kpu9_cam_entries[] = {
|
||||
static struct npc_kpu_profile_cam kpu9_cam_entries[] __maybe_unused = {
|
||||
NPC_KPU_NOP_CAM,
|
||||
NPC_KPU_NOP_CAM,
|
||||
NPC_KPU_NOP_CAM,
|
||||
|
|
@ -7575,7 +7587,7 @@ static struct npc_kpu_profile_cam kpu9_cam_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile_cam kpu10_cam_entries[] = {
|
||||
static struct npc_kpu_profile_cam kpu10_cam_entries[] __maybe_unused = {
|
||||
NPC_KPU_NOP_CAM,
|
||||
NPC_KPU_NOP_CAM,
|
||||
NPC_KPU_NOP_CAM,
|
||||
|
|
@ -7746,7 +7758,7 @@ static struct npc_kpu_profile_cam kpu10_cam_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile_cam kpu11_cam_entries[] = {
|
||||
static struct npc_kpu_profile_cam kpu11_cam_entries[] __maybe_unused = {
|
||||
NPC_KPU_NOP_CAM,
|
||||
NPC_KPU_NOP_CAM,
|
||||
NPC_KPU_NOP_CAM,
|
||||
|
|
@ -8061,7 +8073,7 @@ static struct npc_kpu_profile_cam kpu11_cam_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile_cam kpu12_cam_entries[] = {
|
||||
static struct npc_kpu_profile_cam kpu12_cam_entries[] __maybe_unused = {
|
||||
NPC_KPU_NOP_CAM,
|
||||
NPC_KPU_NOP_CAM,
|
||||
NPC_KPU_NOP_CAM,
|
||||
|
|
@ -8322,7 +8334,7 @@ static struct npc_kpu_profile_cam kpu12_cam_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile_cam kpu13_cam_entries[] = {
|
||||
static struct npc_kpu_profile_cam kpu13_cam_entries[] __maybe_unused = {
|
||||
NPC_KPU_NOP_CAM,
|
||||
NPC_KPU_NOP_CAM,
|
||||
NPC_KPU_NOP_CAM,
|
||||
|
|
@ -8340,7 +8352,7 @@ static struct npc_kpu_profile_cam kpu13_cam_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile_cam kpu14_cam_entries[] = {
|
||||
static struct npc_kpu_profile_cam kpu14_cam_entries[] __maybe_unused = {
|
||||
NPC_KPU_NOP_CAM,
|
||||
NPC_KPU_NOP_CAM,
|
||||
NPC_KPU_NOP_CAM,
|
||||
|
|
@ -8358,7 +8370,7 @@ static struct npc_kpu_profile_cam kpu14_cam_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile_cam kpu15_cam_entries[] = {
|
||||
static struct npc_kpu_profile_cam kpu15_cam_entries[] __maybe_unused = {
|
||||
NPC_KPU_NOP_CAM,
|
||||
NPC_KPU_NOP_CAM,
|
||||
NPC_KPU_NOP_CAM,
|
||||
|
|
@ -8565,7 +8577,7 @@ static struct npc_kpu_profile_cam kpu15_cam_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile_cam kpu16_cam_entries[] = {
|
||||
static struct npc_kpu_profile_cam kpu16_cam_entries[] __maybe_unused = {
|
||||
NPC_KPU_NOP_CAM,
|
||||
NPC_KPU_NOP_CAM,
|
||||
NPC_KPU_NOP_CAM,
|
||||
|
|
@ -8628,7 +8640,7 @@ static struct npc_kpu_profile_cam kpu16_cam_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile_action kpu1_action_entries[] = {
|
||||
static struct npc_kpu_profile_action kpu1_action_entries[] __maybe_unused = {
|
||||
NPC_KPU_NOP_ACTION,
|
||||
NPC_KPU_NOP_ACTION,
|
||||
NPC_KPU_NOP_ACTION,
|
||||
|
|
@ -9368,7 +9380,7 @@ static struct npc_kpu_profile_action kpu1_action_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile_action kpu2_action_entries[] = {
|
||||
static struct npc_kpu_profile_action kpu2_action_entries[] __maybe_unused = {
|
||||
NPC_KPU_NOP_ACTION,
|
||||
NPC_KPU_NOP_ACTION,
|
||||
NPC_KPU_NOP_ACTION,
|
||||
|
|
@ -10209,7 +10221,7 @@ static struct npc_kpu_profile_action kpu2_action_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile_action kpu3_action_entries[] = {
|
||||
static struct npc_kpu_profile_action kpu3_action_entries[] __maybe_unused = {
|
||||
NPC_KPU_NOP_ACTION,
|
||||
NPC_KPU_NOP_ACTION,
|
||||
NPC_KPU_NOP_ACTION,
|
||||
|
|
@ -11082,7 +11094,7 @@ static struct npc_kpu_profile_action kpu3_action_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile_action kpu4_action_entries[] = {
|
||||
static struct npc_kpu_profile_action kpu4_action_entries[] __maybe_unused = {
|
||||
NPC_KPU_NOP_ACTION,
|
||||
NPC_KPU_NOP_ACTION,
|
||||
NPC_KPU_NOP_ACTION,
|
||||
|
|
@ -11363,7 +11375,7 @@ static struct npc_kpu_profile_action kpu4_action_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile_action kpu5_action_entries[] = {
|
||||
static struct npc_kpu_profile_action kpu5_action_entries[] __maybe_unused = {
|
||||
NPC_KPU_NOP_ACTION,
|
||||
NPC_KPU_NOP_ACTION,
|
||||
NPC_KPU_NOP_ACTION,
|
||||
|
|
@ -12300,7 +12312,7 @@ static struct npc_kpu_profile_action kpu5_action_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile_action kpu6_action_entries[] = {
|
||||
static struct npc_kpu_profile_action kpu6_action_entries[] __maybe_unused = {
|
||||
NPC_KPU_NOP_ACTION,
|
||||
NPC_KPU_NOP_ACTION,
|
||||
NPC_KPU_NOP_ACTION,
|
||||
|
|
@ -12949,7 +12961,7 @@ static struct npc_kpu_profile_action kpu6_action_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile_action kpu7_action_entries[] = {
|
||||
static struct npc_kpu_profile_action kpu7_action_entries[] __maybe_unused = {
|
||||
NPC_KPU_NOP_ACTION,
|
||||
NPC_KPU_NOP_ACTION,
|
||||
NPC_KPU_NOP_ACTION,
|
||||
|
|
@ -13262,7 +13274,7 @@ static struct npc_kpu_profile_action kpu7_action_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile_action kpu8_action_entries[] = {
|
||||
static struct npc_kpu_profile_action kpu8_action_entries[] __maybe_unused = {
|
||||
NPC_KPU_NOP_ACTION,
|
||||
NPC_KPU_NOP_ACTION,
|
||||
NPC_KPU_NOP_ACTION,
|
||||
|
|
@ -14007,7 +14019,7 @@ static struct npc_kpu_profile_action kpu8_action_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile_action kpu9_action_entries[] = {
|
||||
static struct npc_kpu_profile_action kpu9_action_entries[] __maybe_unused = {
|
||||
NPC_KPU_NOP_ACTION,
|
||||
NPC_KPU_NOP_ACTION,
|
||||
NPC_KPU_NOP_ACTION,
|
||||
|
|
@ -14440,7 +14452,7 @@ static struct npc_kpu_profile_action kpu9_action_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile_action kpu10_action_entries[] = {
|
||||
static struct npc_kpu_profile_action kpu10_action_entries[] __maybe_unused = {
|
||||
NPC_KPU_NOP_ACTION,
|
||||
NPC_KPU_NOP_ACTION,
|
||||
NPC_KPU_NOP_ACTION,
|
||||
|
|
@ -14593,7 +14605,7 @@ static struct npc_kpu_profile_action kpu10_action_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile_action kpu11_action_entries[] = {
|
||||
static struct npc_kpu_profile_action kpu11_action_entries[] __maybe_unused = {
|
||||
NPC_KPU_NOP_ACTION,
|
||||
NPC_KPU_NOP_ACTION,
|
||||
NPC_KPU_NOP_ACTION,
|
||||
|
|
@ -14874,7 +14886,7 @@ static struct npc_kpu_profile_action kpu11_action_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile_action kpu12_action_entries[] = {
|
||||
static struct npc_kpu_profile_action kpu12_action_entries[] __maybe_unused = {
|
||||
NPC_KPU_NOP_ACTION,
|
||||
NPC_KPU_NOP_ACTION,
|
||||
NPC_KPU_NOP_ACTION,
|
||||
|
|
@ -15107,7 +15119,7 @@ static struct npc_kpu_profile_action kpu12_action_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile_action kpu13_action_entries[] = {
|
||||
static struct npc_kpu_profile_action kpu13_action_entries[] __maybe_unused = {
|
||||
NPC_KPU_NOP_ACTION,
|
||||
NPC_KPU_NOP_ACTION,
|
||||
NPC_KPU_NOP_ACTION,
|
||||
|
|
@ -15124,7 +15136,7 @@ static struct npc_kpu_profile_action kpu13_action_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile_action kpu14_action_entries[] = {
|
||||
static struct npc_kpu_profile_action kpu14_action_entries[] __maybe_unused = {
|
||||
NPC_KPU_NOP_ACTION,
|
||||
NPC_KPU_NOP_ACTION,
|
||||
NPC_KPU_NOP_ACTION,
|
||||
|
|
@ -15141,7 +15153,7 @@ static struct npc_kpu_profile_action kpu14_action_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile_action kpu15_action_entries[] = {
|
||||
static struct npc_kpu_profile_action kpu15_action_entries[] __maybe_unused = {
|
||||
NPC_KPU_NOP_ACTION,
|
||||
NPC_KPU_NOP_ACTION,
|
||||
NPC_KPU_NOP_ACTION,
|
||||
|
|
@ -15326,7 +15338,7 @@ static struct npc_kpu_profile_action kpu15_action_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile_action kpu16_action_entries[] = {
|
||||
static struct npc_kpu_profile_action kpu16_action_entries[] __maybe_unused = {
|
||||
NPC_KPU_NOP_ACTION,
|
||||
NPC_KPU_NOP_ACTION,
|
||||
NPC_KPU_NOP_ACTION,
|
||||
|
|
@ -15383,7 +15395,7 @@ static struct npc_kpu_profile_action kpu16_action_entries[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_kpu_profile npc_kpu_profiles[] = {
|
||||
static struct npc_kpu_profile npc_kpu_profiles[] __maybe_unused = {
|
||||
{
|
||||
ARRAY_SIZE(kpu1_cam_entries),
|
||||
ARRAY_SIZE(kpu1_action_entries),
|
||||
|
|
@ -15482,7 +15494,7 @@ static struct npc_kpu_profile npc_kpu_profiles[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_lt_def_cfg npc_lt_defaults = {
|
||||
static struct npc_lt_def_cfg npc_lt_defaults __maybe_unused = {
|
||||
.rx_ol2 = {
|
||||
.lid = NPC_LID_LA,
|
||||
.ltype_match = NPC_LT_LA_ETHER,
|
||||
|
|
@ -15604,7 +15616,7 @@ static struct npc_lt_def_cfg npc_lt_defaults = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct npc_mcam_kex npc_mkex_default = {
|
||||
static struct npc_mcam_kex npc_mkex_default __maybe_unused = {
|
||||
.mkex_sign = MKEX_SIGN,
|
||||
.name = "default",
|
||||
.kpu_version = NPC_KPU_PROFILE_VER,
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include "rvu_npc_hash.h"
|
||||
#include "cn20k/reg.h"
|
||||
#include "cn20k/api.h"
|
||||
#include "cn20k/npc.h"
|
||||
|
||||
#define DRV_NAME "rvu_af"
|
||||
#define DRV_STRING "Marvell OcteonTX2 RVU Admin Function Driver"
|
||||
|
|
@ -599,6 +600,7 @@ static void rvu_check_min_msix_vec(struct rvu *rvu, int nvecs, int pf, int vf)
|
|||
|
||||
static int rvu_setup_msix_resources(struct rvu *rvu)
|
||||
{
|
||||
struct altaf_intr_notify *altaf_intr_data;
|
||||
struct rvu_hwinfo *hw = rvu->hw;
|
||||
int pf, vf, numvfs, hwvf, err;
|
||||
int nvecs, offset, max_msix;
|
||||
|
|
@ -705,7 +707,30 @@ static int rvu_setup_msix_resources(struct rvu *rvu)
|
|||
rvu->msix_base_iova = iova;
|
||||
rvu->msixtr_base_phy = phy_addr;
|
||||
|
||||
if (is_rvu_otx2(rvu) || is_cn20k(rvu->pdev))
|
||||
return 0;
|
||||
|
||||
if (!rvu->fwdata)
|
||||
goto fail;
|
||||
|
||||
altaf_intr_data = &rvu->fwdata->altaf_intr_info;
|
||||
if (altaf_intr_data->gint_paddr) {
|
||||
iova = dma_map_resource(rvu->dev, altaf_intr_data->gint_paddr,
|
||||
PCI_MSIX_ENTRY_SIZE,
|
||||
DMA_BIDIRECTIONAL, 0);
|
||||
|
||||
if (dma_mapping_error(rvu->dev, iova))
|
||||
goto fail;
|
||||
|
||||
altaf_intr_data->gint_iova_addr = iova;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
dma_unmap_resource(rvu->dev, phy_addr, max_msix * PCI_MSIX_ENTRY_SIZE,
|
||||
DMA_BIDIRECTIONAL, 0);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static void rvu_reset_msix(struct rvu *rvu)
|
||||
|
|
@ -1396,7 +1421,6 @@ static void rvu_detach_block(struct rvu *rvu, int pcifunc, int blktype)
|
|||
if (blkaddr < 0)
|
||||
return;
|
||||
|
||||
|
||||
block = &hw->block[blkaddr];
|
||||
|
||||
num_lfs = rvu_get_rsrc_mapcount(pfvf, block->addr);
|
||||
|
|
@ -1467,6 +1491,13 @@ static int rvu_detach_rsrcs(struct rvu *rvu, struct rsrc_detach *detach,
|
|||
else if ((blkid == BLKADDR_CPT1) && !detach->cptlfs)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (detach_all ||
|
||||
(detach && (blkid == BLKADDR_NIX0 ||
|
||||
blkid == BLKADDR_NIX1) &&
|
||||
detach->nixlf))
|
||||
npc_cn20k_dft_rules_free(rvu, pcifunc);
|
||||
|
||||
rvu_detach_block(rvu, pcifunc, block->type);
|
||||
}
|
||||
|
||||
|
|
@ -1750,6 +1781,12 @@ int rvu_mbox_handler_attach_resources(struct rvu *rvu,
|
|||
err = rvu_attach_block(rvu, pcifunc, BLKTYPE_NIX, 1, attach);
|
||||
if (err)
|
||||
goto fail2;
|
||||
|
||||
if (is_cn20k(rvu->pdev)) {
|
||||
err = npc_cn20k_dft_rules_alloc(rvu, pcifunc);
|
||||
if (err)
|
||||
goto fail3;
|
||||
}
|
||||
}
|
||||
|
||||
if (attach->sso) {
|
||||
|
|
@ -1763,7 +1800,7 @@ int rvu_mbox_handler_attach_resources(struct rvu *rvu,
|
|||
err = rvu_attach_block(rvu, pcifunc, BLKTYPE_SSO,
|
||||
attach->sso, attach);
|
||||
if (err)
|
||||
goto fail3;
|
||||
goto fail4;
|
||||
}
|
||||
|
||||
if (attach->ssow) {
|
||||
|
|
@ -1772,7 +1809,7 @@ int rvu_mbox_handler_attach_resources(struct rvu *rvu,
|
|||
err = rvu_attach_block(rvu, pcifunc, BLKTYPE_SSOW,
|
||||
attach->ssow, attach);
|
||||
if (err)
|
||||
goto fail4;
|
||||
goto fail5;
|
||||
}
|
||||
|
||||
if (attach->timlfs) {
|
||||
|
|
@ -1781,7 +1818,7 @@ int rvu_mbox_handler_attach_resources(struct rvu *rvu,
|
|||
err = rvu_attach_block(rvu, pcifunc, BLKTYPE_TIM,
|
||||
attach->timlfs, attach);
|
||||
if (err)
|
||||
goto fail5;
|
||||
goto fail6;
|
||||
}
|
||||
|
||||
if (attach->cptlfs) {
|
||||
|
|
@ -1791,24 +1828,28 @@ int rvu_mbox_handler_attach_resources(struct rvu *rvu,
|
|||
err = rvu_attach_block(rvu, pcifunc, BLKTYPE_CPT,
|
||||
attach->cptlfs, attach);
|
||||
if (err)
|
||||
goto fail6;
|
||||
goto fail7;
|
||||
}
|
||||
|
||||
mutex_unlock(&rvu->rsrc_lock);
|
||||
return 0;
|
||||
|
||||
fail6:
|
||||
fail7:
|
||||
if (attach->timlfs)
|
||||
rvu_detach_block(rvu, pcifunc, BLKTYPE_TIM);
|
||||
|
||||
fail5:
|
||||
fail6:
|
||||
if (attach->ssow)
|
||||
rvu_detach_block(rvu, pcifunc, BLKTYPE_SSOW);
|
||||
|
||||
fail4:
|
||||
fail5:
|
||||
if (attach->sso)
|
||||
rvu_detach_block(rvu, pcifunc, BLKTYPE_SSO);
|
||||
|
||||
fail4:
|
||||
if (is_cn20k(rvu->pdev))
|
||||
npc_cn20k_dft_rules_free(rvu, pcifunc);
|
||||
|
||||
fail3:
|
||||
if (attach->nixlf)
|
||||
rvu_detach_block(rvu, pcifunc, BLKTYPE_NIX);
|
||||
|
|
@ -2185,6 +2226,33 @@ int rvu_mbox_handler_ndc_sync_op(struct rvu *rvu,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void rvu_notify_altaf(struct rvu *rvu, u16 pcifunc, u64 op)
|
||||
{
|
||||
int pf, vf;
|
||||
|
||||
if (!rvu->fwdata)
|
||||
return;
|
||||
|
||||
if (op == ALTAF_FLR) {
|
||||
pf = rvu_get_pf(rvu->pdev, pcifunc);
|
||||
set_bit(pf, rvu->fwdata->altaf_intr_info.flr_pf_bmap);
|
||||
if (pcifunc & RVU_PFVF_FUNC_MASK) {
|
||||
vf = pcifunc & RVU_PFVF_FUNC_MASK;
|
||||
if (vf >= 128) {
|
||||
WARN(1,
|
||||
"flr_vf_bmap size is 128 bits, vf=%u\n",
|
||||
vf);
|
||||
return;
|
||||
}
|
||||
|
||||
set_bit(vf, rvu->fwdata->altaf_intr_info.flr_vf_bmap);
|
||||
}
|
||||
}
|
||||
|
||||
rvu_write64(rvu, BLKADDR_NIX0, AF_BAR2_ALIASX(0, NIX_GINT_INT_W1S), op);
|
||||
usleep_range(5000, 6000);
|
||||
}
|
||||
|
||||
static int rvu_process_mbox_msg(struct otx2_mbox *mbox, int devid,
|
||||
struct mbox_msghdr *req)
|
||||
{
|
||||
|
|
@ -2268,7 +2336,8 @@ static void __rvu_mbox_handler(struct rvu_work *mwork, int type, bool poll)
|
|||
|
||||
offset = mbox->rx_start + ALIGN(sizeof(*req_hdr), MBOX_MSG_ALIGN);
|
||||
|
||||
if (req_hdr->sig && !(is_rvu_otx2(rvu) || is_cn20k(rvu->pdev))) {
|
||||
if (req_hdr->sig && rvu->altaf_ready &&
|
||||
!(is_rvu_otx2(rvu) || is_cn20k(rvu->pdev))) {
|
||||
req_hdr->opt_msg = mw->mbox_wrk[devid].num_msgs;
|
||||
rvu_write64(rvu, BLKADDR_NIX0, RVU_AF_BAR2_SEL,
|
||||
RVU_AF_BAR2_PFID);
|
||||
|
|
@ -2777,6 +2846,16 @@ static void rvu_blklf_teardown(struct rvu *rvu, u16 pcifunc, u8 blkaddr)
|
|||
block = &rvu->hw->block[blkaddr];
|
||||
num_lfs = rvu_get_rsrc_mapcount(rvu_get_pfvf(rvu, pcifunc),
|
||||
block->addr);
|
||||
|
||||
if (block->addr == BLKADDR_TIM && rvu->altaf_ready) {
|
||||
rvu_notify_altaf(rvu, pcifunc, ALTAF_FLR);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((block->addr == BLKADDR_SSO || block->addr == BLKADDR_SSOW) &&
|
||||
rvu->altaf_ready)
|
||||
return;
|
||||
|
||||
if (!num_lfs)
|
||||
return;
|
||||
for (slot = 0; slot < num_lfs; slot++) {
|
||||
|
|
@ -3060,12 +3139,12 @@ static int rvu_afvf_msix_vectors_num_ok(struct rvu *rvu)
|
|||
|
||||
static int rvu_register_interrupts(struct rvu *rvu)
|
||||
{
|
||||
int ret, offset, pf_vec_start;
|
||||
int i, ret, offset, pf_vec_start;
|
||||
|
||||
rvu->num_vec = pci_msix_vec_count(rvu->pdev);
|
||||
|
||||
rvu->irq_name = devm_kmalloc_array(rvu->dev, rvu->num_vec,
|
||||
NAME_SIZE, GFP_KERNEL);
|
||||
rvu->irq_name = devm_kcalloc(rvu->dev, rvu->num_vec,
|
||||
NAME_SIZE, GFP_KERNEL);
|
||||
if (!rvu->irq_name)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -3251,6 +3330,13 @@ static int rvu_register_interrupts(struct rvu *rvu)
|
|||
if (ret)
|
||||
goto fail;
|
||||
|
||||
for (i = 0; i < rvu->num_vec; i++) {
|
||||
if (strstr(&rvu->irq_name[i * NAME_SIZE], "Mbox") ||
|
||||
strstr(&rvu->irq_name[i * NAME_SIZE], "FLR"))
|
||||
irq_set_affinity(pci_irq_vector(rvu->pdev, i),
|
||||
cpumask_of(0));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
|
|
@ -3279,8 +3365,8 @@ static int rvu_flr_init(struct rvu *rvu)
|
|||
cfg | BIT_ULL(22));
|
||||
}
|
||||
|
||||
rvu->flr_wq = alloc_ordered_workqueue("rvu_afpf_flr",
|
||||
WQ_HIGHPRI | WQ_MEM_RECLAIM);
|
||||
rvu->flr_wq = alloc_workqueue("rvu_afpf_flr",
|
||||
WQ_HIGHPRI | WQ_MEM_RECLAIM, 0);
|
||||
if (!rvu->flr_wq)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ struct npc_key_field {
|
|||
/* Masks where all set bits indicate position
|
||||
* of a field in the key
|
||||
*/
|
||||
u64 kw_mask[NPC_MAX_KWS_IN_KEY];
|
||||
u64 kw_mask[NPC_KWS_IN_KEY_SZ_MAX];
|
||||
/* Number of words in the key a field spans. If a field is
|
||||
* of 16 bytes and key offset is 4 then the field will use
|
||||
* 4 bytes in KW0, 8 bytes in KW1 and 4 bytes in KW2 and
|
||||
|
|
@ -308,6 +308,7 @@ struct rvu_pfvf {
|
|||
u64 lmt_map_ent_w1; /* Preseving the word1 of lmtst map table entry*/
|
||||
unsigned long flags;
|
||||
struct sdp_node_info *sdp_info;
|
||||
u8 hw_prio; /* Hw priority of default rules */
|
||||
};
|
||||
|
||||
enum rvu_pfvf_flags {
|
||||
|
|
@ -447,9 +448,11 @@ struct rvu_hwinfo {
|
|||
u8 sdp_links;
|
||||
u8 cpt_links; /* Number of CPT links */
|
||||
u8 npc_kpus; /* No of parser units */
|
||||
u8 npc_kpms; /* Number of enhanced parser units */
|
||||
u8 npc_kex_extr; /* Number of LDATA extractors per KEX */
|
||||
u8 npc_pkinds; /* No of port kinds */
|
||||
u8 npc_intfs; /* No of interfaces */
|
||||
u8 npc_kpu_entries; /* No of KPU entries */
|
||||
u16 npc_kpu_entries; /* No of KPU entries */
|
||||
u16 npc_counters; /* No of match stats counters */
|
||||
u32 lbk_bufsize; /* FIFO size supported by LBK */
|
||||
bool npc_ext_set; /* Extended register set */
|
||||
|
|
@ -552,7 +555,11 @@ struct npc_kpu_profile_adapter {
|
|||
const struct npc_lt_def_cfg *lt_def;
|
||||
const struct npc_kpu_profile_action *ikpu; /* array[pkinds] */
|
||||
const struct npc_kpu_profile *kpu; /* array[kpus] */
|
||||
struct npc_mcam_kex *mkex;
|
||||
union npc_mcam_key_prfl {
|
||||
struct npc_mcam_kex *mkex;
|
||||
/* used for cn9k and cn10k */
|
||||
struct npc_mcam_kex_extr *mkex_extr; /* used for cn20k */
|
||||
} mcam_kex_prfl;
|
||||
struct npc_mcam_kex_hash *mkex_hash;
|
||||
bool custom;
|
||||
size_t pkinds;
|
||||
|
|
@ -1117,8 +1124,8 @@ int rvu_cgx_cfg_pause_frm(struct rvu *rvu, u16 pcifunc, u8 tx_pause, u8 rx_pause
|
|||
void rvu_mac_reset(struct rvu *rvu, u16 pcifunc);
|
||||
u32 rvu_cgx_get_lmac_fifolen(struct rvu *rvu, int cgx, int lmac);
|
||||
void cgx_start_linkup(struct rvu *rvu);
|
||||
int npc_get_nixlf_mcam_index(struct npc_mcam *mcam, u16 pcifunc, int nixlf,
|
||||
int type);
|
||||
int npc_get_nixlf_mcam_index(struct npc_mcam *mcam,
|
||||
u16 pcifunc, int nixlf, int type);
|
||||
bool is_mcam_entry_enabled(struct rvu *rvu, struct npc_mcam *mcam, int blkaddr,
|
||||
int index);
|
||||
int rvu_npc_init(struct rvu *rvu);
|
||||
|
|
@ -1184,4 +1191,5 @@ int rvu_rep_pf_init(struct rvu *rvu);
|
|||
int rvu_rep_install_mcam_rules(struct rvu *rvu);
|
||||
void rvu_rep_update_rules(struct rvu *rvu, u16 pcifunc, bool ena);
|
||||
int rvu_rep_notify_pfvf_state(struct rvu *rvu, u16 pcifunc, bool enable);
|
||||
int npc_mcam_verify_entry(struct npc_mcam *mcam, u16 pcifunc, int entry);
|
||||
#endif /* RVU_H */
|
||||
|
|
|
|||
|
|
@ -21,7 +21,9 @@
|
|||
#include "rvu_npc_hash.h"
|
||||
#include "mcs.h"
|
||||
|
||||
#include "cn20k/reg.h"
|
||||
#include "cn20k/debugfs.h"
|
||||
#include "cn20k/npc.h"
|
||||
|
||||
#define DEBUGFS_DIR_NAME "octeontx2"
|
||||
|
||||
|
|
@ -3196,7 +3198,9 @@ static void rvu_print_npc_mcam_info(struct seq_file *s,
|
|||
static int rvu_dbg_npc_mcam_info_display(struct seq_file *filp, void *unsued)
|
||||
{
|
||||
struct rvu *rvu = filp->private;
|
||||
int x4_free, x2_free, sb_free;
|
||||
int pf, vf, numvfs, blkaddr;
|
||||
struct npc_priv_t *npc_priv;
|
||||
struct npc_mcam *mcam;
|
||||
u16 pcifunc, counters;
|
||||
u64 cfg;
|
||||
|
|
@ -3210,16 +3214,34 @@ static int rvu_dbg_npc_mcam_info_display(struct seq_file *filp, void *unsued)
|
|||
|
||||
seq_puts(filp, "\nNPC MCAM info:\n");
|
||||
/* MCAM keywidth on receive and transmit sides */
|
||||
cfg = rvu_read64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(NIX_INTF_RX));
|
||||
cfg = (cfg >> 32) & 0x07;
|
||||
seq_printf(filp, "\t\t RX keywidth \t: %s\n", (cfg == NPC_MCAM_KEY_X1) ?
|
||||
"112bits" : ((cfg == NPC_MCAM_KEY_X2) ?
|
||||
"224bits" : "448bits"));
|
||||
cfg = rvu_read64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(NIX_INTF_TX));
|
||||
cfg = (cfg >> 32) & 0x07;
|
||||
seq_printf(filp, "\t\t TX keywidth \t: %s\n", (cfg == NPC_MCAM_KEY_X1) ?
|
||||
"112bits" : ((cfg == NPC_MCAM_KEY_X2) ?
|
||||
"224bits" : "448bits"));
|
||||
if (is_cn20k(rvu->pdev)) {
|
||||
npc_priv = npc_priv_get();
|
||||
seq_printf(filp, "\t\t RX keywidth \t: %s\n",
|
||||
(npc_priv->kw == NPC_MCAM_KEY_X1) ?
|
||||
"256bits" : "512bits");
|
||||
|
||||
npc_cn20k_subbank_calc_free(rvu, &x2_free, &x4_free, &sb_free);
|
||||
seq_printf(filp, "\t\t free x4 slots\t: %d\n", x4_free);
|
||||
|
||||
seq_printf(filp, "\t\t free x2 slots\t: %d\n", x2_free);
|
||||
|
||||
seq_printf(filp, "\t\t free subbanks\t: %d\n", sb_free);
|
||||
} else {
|
||||
cfg = rvu_read64(rvu, blkaddr,
|
||||
NPC_AF_INTFX_KEX_CFG(NIX_INTF_RX));
|
||||
cfg = (cfg >> 32) & 0x07;
|
||||
seq_printf(filp, "\t\t RX keywidth \t: %s\n",
|
||||
(cfg == NPC_MCAM_KEY_X1) ?
|
||||
"112bits" : ((cfg == NPC_MCAM_KEY_X2) ?
|
||||
"224bits" : "448bits"));
|
||||
cfg = rvu_read64(rvu, blkaddr,
|
||||
NPC_AF_INTFX_KEX_CFG(NIX_INTF_TX));
|
||||
cfg = (cfg >> 32) & 0x07;
|
||||
seq_printf(filp, "\t\t TX keywidth \t: %s\n",
|
||||
(cfg == NPC_MCAM_KEY_X1) ?
|
||||
"112bits" : ((cfg == NPC_MCAM_KEY_X2) ?
|
||||
"224bits" : "448bits"));
|
||||
}
|
||||
|
||||
mutex_lock(&mcam->lock);
|
||||
/* MCAM entries */
|
||||
|
|
@ -3506,11 +3528,11 @@ static int rvu_dbg_npc_mcam_show_rules(struct seq_file *s, void *unused)
|
|||
struct rvu_npc_mcam_rule *iter;
|
||||
struct rvu *rvu = s->private;
|
||||
struct npc_mcam *mcam;
|
||||
int pf, vf = -1;
|
||||
int pf, vf = -1, bank;
|
||||
u16 target, index;
|
||||
bool enabled;
|
||||
u64 hits, off;
|
||||
int blkaddr;
|
||||
u16 target;
|
||||
u64 hits;
|
||||
|
||||
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
|
||||
if (blkaddr < 0)
|
||||
|
|
@ -3554,6 +3576,15 @@ static int rvu_dbg_npc_mcam_show_rules(struct seq_file *s, void *unused)
|
|||
|
||||
enabled = is_mcam_entry_enabled(rvu, mcam, blkaddr, iter->entry);
|
||||
seq_printf(s, "\tenabled: %s\n", enabled ? "yes" : "no");
|
||||
if (is_cn20k(rvu->pdev)) {
|
||||
seq_printf(s, "\tpriority: %u\n", iter->hw_prio);
|
||||
index = iter->entry & (mcam->banksize - 1);
|
||||
bank = npc_get_bank(mcam, iter->entry);
|
||||
off = NPC_AF_CN20K_MCAMEX_BANKX_STAT_EXT(index, bank);
|
||||
hits = rvu_read64(rvu, blkaddr, off);
|
||||
seq_printf(s, "\thits: %lld\n", hits);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!iter->has_cntr)
|
||||
continue;
|
||||
|
|
@ -3698,9 +3729,9 @@ static int rvu_dbg_npc_exact_drop_cnt(struct seq_file *s, void *unused)
|
|||
struct npc_exact_table *table;
|
||||
struct rvu *rvu = s->private;
|
||||
struct npc_key_field *field;
|
||||
u64 cfg, cam1, off;
|
||||
u16 chan, pcifunc;
|
||||
int blkaddr, i;
|
||||
u64 cfg, cam1;
|
||||
char *str;
|
||||
|
||||
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
|
||||
|
|
@ -3721,11 +3752,17 @@ static int rvu_dbg_npc_exact_drop_cnt(struct seq_file *s, void *unused)
|
|||
chan = field->kw_mask[0] & cam1;
|
||||
|
||||
str = (cfg & 1) ? "enabled" : "disabled";
|
||||
if (is_cn20k(rvu->pdev)) {
|
||||
off = NPC_AF_CN20K_MCAMEX_BANKX_STAT_EXT(i, 0);
|
||||
seq_printf(s, "0x%x\t%d\t\t%llu\t0x%x\t%s\n", pcifunc,
|
||||
i, rvu_read64(rvu, blkaddr, off), chan, str);
|
||||
} else {
|
||||
off = NPC_AF_MATCH_STATX(table->counter_idx[i]);
|
||||
seq_printf(s, "0x%x\t%d\t\t%llu\t0x%x\t%s\n", pcifunc,
|
||||
i, rvu_read64(rvu, blkaddr, off),
|
||||
chan, str);
|
||||
}
|
||||
|
||||
seq_printf(s, "0x%x\t%d\t\t%llu\t0x%x\t%s\n", pcifunc, i,
|
||||
rvu_read64(rvu, blkaddr,
|
||||
NPC_AF_MATCH_STATX(table->counter_idx[i])),
|
||||
chan, str);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -3745,6 +3782,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;
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include "rvu_reg.h"
|
||||
#include "rvu_struct.h"
|
||||
#include "rvu_npc_hash.h"
|
||||
#include "cn20k/npc.h"
|
||||
|
||||
#define DRV_NAME "octeontx2-af"
|
||||
|
||||
|
|
@ -1256,9 +1257,71 @@ enum rvu_af_dl_param_id {
|
|||
RVU_AF_DEVLINK_PARAM_ID_NPC_MCAM_ZONE_PERCENT,
|
||||
RVU_AF_DEVLINK_PARAM_ID_NPC_EXACT_FEATURE_DISABLE,
|
||||
RVU_AF_DEVLINK_PARAM_ID_NPC_DEF_RULE_CNTR_ENABLE,
|
||||
RVU_AF_DEVLINK_PARAM_ID_NPC_DEFRAG,
|
||||
RVU_AF_DEVLINK_PARAM_ID_NIX_MAXLF,
|
||||
};
|
||||
|
||||
static int rvu_af_npc_defrag_feature_get(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct rvu_devlink *rvu_dl = devlink_priv(devlink);
|
||||
struct rvu *rvu = rvu_dl->rvu;
|
||||
bool enabled;
|
||||
|
||||
enabled = is_cn20k(rvu->pdev);
|
||||
|
||||
snprintf(ctx->val.vstr, sizeof(ctx->val.vstr), "%s",
|
||||
enabled ? "enabled" : "disabled");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rvu_af_npc_defrag(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct rvu_devlink *rvu_dl = devlink_priv(devlink);
|
||||
struct rvu *rvu = rvu_dl->rvu;
|
||||
|
||||
/* It is hard to roll back if defrag process fails.
|
||||
* print a error message and return fault.
|
||||
*/
|
||||
if (npc_cn20k_defrag(rvu)) {
|
||||
dev_err(rvu->dev, "Defrag process failed\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rvu_af_npc_defrag_feature_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct rvu_devlink *rvu_dl = devlink_priv(devlink);
|
||||
struct rvu *rvu = rvu_dl->rvu;
|
||||
u64 enable;
|
||||
|
||||
if (kstrtoull(val.vstr, 10, &enable)) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Only 1 value is supported");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (enable != 1) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Only initiating defrag is supported");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (is_cn20k(rvu->pdev))
|
||||
return 0;
|
||||
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Can defrag NPC only in cn20k silicon");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static int rvu_af_npc_exact_feature_get(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
|
|
@ -1561,6 +1624,15 @@ static const struct devlink_ops rvu_devlink_ops = {
|
|||
.eswitch_mode_set = rvu_devlink_eswitch_mode_set,
|
||||
};
|
||||
|
||||
static const struct devlink_param rvu_af_dl_param_defrag[] = {
|
||||
DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_NPC_DEFRAG,
|
||||
"npc_defrag", DEVLINK_PARAM_TYPE_STRING,
|
||||
BIT(DEVLINK_PARAM_CMODE_RUNTIME),
|
||||
rvu_af_npc_defrag_feature_get,
|
||||
rvu_af_npc_defrag,
|
||||
rvu_af_npc_defrag_feature_validate),
|
||||
};
|
||||
|
||||
int rvu_register_dl(struct rvu *rvu)
|
||||
{
|
||||
struct rvu_devlink *rvu_dl;
|
||||
|
|
@ -1593,6 +1665,17 @@ int rvu_register_dl(struct rvu *rvu)
|
|||
goto err_dl_health;
|
||||
}
|
||||
|
||||
if (is_cn20k(rvu->pdev)) {
|
||||
err = devlink_params_register(dl, rvu_af_dl_param_defrag,
|
||||
ARRAY_SIZE(rvu_af_dl_param_defrag));
|
||||
if (err) {
|
||||
dev_err(rvu->dev,
|
||||
"devlink defrag params register failed with error %d",
|
||||
err);
|
||||
goto err_dl_defrag;
|
||||
}
|
||||
}
|
||||
|
||||
/* Register exact match devlink only for CN10K-B */
|
||||
if (!rvu_npc_exact_has_match_table(rvu))
|
||||
goto done;
|
||||
|
|
@ -1601,7 +1684,8 @@ int rvu_register_dl(struct rvu *rvu)
|
|||
ARRAY_SIZE(rvu_af_dl_param_exact_match));
|
||||
if (err) {
|
||||
dev_err(rvu->dev,
|
||||
"devlink exact match params register failed with error %d", err);
|
||||
"devlink exact match params register failed with error %d",
|
||||
err);
|
||||
goto err_dl_exact_match;
|
||||
}
|
||||
|
||||
|
|
@ -1610,6 +1694,11 @@ int rvu_register_dl(struct rvu *rvu)
|
|||
return 0;
|
||||
|
||||
err_dl_exact_match:
|
||||
if (is_cn20k(rvu->pdev))
|
||||
devlink_params_unregister(dl, rvu_af_dl_param_defrag,
|
||||
ARRAY_SIZE(rvu_af_dl_param_defrag));
|
||||
|
||||
err_dl_defrag:
|
||||
devlink_params_unregister(dl, rvu_af_dl_params, ARRAY_SIZE(rvu_af_dl_params));
|
||||
|
||||
err_dl_health:
|
||||
|
|
@ -1627,6 +1716,10 @@ void rvu_unregister_dl(struct rvu *rvu)
|
|||
|
||||
devlink_params_unregister(dl, rvu_af_dl_params, ARRAY_SIZE(rvu_af_dl_params));
|
||||
|
||||
if (is_cn20k(rvu->pdev))
|
||||
devlink_params_unregister(dl, rvu_af_dl_param_defrag,
|
||||
ARRAY_SIZE(rvu_af_dl_param_defrag));
|
||||
|
||||
/* Unregister exact match devlink only for CN10K-B */
|
||||
if (rvu_npc_exact_has_match_table(rvu))
|
||||
devlink_params_unregister(dl, rvu_af_dl_param_exact_match,
|
||||
|
|
|
|||
|
|
@ -5289,7 +5289,6 @@ int rvu_mbox_handler_nix_lf_stop_rx(struct rvu *rvu, struct msg_req *req,
|
|||
/* Disable the interface if it is in any multicast list */
|
||||
nix_mcast_update_mce_entry(rvu, pcifunc, 0);
|
||||
|
||||
|
||||
pfvf = rvu_get_pfvf(rvu, pcifunc);
|
||||
clear_bit(NIXLF_INITIALIZED, &pfvf->flags);
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
21
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.h
Normal file
21
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Marvell RVU Admin Function driver
|
||||
*
|
||||
* Copyright (C) 2026 Marvell.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef RVU_NPC_H
|
||||
#define RVU_NPC_H
|
||||
|
||||
u64 npc_enable_mask(int count);
|
||||
void npc_load_kpu_profile(struct rvu *rvu);
|
||||
void npc_config_kpuaction(struct rvu *rvu, int blkaddr,
|
||||
const struct npc_kpu_profile_action *kpuaction,
|
||||
int kpu, int entry, bool pkind);
|
||||
int npc_fwdb_prfl_img_map(struct rvu *rvu, void __iomem **prfl_img_addr,
|
||||
u64 *size);
|
||||
|
||||
void npc_mcam_clear_bit(struct npc_mcam *mcam, u16 index);
|
||||
void npc_mcam_set_bit(struct npc_mcam *mcam, u16 index);
|
||||
#endif /* RVU_NPC_H */
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -15,7 +15,19 @@
|
|||
#define NPC_LDATA_EN BIT_ULL(7)
|
||||
|
||||
void npc_update_entry(struct rvu *rvu, enum key_fields type,
|
||||
struct mcam_entry *entry, u64 val_lo,
|
||||
struct mcam_entry_mdata *mdata, u64 val_lo,
|
||||
u64 val_hi, u64 mask_lo, u64 mask_hi, u8 intf);
|
||||
|
||||
void npc_update_flow(struct rvu *rvu, struct mcam_entry_mdata *mdata,
|
||||
u64 features, struct flow_msg *pkt,
|
||||
struct flow_msg *mask,
|
||||
struct rvu_npc_mcam_rule *output, u8 intf,
|
||||
int blkaddr);
|
||||
|
||||
void
|
||||
npc_populate_mcam_mdata(struct rvu *rvu,
|
||||
struct mcam_entry_mdata *mdata,
|
||||
struct cn20k_mcam_entry *cn20k_entry,
|
||||
struct mcam_entry *entry);
|
||||
|
||||
#endif /* RVU_NPC_FS_H */
|
||||
|
|
|
|||
|
|
@ -125,6 +125,9 @@ static void npc_program_mkex_hash_rx(struct rvu *rvu, int blkaddr,
|
|||
struct npc_mcam_kex_hash *mkex_hash = rvu->kpu.mkex_hash;
|
||||
int lid, lt, ld, hash_cnt = 0;
|
||||
|
||||
if (is_cn20k(rvu->pdev))
|
||||
return;
|
||||
|
||||
if (is_npc_intf_tx(intf))
|
||||
return;
|
||||
|
||||
|
|
@ -165,6 +168,9 @@ static void npc_program_mkex_hash_tx(struct rvu *rvu, int blkaddr,
|
|||
struct npc_mcam_kex_hash *mkex_hash = rvu->kpu.mkex_hash;
|
||||
int lid, lt, ld, hash_cnt = 0;
|
||||
|
||||
if (is_cn20k(rvu->pdev))
|
||||
return;
|
||||
|
||||
if (is_npc_intf_rx(intf))
|
||||
return;
|
||||
|
||||
|
|
@ -224,6 +230,9 @@ void npc_program_mkex_hash(struct rvu *rvu, int blkaddr)
|
|||
struct rvu_hwinfo *hw = rvu->hw;
|
||||
u64 cfg;
|
||||
|
||||
if (is_cn20k(rvu->pdev))
|
||||
return;
|
||||
|
||||
/* Check if hardware supports hash extraction */
|
||||
if (!hwcap->npc_hash_extract)
|
||||
return;
|
||||
|
|
@ -273,7 +282,7 @@ void npc_program_mkex_hash(struct rvu *rvu, int blkaddr)
|
|||
}
|
||||
|
||||
void npc_update_field_hash(struct rvu *rvu, u8 intf,
|
||||
struct mcam_entry *entry,
|
||||
struct mcam_entry_mdata *mdata,
|
||||
int blkaddr,
|
||||
u64 features,
|
||||
struct flow_msg *pkt,
|
||||
|
|
@ -284,9 +293,13 @@ void npc_update_field_hash(struct rvu *rvu, u8 intf,
|
|||
struct npc_mcam_kex_hash *mkex_hash = rvu->kpu.mkex_hash;
|
||||
struct npc_get_field_hash_info_req req;
|
||||
struct npc_get_field_hash_info_rsp rsp;
|
||||
u8 hash_idx, lid, ltype, ltype_mask;
|
||||
u64 ldata[2], cfg;
|
||||
u32 field_hash;
|
||||
u8 hash_idx;
|
||||
bool en;
|
||||
|
||||
if (is_cn20k(rvu->pdev))
|
||||
return;
|
||||
|
||||
if (!rvu->hw->cap.npc_hash_extract) {
|
||||
dev_dbg(rvu->dev, "%s: Field hash extract feature is not supported\n", __func__);
|
||||
|
|
@ -298,60 +311,60 @@ void npc_update_field_hash(struct rvu *rvu, u8 intf,
|
|||
|
||||
for (hash_idx = 0; hash_idx < NPC_MAX_HASH; hash_idx++) {
|
||||
cfg = rvu_read64(rvu, blkaddr, NPC_AF_INTFX_HASHX_CFG(intf, hash_idx));
|
||||
if ((cfg & BIT_ULL(11)) && (cfg & BIT_ULL(12))) {
|
||||
u8 lid = (cfg & GENMASK_ULL(10, 8)) >> 8;
|
||||
u8 ltype = (cfg & GENMASK_ULL(7, 4)) >> 4;
|
||||
u8 ltype_mask = cfg & GENMASK_ULL(3, 0);
|
||||
en = !!(cfg & BIT_ULL(11)) && (cfg & BIT_ULL(12));
|
||||
if (!en)
|
||||
continue;
|
||||
|
||||
if (mkex_hash->lid_lt_ld_hash_en[intf][lid][ltype][hash_idx]) {
|
||||
switch (ltype & ltype_mask) {
|
||||
/* If hash extract enabled is supported for IPv6 then
|
||||
* 128 bit IPv6 source and destination addressed
|
||||
* is hashed to 32 bit value.
|
||||
*/
|
||||
case NPC_LT_LC_IP6:
|
||||
/* ld[0] == hash_idx[0] == Source IPv6
|
||||
* ld[1] == hash_idx[1] == Destination IPv6
|
||||
*/
|
||||
if ((features & BIT_ULL(NPC_SIP_IPV6)) && !hash_idx) {
|
||||
u32 src_ip[IPV6_WORDS];
|
||||
lid = (cfg & GENMASK_ULL(10, 8)) >> 8;
|
||||
ltype = (cfg & GENMASK_ULL(7, 4)) >> 4;
|
||||
ltype_mask = cfg & GENMASK_ULL(3, 0);
|
||||
|
||||
be32_to_cpu_array(src_ip, pkt->ip6src, IPV6_WORDS);
|
||||
ldata[1] = (u64)src_ip[0] << 32 | src_ip[1];
|
||||
ldata[0] = (u64)src_ip[2] << 32 | src_ip[3];
|
||||
field_hash = npc_field_hash_calc(ldata,
|
||||
rsp,
|
||||
intf,
|
||||
hash_idx);
|
||||
npc_update_entry(rvu, NPC_SIP_IPV6, entry,
|
||||
field_hash, 0,
|
||||
GENMASK(31, 0), 0, intf);
|
||||
memcpy(&opkt->ip6src, &pkt->ip6src,
|
||||
sizeof(pkt->ip6src));
|
||||
memcpy(&omask->ip6src, &mask->ip6src,
|
||||
sizeof(mask->ip6src));
|
||||
} else if ((features & BIT_ULL(NPC_DIP_IPV6)) && hash_idx) {
|
||||
u32 dst_ip[IPV6_WORDS];
|
||||
if (!mkex_hash->lid_lt_ld_hash_en[intf][lid][ltype][hash_idx])
|
||||
continue;
|
||||
|
||||
be32_to_cpu_array(dst_ip, pkt->ip6dst, IPV6_WORDS);
|
||||
ldata[1] = (u64)dst_ip[0] << 32 | dst_ip[1];
|
||||
ldata[0] = (u64)dst_ip[2] << 32 | dst_ip[3];
|
||||
field_hash = npc_field_hash_calc(ldata,
|
||||
rsp,
|
||||
intf,
|
||||
hash_idx);
|
||||
npc_update_entry(rvu, NPC_DIP_IPV6, entry,
|
||||
field_hash, 0,
|
||||
GENMASK(31, 0), 0, intf);
|
||||
memcpy(&opkt->ip6dst, &pkt->ip6dst,
|
||||
sizeof(pkt->ip6dst));
|
||||
memcpy(&omask->ip6dst, &mask->ip6dst,
|
||||
sizeof(mask->ip6dst));
|
||||
}
|
||||
/* If hash extract enabled is supported for IPv6 then
|
||||
* 128 bit IPv6 source and destination addressed
|
||||
* is hashed to 32 bit value.
|
||||
*/
|
||||
if ((ltype & ltype_mask) != NPC_LT_LC_IP6)
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* ld[0] == hash_idx[0] == Source IPv6
|
||||
* ld[1] == hash_idx[1] == Destination IPv6
|
||||
*/
|
||||
if ((features & BIT_ULL(NPC_SIP_IPV6)) && !hash_idx) {
|
||||
u32 src_ip[IPV6_WORDS];
|
||||
|
||||
be32_to_cpu_array(src_ip, pkt->ip6src, IPV6_WORDS);
|
||||
ldata[1] = (u64)src_ip[0] << 32 | src_ip[1];
|
||||
ldata[0] = (u64)src_ip[2] << 32 | src_ip[3];
|
||||
field_hash = npc_field_hash_calc(ldata, rsp, intf,
|
||||
hash_idx);
|
||||
npc_update_entry(rvu, NPC_SIP_IPV6, mdata, field_hash,
|
||||
0, GENMASK(31, 0), 0, intf);
|
||||
memcpy(&opkt->ip6src, &pkt->ip6src,
|
||||
sizeof(pkt->ip6src));
|
||||
memcpy(&omask->ip6src, &mask->ip6src,
|
||||
sizeof(mask->ip6src));
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((features & BIT_ULL(NPC_DIP_IPV6)) && hash_idx) {
|
||||
u32 dst_ip[IPV6_WORDS];
|
||||
|
||||
be32_to_cpu_array(dst_ip, pkt->ip6dst, IPV6_WORDS);
|
||||
ldata[1] = (u64)dst_ip[0] << 32 | dst_ip[1];
|
||||
ldata[0] = (u64)dst_ip[2] << 32 | dst_ip[3];
|
||||
field_hash = npc_field_hash_calc(ldata, rsp, intf,
|
||||
hash_idx);
|
||||
npc_update_entry(rvu, NPC_DIP_IPV6, mdata,
|
||||
field_hash, 0, GENMASK(31, 0),
|
||||
0, intf);
|
||||
memcpy(&opkt->ip6dst, &pkt->ip6dst,
|
||||
sizeof(pkt->ip6dst));
|
||||
memcpy(&omask->ip6dst, &mask->ip6dst,
|
||||
sizeof(mask->ip6dst));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1874,6 +1887,9 @@ int rvu_npc_exact_init(struct rvu *rvu)
|
|||
u64 cfg;
|
||||
bool rc;
|
||||
|
||||
if (is_cn20k(rvu->pdev))
|
||||
return 0;
|
||||
|
||||
/* Read NPC_AF_CONST3 and check for have exact
|
||||
* match functionality is present
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ struct npc_mcam_kex_hash {
|
|||
} __packed;
|
||||
|
||||
void npc_update_field_hash(struct rvu *rvu, u8 intf,
|
||||
struct mcam_entry *entry,
|
||||
struct mcam_entry_mdata *mdata,
|
||||
int blkaddr,
|
||||
u64 features,
|
||||
struct flow_msg *pkt,
|
||||
|
|
|
|||
|
|
@ -251,6 +251,272 @@ static u8 cn20k_aura_bpid_idx(struct otx2_nic *pfvf, int aura_id)
|
|||
#endif
|
||||
}
|
||||
|
||||
static int cn20k_tc_get_entry_index(struct otx2_flow_config *flow_cfg,
|
||||
struct otx2_tc_flow *node)
|
||||
{
|
||||
struct otx2_tc_flow *tmp;
|
||||
int index = 0;
|
||||
|
||||
list_for_each_entry(tmp, &flow_cfg->flow_list_tc, list) {
|
||||
if (tmp == node)
|
||||
return index;
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int cn20k_tc_free_mcam_entry(struct otx2_nic *nic, u16 entry)
|
||||
{
|
||||
struct npc_mcam_free_entry_req *req;
|
||||
int err;
|
||||
|
||||
mutex_lock(&nic->mbox.lock);
|
||||
req = otx2_mbox_alloc_msg_npc_mcam_free_entry(&nic->mbox);
|
||||
if (!req) {
|
||||
mutex_unlock(&nic->mbox.lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
req->entry = entry;
|
||||
/* Send message to AF to free MCAM entries */
|
||||
err = otx2_sync_mbox_msg(&nic->mbox);
|
||||
if (err) {
|
||||
mutex_unlock(&nic->mbox.lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
mutex_unlock(&nic->mbox.lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool cn20k_tc_check_entry_shiftable(struct otx2_nic *nic,
|
||||
struct otx2_flow_config *flow_cfg,
|
||||
struct otx2_tc_flow *node, int index,
|
||||
bool error)
|
||||
{
|
||||
struct otx2_tc_flow *first, *tmp, *n;
|
||||
u32 prio = 0;
|
||||
int i = 0;
|
||||
u8 type;
|
||||
|
||||
first = list_first_entry(&flow_cfg->flow_list_tc, struct otx2_tc_flow,
|
||||
list);
|
||||
type = first->kw_type;
|
||||
|
||||
/* Check all the nodes from start to given index (including index) has
|
||||
* same type i.e, either X2 or X4
|
||||
*/
|
||||
list_for_each_entry_safe(tmp, n, &flow_cfg->flow_list_tc, list) {
|
||||
if (i > index)
|
||||
break;
|
||||
|
||||
if (type != tmp->kw_type) {
|
||||
/* List has both X2 and X4 entries so entries cannot be
|
||||
* shifted to save MCAM space.
|
||||
*/
|
||||
if (error)
|
||||
dev_err(nic->dev, "Rule %d cannot be shifted to %d\n",
|
||||
tmp->prio, prio);
|
||||
return false;
|
||||
}
|
||||
|
||||
type = tmp->kw_type;
|
||||
prio = tmp->prio;
|
||||
i++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void cn20k_tc_update_mcam_table_del_req(struct otx2_nic *nic,
|
||||
struct otx2_flow_config *flow_cfg,
|
||||
struct otx2_tc_flow *node)
|
||||
{
|
||||
struct otx2_tc_flow *first, *tmp, *n;
|
||||
int i = 0, index;
|
||||
u16 cntr_val = 0;
|
||||
u16 entry;
|
||||
|
||||
index = cn20k_tc_get_entry_index(flow_cfg, node);
|
||||
if (index < 0) {
|
||||
netdev_dbg(nic->netdev, "Could not find node\n");
|
||||
return;
|
||||
}
|
||||
|
||||
first = list_first_entry(&flow_cfg->flow_list_tc, struct otx2_tc_flow,
|
||||
list);
|
||||
entry = first->entry;
|
||||
|
||||
/* If entries cannot be shifted then delete given entry
|
||||
* and free it to AF too.
|
||||
*/
|
||||
if (!cn20k_tc_check_entry_shiftable(nic, flow_cfg, node,
|
||||
index, false)) {
|
||||
list_del(&node->list);
|
||||
entry = node->entry;
|
||||
goto free_mcam_entry;
|
||||
}
|
||||
|
||||
/* Find and delete the entry from the list and re-install
|
||||
* all the entries from beginning to the index of the
|
||||
* deleted entry to higher mcam indexes.
|
||||
*/
|
||||
list_for_each_entry_safe(tmp, n, &flow_cfg->flow_list_tc, list) {
|
||||
if (node == tmp) {
|
||||
list_del(&tmp->list);
|
||||
break;
|
||||
}
|
||||
|
||||
otx2_del_mcam_flow_entry(nic, tmp->entry, &cntr_val);
|
||||
tmp->entry = (list_next_entry(tmp, list))->entry;
|
||||
tmp->req.entry = tmp->entry;
|
||||
tmp->req.cntr_val = cntr_val;
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(tmp, n, &flow_cfg->flow_list_tc, list) {
|
||||
if (i == index)
|
||||
break;
|
||||
|
||||
otx2_add_mcam_flow_entry(nic, &tmp->req);
|
||||
i++;
|
||||
}
|
||||
|
||||
free_mcam_entry:
|
||||
if (cn20k_tc_free_mcam_entry(nic, entry))
|
||||
netdev_err(nic->netdev, "Freeing entry %d to AF failed\n",
|
||||
entry);
|
||||
}
|
||||
|
||||
int cn20k_tc_update_mcam_table_add_req(struct otx2_nic *nic,
|
||||
struct otx2_flow_config *flow_cfg,
|
||||
struct otx2_tc_flow *node)
|
||||
{
|
||||
struct otx2_tc_flow *tmp;
|
||||
u16 cntr_val = 0;
|
||||
int list_idx, i;
|
||||
int entry, prev;
|
||||
|
||||
/* Find the index of the entry(list_idx) whose priority
|
||||
* is greater than the new entry and re-install all
|
||||
* the entries from beginning to list_idx to higher
|
||||
* mcam indexes.
|
||||
*/
|
||||
list_idx = otx2_tc_add_to_flow_list(flow_cfg, node);
|
||||
entry = node->entry;
|
||||
if (!cn20k_tc_check_entry_shiftable(nic, flow_cfg, node,
|
||||
list_idx, true))
|
||||
/* Due to mix of X2 and X4, entries cannot be shifted.
|
||||
* In this case free the entry allocated for this rule.
|
||||
*/
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < list_idx; i++) {
|
||||
tmp = otx2_tc_get_entry_by_index(flow_cfg, i);
|
||||
if (!tmp)
|
||||
return -ENOMEM;
|
||||
|
||||
otx2_del_mcam_flow_entry(nic, tmp->entry, &cntr_val);
|
||||
prev = tmp->entry;
|
||||
tmp->entry = entry;
|
||||
tmp->req.entry = tmp->entry;
|
||||
tmp->req.cntr_val = cntr_val;
|
||||
otx2_add_mcam_flow_entry(nic, &tmp->req);
|
||||
entry = prev;
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
#define MAX_TC_HW_PRIORITY 125
|
||||
#define MAX_TC_VF_PRIORITY 126
|
||||
#define MAX_TC_PF_PRIORITY 127
|
||||
|
||||
static int __cn20k_tc_alloc_entry(struct otx2_nic *nic,
|
||||
struct npc_install_flow_req *flow_req,
|
||||
u16 *entry, u8 *type,
|
||||
u32 tc_priority, bool hw_priority)
|
||||
{
|
||||
struct otx2_flow_config *flow_cfg = nic->flow_cfg;
|
||||
struct npc_install_flow_req *req;
|
||||
struct npc_install_flow_rsp *rsp;
|
||||
struct otx2_tc_flow *tmp;
|
||||
int ret = 0;
|
||||
|
||||
req = otx2_mbox_alloc_msg_npc_install_flow(&nic->mbox);
|
||||
if (!req)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(&flow_req->hdr, &req->hdr, sizeof(struct mbox_msghdr));
|
||||
memcpy(req, flow_req, sizeof(struct npc_install_flow_req));
|
||||
req->alloc_entry = 1;
|
||||
|
||||
/* Allocate very least priority for first rule */
|
||||
if (hw_priority || list_empty(&flow_cfg->flow_list_tc)) {
|
||||
req->ref_prio = NPC_MCAM_LEAST_PRIO;
|
||||
} else {
|
||||
req->ref_prio = NPC_MCAM_HIGHER_PRIO;
|
||||
tmp = list_first_entry(&flow_cfg->flow_list_tc,
|
||||
struct otx2_tc_flow, list);
|
||||
req->ref_entry = tmp->entry;
|
||||
}
|
||||
|
||||
ret = otx2_sync_mbox_msg(&nic->mbox);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
rsp = (struct npc_install_flow_rsp *)otx2_mbox_get_rsp(&nic->mbox.mbox,
|
||||
0, &req->hdr);
|
||||
if (IS_ERR(rsp))
|
||||
return -EFAULT;
|
||||
|
||||
if (entry)
|
||||
*entry = rsp->entry;
|
||||
if (type)
|
||||
*type = rsp->kw_type;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cn20k_tc_alloc_entry(struct otx2_nic *nic,
|
||||
struct flow_cls_offload *tc_flow_cmd,
|
||||
struct otx2_tc_flow *new_node,
|
||||
struct npc_install_flow_req *flow_req)
|
||||
{
|
||||
bool hw_priority = false;
|
||||
u16 entry_from_af;
|
||||
u8 entry_type;
|
||||
int ret;
|
||||
|
||||
if (is_otx2_vf(nic->pcifunc))
|
||||
flow_req->hw_prio = MAX_TC_VF_PRIORITY;
|
||||
else
|
||||
flow_req->hw_prio = MAX_TC_PF_PRIORITY;
|
||||
|
||||
if (new_node->prio <= MAX_TC_HW_PRIORITY) {
|
||||
flow_req->hw_prio = new_node->prio;
|
||||
hw_priority = true;
|
||||
}
|
||||
|
||||
mutex_lock(&nic->mbox.lock);
|
||||
|
||||
ret = __cn20k_tc_alloc_entry(nic, flow_req, &entry_from_af, &entry_type,
|
||||
new_node->prio, hw_priority);
|
||||
if (ret) {
|
||||
mutex_unlock(&nic->mbox.lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
new_node->kw_type = entry_type;
|
||||
new_node->entry = entry_from_af;
|
||||
|
||||
mutex_unlock(&nic->mbox.lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cn20k_aura_aq_init(struct otx2_nic *pfvf, int aura_id,
|
||||
int pool_id, int numptrs)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,8 +10,22 @@
|
|||
|
||||
#include "otx2_common.h"
|
||||
|
||||
struct otx2_flow_config;
|
||||
struct otx2_tc_flow;
|
||||
|
||||
void cn20k_init(struct otx2_nic *pfvf);
|
||||
int cn20k_register_pfvf_mbox_intr(struct otx2_nic *pf, int numvfs);
|
||||
void cn20k_disable_pfvf_mbox_intr(struct otx2_nic *pf, int numvfs);
|
||||
void cn20k_enable_pfvf_mbox_intr(struct otx2_nic *pf, int numvfs);
|
||||
void cn20k_tc_update_mcam_table_del_req(struct otx2_nic *nic,
|
||||
struct otx2_flow_config *flow_cfg,
|
||||
struct otx2_tc_flow *node);
|
||||
int cn20k_tc_update_mcam_table_add_req(struct otx2_nic *nic,
|
||||
struct otx2_flow_config *flow_cfg,
|
||||
struct otx2_tc_flow *node);
|
||||
int cn20k_tc_alloc_entry(struct otx2_nic *nic,
|
||||
struct flow_cls_offload *tc_flow_cmd,
|
||||
struct otx2_tc_flow *new_node,
|
||||
struct npc_install_flow_req *dummy);
|
||||
int cn20k_tc_free_mcam_entry(struct otx2_nic *nic, u16 entry);
|
||||
#endif /* CN20K_H */
|
||||
|
|
|
|||
|
|
@ -366,6 +366,31 @@ struct otx2_flow_config {
|
|||
u16 ntuple_cnt;
|
||||
};
|
||||
|
||||
struct otx2_tc_flow_stats {
|
||||
u64 bytes;
|
||||
u64 pkts;
|
||||
u64 used;
|
||||
};
|
||||
|
||||
struct otx2_tc_flow {
|
||||
struct list_head list;
|
||||
unsigned long cookie;
|
||||
struct rcu_head rcu;
|
||||
struct otx2_tc_flow_stats stats;
|
||||
spinlock_t lock; /* lock for stats */
|
||||
u16 rq;
|
||||
u16 entry;
|
||||
u16 leaf_profile;
|
||||
bool is_act_police;
|
||||
u32 prio;
|
||||
struct npc_install_flow_req req;
|
||||
u64 rate;
|
||||
u32 burst;
|
||||
u32 mcast_grp_idx;
|
||||
bool is_pps;
|
||||
u8 kw_type; /* X2/X4 */
|
||||
};
|
||||
|
||||
struct dev_hw_ops {
|
||||
int (*sq_aq_init)(void *dev, u16 qidx, u8 chan_offset,
|
||||
u16 sqb_aura);
|
||||
|
|
@ -1223,4 +1248,14 @@ void otx2_dma_unmap_skb_frags(struct otx2_nic *pfvf, struct sg_list *sg);
|
|||
int otx2_read_free_sqe(struct otx2_nic *pfvf, u16 qidx);
|
||||
void otx2_queue_vf_work(struct mbox *mw, struct workqueue_struct *mbox_wq,
|
||||
int first, int mdevs, u64 intr);
|
||||
int otx2_del_mcam_flow_entry(struct otx2_nic *nic, u16 entry,
|
||||
u16 *cntr_val);
|
||||
int otx2_add_mcam_flow_entry(struct otx2_nic *nic,
|
||||
struct npc_install_flow_req *req);
|
||||
int otx2_tc_add_to_flow_list(struct otx2_flow_config *flow_cfg,
|
||||
struct otx2_tc_flow *node);
|
||||
|
||||
struct otx2_tc_flow *
|
||||
otx2_tc_get_entry_by_index(struct otx2_flow_config *flow_cfg,
|
||||
int index);
|
||||
#endif /* OTX2_COMMON_H */
|
||||
|
|
|
|||
|
|
@ -37,6 +37,98 @@ static void otx2_clear_ntuple_flow_info(struct otx2_nic *pfvf, struct otx2_flow_
|
|||
flow_cfg->max_flows = 0;
|
||||
}
|
||||
|
||||
static int otx2_mcam_pfl_info_get(struct otx2_nic *pfvf, bool *is_x2,
|
||||
u16 *x4_slots)
|
||||
{
|
||||
struct npc_get_pfl_info_rsp *rsp;
|
||||
struct msg_req *req;
|
||||
static struct {
|
||||
bool is_set;
|
||||
bool is_x2;
|
||||
u16 x4_slots;
|
||||
} pfl_info;
|
||||
|
||||
/* Avoid sending mboxes for constant information
|
||||
* like x4_slots
|
||||
*/
|
||||
mutex_lock(&pfvf->mbox.lock);
|
||||
if (pfl_info.is_set) {
|
||||
*is_x2 = pfl_info.is_x2;
|
||||
*x4_slots = pfl_info.x4_slots;
|
||||
mutex_unlock(&pfvf->mbox.lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
req = otx2_mbox_alloc_msg_npc_get_pfl_info(&pfvf->mbox);
|
||||
if (!req) {
|
||||
mutex_unlock(&pfvf->mbox.lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Send message to AF */
|
||||
if (otx2_sync_mbox_msg(&pfvf->mbox)) {
|
||||
mutex_unlock(&pfvf->mbox.lock);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
rsp = (struct npc_get_pfl_info_rsp *)otx2_mbox_get_rsp
|
||||
(&pfvf->mbox.mbox, 0, &req->hdr);
|
||||
|
||||
if (IS_ERR(rsp)) {
|
||||
mutex_unlock(&pfvf->mbox.lock);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
*is_x2 = (rsp->kw_type == NPC_MCAM_KEY_X2);
|
||||
if (*is_x2)
|
||||
*x4_slots = 0;
|
||||
else
|
||||
*x4_slots = rsp->x4_slots;
|
||||
|
||||
pfl_info.is_x2 = *is_x2;
|
||||
pfl_info.x4_slots = *x4_slots;
|
||||
pfl_info.is_set = true;
|
||||
|
||||
mutex_unlock(&pfvf->mbox.lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int otx2_get_dft_rl_idx(struct otx2_nic *pfvf, u16 *mcam_idx)
|
||||
{
|
||||
struct npc_get_dft_rl_idxs_rsp *rsp;
|
||||
struct msg_req *req;
|
||||
|
||||
mutex_lock(&pfvf->mbox.lock);
|
||||
|
||||
req = otx2_mbox_alloc_msg_npc_get_dft_rl_idxs(&pfvf->mbox);
|
||||
if (!req) {
|
||||
mutex_unlock(&pfvf->mbox.lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Send message to AF */
|
||||
if (otx2_sync_mbox_msg(&pfvf->mbox)) {
|
||||
mutex_unlock(&pfvf->mbox.lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rsp = (struct npc_get_dft_rl_idxs_rsp *)otx2_mbox_get_rsp
|
||||
(&pfvf->mbox.mbox, 0, &req->hdr);
|
||||
|
||||
if (IS_ERR(rsp)) {
|
||||
mutex_unlock(&pfvf->mbox.lock);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (is_otx2_lbkvf(pfvf->pdev))
|
||||
*mcam_idx = rsp->promisc;
|
||||
else
|
||||
*mcam_idx = rsp->ucast;
|
||||
|
||||
mutex_unlock(&pfvf->mbox.lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int otx2_free_ntuple_mcam_entries(struct otx2_nic *pfvf)
|
||||
{
|
||||
struct otx2_flow_config *flow_cfg = pfvf->flow_cfg;
|
||||
|
|
@ -69,7 +161,10 @@ int otx2_alloc_mcam_entries(struct otx2_nic *pfvf, u16 count)
|
|||
struct otx2_flow_config *flow_cfg = pfvf->flow_cfg;
|
||||
struct npc_mcam_alloc_entry_req *req;
|
||||
struct npc_mcam_alloc_entry_rsp *rsp;
|
||||
int ent, allocated = 0;
|
||||
u16 dft_idx = 0, x4_slots = 0;
|
||||
int ent, allocated = 0, ref;
|
||||
bool is_x2 = false;
|
||||
int rc;
|
||||
|
||||
/* Free current ones and allocate new ones with requested count */
|
||||
otx2_free_ntuple_mcam_entries(pfvf);
|
||||
|
|
@ -86,6 +181,22 @@ int otx2_alloc_mcam_entries(struct otx2_nic *pfvf, u16 count)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (is_cn20k(pfvf->pdev)) {
|
||||
rc = otx2_mcam_pfl_info_get(pfvf, &is_x2, &x4_slots);
|
||||
if (rc) {
|
||||
netdev_err(pfvf->netdev, "Error to retrieve profile info\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = otx2_get_dft_rl_idx(pfvf, &dft_idx);
|
||||
if (rc) {
|
||||
netdev_err(pfvf->netdev,
|
||||
"Error to retrieve ucast mcam idx for pcifunc %#x\n",
|
||||
pfvf->pcifunc);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_lock(&pfvf->mbox.lock);
|
||||
|
||||
/* In a single request a max of NPC_MAX_NONCONTIG_ENTRIES MCAM entries
|
||||
|
|
@ -96,18 +207,31 @@ int otx2_alloc_mcam_entries(struct otx2_nic *pfvf, u16 count)
|
|||
if (!req)
|
||||
goto exit;
|
||||
|
||||
req->kw_type = is_x2 ? NPC_MCAM_KEY_X2 : NPC_MCAM_KEY_X4;
|
||||
req->contig = false;
|
||||
req->count = (count - allocated) > NPC_MAX_NONCONTIG_ENTRIES ?
|
||||
NPC_MAX_NONCONTIG_ENTRIES : count - allocated;
|
||||
|
||||
ref = 0;
|
||||
|
||||
if (is_cn20k(pfvf->pdev)) {
|
||||
req->ref_prio = NPC_MCAM_HIGHER_PRIO;
|
||||
ref = dft_idx;
|
||||
}
|
||||
|
||||
/* Allocate higher priority entries for PFs, so that VF's entries
|
||||
* will be on top of PF.
|
||||
*/
|
||||
if (!is_otx2_vf(pfvf->pcifunc)) {
|
||||
req->priority = NPC_MCAM_HIGHER_PRIO;
|
||||
req->ref_entry = flow_cfg->def_ent[0];
|
||||
req->ref_prio = NPC_MCAM_HIGHER_PRIO;
|
||||
ref = flow_cfg->def_ent[0];
|
||||
}
|
||||
|
||||
if (is_cn20k(pfvf->pdev))
|
||||
ref = is_x2 ? ref : ref & (x4_slots - 1);
|
||||
|
||||
req->ref_entry = ref;
|
||||
|
||||
/* Send message to AF */
|
||||
if (otx2_sync_mbox_msg(&pfvf->mbox))
|
||||
goto exit;
|
||||
|
|
@ -163,8 +287,24 @@ int otx2_mcam_entry_init(struct otx2_nic *pfvf)
|
|||
struct npc_get_field_status_rsp *frsp;
|
||||
struct npc_mcam_alloc_entry_req *req;
|
||||
struct npc_mcam_alloc_entry_rsp *rsp;
|
||||
int vf_vlan_max_flows;
|
||||
int ent, count;
|
||||
int vf_vlan_max_flows, count;
|
||||
int rc, ref, prio, ent;
|
||||
u16 dft_idx;
|
||||
|
||||
ref = 0;
|
||||
prio = 0;
|
||||
if (is_cn20k(pfvf->pdev)) {
|
||||
rc = otx2_get_dft_rl_idx(pfvf, &dft_idx);
|
||||
if (rc) {
|
||||
netdev_err(pfvf->netdev,
|
||||
"Error to retrieve ucast mcam idx for pcifunc %#x\n",
|
||||
pfvf->pcifunc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
ref = dft_idx;
|
||||
prio = NPC_MCAM_HIGHER_PRIO;
|
||||
}
|
||||
|
||||
vf_vlan_max_flows = pfvf->total_vfs * OTX2_PER_VF_VLAN_FLOWS;
|
||||
count = flow_cfg->ucast_flt_cnt +
|
||||
|
|
@ -183,8 +323,11 @@ int otx2_mcam_entry_init(struct otx2_nic *pfvf)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
req->kw_type = NPC_MCAM_KEY_X2;
|
||||
req->contig = false;
|
||||
req->count = count;
|
||||
req->ref_prio = prio;
|
||||
req->ref_entry = ref;
|
||||
|
||||
/* Send message to AF */
|
||||
if (otx2_sync_mbox_msg(&pfvf->mbox)) {
|
||||
|
|
@ -819,7 +962,7 @@ static int otx2_prepare_ipv6_flow(struct ethtool_rx_flow_spec *fsp,
|
|||
}
|
||||
|
||||
static int otx2_prepare_flow_request(struct ethtool_rx_flow_spec *fsp,
|
||||
struct npc_install_flow_req *req)
|
||||
struct npc_install_flow_req *req)
|
||||
{
|
||||
struct ethhdr *eth_mask = &fsp->m_u.ether_spec;
|
||||
struct ethhdr *eth_hdr = &fsp->h_u.ether_spec;
|
||||
|
|
@ -945,6 +1088,58 @@ static int otx2_prepare_flow_request(struct ethtool_rx_flow_spec *fsp,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int otx2_get_kw_type(struct otx2_nic *pfvf,
|
||||
struct npc_install_flow_req *fl_req,
|
||||
u8 *kw_type)
|
||||
{
|
||||
struct npc_get_num_kws_req *req;
|
||||
struct npc_get_num_kws_rsp *rsp;
|
||||
u8 *src, *dst;
|
||||
int off, err;
|
||||
int kw_bits;
|
||||
|
||||
off = offsetof(struct npc_install_flow_req, packet);
|
||||
|
||||
mutex_lock(&pfvf->mbox.lock);
|
||||
|
||||
req = otx2_mbox_alloc_msg_npc_get_num_kws(&pfvf->mbox);
|
||||
if (!req) {
|
||||
mutex_unlock(&pfvf->mbox.lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dst = (u8 *)&req->fl + off;
|
||||
src = (u8 *)fl_req + off;
|
||||
|
||||
memcpy(dst, src, sizeof(struct npc_install_flow_req) - off);
|
||||
|
||||
err = otx2_sync_mbox_msg(&pfvf->mbox);
|
||||
if (err) {
|
||||
mutex_unlock(&pfvf->mbox.lock);
|
||||
netdev_err(pfvf->netdev,
|
||||
"Error to get default number of keywords\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
rsp = (struct npc_get_num_kws_rsp *)otx2_mbox_get_rsp
|
||||
(&pfvf->mbox.mbox, 0, &req->hdr);
|
||||
if (IS_ERR(rsp)) {
|
||||
mutex_unlock(&pfvf->mbox.lock);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
kw_bits = rsp->kws * 64;
|
||||
|
||||
if (kw_bits <= 256)
|
||||
*kw_type = NPC_MCAM_KEY_X2;
|
||||
else
|
||||
*kw_type = NPC_MCAM_KEY_X4;
|
||||
|
||||
mutex_unlock(&pfvf->mbox.lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int otx2_is_flow_rule_dmacfilter(struct otx2_nic *pfvf,
|
||||
struct ethtool_rx_flow_spec *fsp)
|
||||
{
|
||||
|
|
@ -973,12 +1168,41 @@ static int otx2_is_flow_rule_dmacfilter(struct otx2_nic *pfvf,
|
|||
|
||||
static int otx2_add_flow_msg(struct otx2_nic *pfvf, struct otx2_flow *flow)
|
||||
{
|
||||
struct otx2_flow_config *flow_cfg = pfvf->flow_cfg;
|
||||
struct npc_install_flow_req *req, treq = { 0 };
|
||||
u64 ring_cookie = flow->flow_spec.ring_cookie;
|
||||
#ifdef CONFIG_DCB
|
||||
int vlan_prio, qidx, pfc_rule = 0;
|
||||
#endif
|
||||
struct npc_install_flow_req *req;
|
||||
int err, vf = 0;
|
||||
int err, vf = 0, off, sz;
|
||||
bool modify = false;
|
||||
u8 kw_type = 0;
|
||||
u8 *src, *dst;
|
||||
u16 x4_slots;
|
||||
bool is_x2;
|
||||
|
||||
if (is_cn20k(pfvf->pdev)) {
|
||||
err = otx2_mcam_pfl_info_get(pfvf, &is_x2, &x4_slots);
|
||||
if (err) {
|
||||
netdev_err(pfvf->netdev,
|
||||
"Error to retrieve NPC profile info, pcifunc=%#x\n",
|
||||
pfvf->pcifunc);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (!is_x2) {
|
||||
err = otx2_prepare_flow_request(&flow->flow_spec,
|
||||
&treq);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = otx2_get_kw_type(pfvf, &treq, &kw_type);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
modify = true;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_lock(&pfvf->mbox.lock);
|
||||
req = otx2_mbox_alloc_msg_npc_install_flow(&pfvf->mbox);
|
||||
|
|
@ -987,14 +1211,29 @@ static int otx2_add_flow_msg(struct otx2_nic *pfvf, struct otx2_flow *flow)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
err = otx2_prepare_flow_request(&flow->flow_spec, req);
|
||||
if (err) {
|
||||
/* free the allocated msg above */
|
||||
otx2_mbox_reset(&pfvf->mbox.mbox, 0);
|
||||
mutex_unlock(&pfvf->mbox.lock);
|
||||
return err;
|
||||
if (modify) {
|
||||
off = offsetof(struct npc_install_flow_req, packet);
|
||||
sz = sizeof(struct npc_install_flow_req) - off;
|
||||
dst = (u8 *)req + off;
|
||||
src = (u8 *)&treq + off;
|
||||
|
||||
memcpy(dst, src, sz);
|
||||
req->req_kw_type = kw_type;
|
||||
} else {
|
||||
err = otx2_prepare_flow_request(&flow->flow_spec, req);
|
||||
if (err) {
|
||||
/* free the allocated msg above */
|
||||
otx2_mbox_reset(&pfvf->mbox.mbox, 0);
|
||||
mutex_unlock(&pfvf->mbox.lock);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
netdev_dbg(pfvf->netdev,
|
||||
"flow entry (%u) installed at loc:%u kw_type=%u\n",
|
||||
flow_cfg->flow_ent[flow->location],
|
||||
flow->location, kw_type);
|
||||
|
||||
req->entry = flow->entry;
|
||||
req->intf = NIX_INTF_RX;
|
||||
req->set_cntr = 1;
|
||||
|
|
|
|||
|
|
@ -31,30 +31,6 @@
|
|||
|
||||
#define MCAST_INVALID_GRP (-1U)
|
||||
|
||||
struct otx2_tc_flow_stats {
|
||||
u64 bytes;
|
||||
u64 pkts;
|
||||
u64 used;
|
||||
};
|
||||
|
||||
struct otx2_tc_flow {
|
||||
struct list_head list;
|
||||
unsigned long cookie;
|
||||
struct rcu_head rcu;
|
||||
struct otx2_tc_flow_stats stats;
|
||||
spinlock_t lock; /* lock for stats */
|
||||
u16 rq;
|
||||
u16 entry;
|
||||
u16 leaf_profile;
|
||||
bool is_act_police;
|
||||
u32 prio;
|
||||
struct npc_install_flow_req req;
|
||||
u32 mcast_grp_idx;
|
||||
u64 rate;
|
||||
u32 burst;
|
||||
bool is_pps;
|
||||
};
|
||||
|
||||
static void otx2_get_egress_burst_cfg(struct otx2_nic *nic, u32 burst,
|
||||
u32 *burst_exp, u32 *burst_mantissa)
|
||||
{
|
||||
|
|
@ -971,8 +947,9 @@ static void otx2_destroy_tc_flow_list(struct otx2_nic *pfvf)
|
|||
}
|
||||
}
|
||||
|
||||
static struct otx2_tc_flow *otx2_tc_get_entry_by_cookie(struct otx2_flow_config *flow_cfg,
|
||||
unsigned long cookie)
|
||||
static struct otx2_tc_flow *
|
||||
otx2_tc_get_entry_by_cookie(struct otx2_flow_config *flow_cfg,
|
||||
unsigned long cookie)
|
||||
{
|
||||
struct otx2_tc_flow *tmp;
|
||||
|
||||
|
|
@ -984,8 +961,8 @@ static struct otx2_tc_flow *otx2_tc_get_entry_by_cookie(struct otx2_flow_config
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static struct otx2_tc_flow *otx2_tc_get_entry_by_index(struct otx2_flow_config *flow_cfg,
|
||||
int index)
|
||||
struct otx2_tc_flow *
|
||||
otx2_tc_get_entry_by_index(struct otx2_flow_config *flow_cfg, int index)
|
||||
{
|
||||
struct otx2_tc_flow *tmp;
|
||||
int i = 0;
|
||||
|
|
@ -1014,8 +991,8 @@ static void otx2_tc_del_from_flow_list(struct otx2_flow_config *flow_cfg,
|
|||
}
|
||||
}
|
||||
|
||||
static int otx2_tc_add_to_flow_list(struct otx2_flow_config *flow_cfg,
|
||||
struct otx2_tc_flow *node)
|
||||
int otx2_tc_add_to_flow_list(struct otx2_flow_config *flow_cfg,
|
||||
struct otx2_tc_flow *node)
|
||||
{
|
||||
struct list_head *pos, *n;
|
||||
struct otx2_tc_flow *tmp;
|
||||
|
|
@ -1038,7 +1015,8 @@ static int otx2_tc_add_to_flow_list(struct otx2_flow_config *flow_cfg,
|
|||
return index;
|
||||
}
|
||||
|
||||
static int otx2_add_mcam_flow_entry(struct otx2_nic *nic, struct npc_install_flow_req *req)
|
||||
int otx2_add_mcam_flow_entry(struct otx2_nic *nic,
|
||||
struct npc_install_flow_req *req)
|
||||
{
|
||||
struct npc_install_flow_req *tmp_req;
|
||||
int err;
|
||||
|
|
@ -1064,7 +1042,7 @@ static int otx2_add_mcam_flow_entry(struct otx2_nic *nic, struct npc_install_flo
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int otx2_del_mcam_flow_entry(struct otx2_nic *nic, u16 entry, u16 *cntr_val)
|
||||
int otx2_del_mcam_flow_entry(struct otx2_nic *nic, u16 entry, u16 *cntr_val)
|
||||
{
|
||||
struct npc_delete_flow_rsp *rsp;
|
||||
struct npc_delete_flow_req *req;
|
||||
|
|
@ -1114,6 +1092,11 @@ static int otx2_tc_update_mcam_table_del_req(struct otx2_nic *nic,
|
|||
int i = 0, index = 0;
|
||||
u16 cntr_val = 0;
|
||||
|
||||
if (is_cn20k(nic->pdev)) {
|
||||
cn20k_tc_update_mcam_table_del_req(nic, flow_cfg, node);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Find and delete the entry from the list and re-install
|
||||
* all the entries from beginning to the index of the
|
||||
* deleted entry to higher mcam indexes.
|
||||
|
|
@ -1153,6 +1136,9 @@ static int otx2_tc_update_mcam_table_add_req(struct otx2_nic *nic,
|
|||
int list_idx, i;
|
||||
u16 cntr_val = 0;
|
||||
|
||||
if (is_cn20k(nic->pdev))
|
||||
return cn20k_tc_update_mcam_table_add_req(nic, flow_cfg, node);
|
||||
|
||||
/* Find the index of the entry(list_idx) whose priority
|
||||
* is greater than the new entry and re-install all
|
||||
* the entries from beginning to list_idx to higher
|
||||
|
|
@ -1172,7 +1158,7 @@ static int otx2_tc_update_mcam_table_add_req(struct otx2_nic *nic,
|
|||
mcam_idx++;
|
||||
}
|
||||
|
||||
return mcam_idx;
|
||||
return flow_cfg->flow_ent[mcam_idx];
|
||||
}
|
||||
|
||||
static int otx2_tc_update_mcam_table(struct otx2_nic *nic,
|
||||
|
|
@ -1238,7 +1224,6 @@ static int otx2_tc_del_flow(struct otx2_nic *nic,
|
|||
mutex_unlock(&nic->mbox.lock);
|
||||
}
|
||||
|
||||
|
||||
free_mcam_flow:
|
||||
otx2_del_mcam_flow_entry(nic, flow_node->entry, NULL);
|
||||
otx2_tc_update_mcam_table(nic, flow_cfg, flow_node, false);
|
||||
|
|
@ -1254,7 +1239,7 @@ static int otx2_tc_add_flow(struct otx2_nic *nic,
|
|||
struct otx2_flow_config *flow_cfg = nic->flow_cfg;
|
||||
struct otx2_tc_flow *new_node, *old_node;
|
||||
struct npc_install_flow_req *req, dummy;
|
||||
int rc, err, mcam_idx;
|
||||
int rc, err, entry;
|
||||
|
||||
if (!(nic->flags & OTX2_FLAG_TC_FLOWER_SUPPORT))
|
||||
return -ENOMEM;
|
||||
|
|
@ -1264,7 +1249,7 @@ static int otx2_tc_add_flow(struct otx2_nic *nic,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (flow_cfg->nr_flows == flow_cfg->max_flows) {
|
||||
if (!is_cn20k(nic->pdev) && flow_cfg->nr_flows == flow_cfg->max_flows) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Free MCAM entry not available to add the flow");
|
||||
return -ENOMEM;
|
||||
|
|
@ -1292,7 +1277,23 @@ static int otx2_tc_add_flow(struct otx2_nic *nic,
|
|||
if (old_node)
|
||||
otx2_tc_del_flow(nic, tc_flow_cmd);
|
||||
|
||||
mcam_idx = otx2_tc_update_mcam_table(nic, flow_cfg, new_node, true);
|
||||
if (is_cn20k(nic->pdev)) {
|
||||
rc = cn20k_tc_alloc_entry(nic, tc_flow_cmd, new_node, &dummy);
|
||||
if (rc) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"MCAM rule allocation failed");
|
||||
kfree_rcu(new_node, rcu);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
entry = otx2_tc_update_mcam_table(nic, flow_cfg, new_node, true);
|
||||
if (entry < 0) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Adding rule failed");
|
||||
rc = entry;
|
||||
goto free_leaf;
|
||||
}
|
||||
|
||||
mutex_lock(&nic->mbox.lock);
|
||||
req = otx2_mbox_alloc_msg_npc_install_flow(&nic->mbox);
|
||||
if (!req) {
|
||||
|
|
@ -1304,7 +1305,7 @@ static int otx2_tc_add_flow(struct otx2_nic *nic,
|
|||
memcpy(&dummy.hdr, &req->hdr, sizeof(struct mbox_msghdr));
|
||||
memcpy(req, &dummy, sizeof(struct npc_install_flow_req));
|
||||
req->channel = nic->hw.rx_chan_base;
|
||||
req->entry = flow_cfg->flow_ent[mcam_idx];
|
||||
req->entry = (u16)entry;
|
||||
req->intf = NIX_INTF_RX;
|
||||
req->vf = nic->pcifunc;
|
||||
req->set_cntr = 1;
|
||||
|
|
@ -1325,6 +1326,8 @@ static int otx2_tc_add_flow(struct otx2_nic *nic,
|
|||
return 0;
|
||||
|
||||
free_leaf:
|
||||
if (is_cn20k(nic->pdev))
|
||||
cn20k_tc_free_mcam_entry(nic, new_node->entry);
|
||||
otx2_tc_del_from_flow_list(flow_cfg, new_node);
|
||||
if (new_node->is_act_police) {
|
||||
mutex_lock(&nic->mbox.lock);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user