Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

+7442 -472
+1 -1
drivers/net/ethernet/marvell/octeontx2/af/Makefile
··· 13 13 rvu_cpt.o rvu_devlink.o rpm.o rvu_cn10k.o rvu_switch.o \ 14 14 rvu_sdp.o rvu_npc_hash.o mcs.o mcs_rvu_if.o mcs_cnf10kb.o \ 15 15 rvu_rep.o cn20k/mbox_init.o cn20k/nix.o cn20k/debugfs.o \ 16 - cn20k/npa.o 16 + cn20k/npa.o cn20k/npc.o
+273
drivers/net/ethernet/marvell/octeontx2/af/cn20k/debugfs.c
··· 11 11 #include <linux/pci.h> 12 12 13 13 #include "struct.h" 14 + #include "rvu.h" 14 15 #include "debugfs.h" 16 + #include "cn20k/npc.h" 17 + 18 + static int npc_mcam_layout_show(struct seq_file *s, void *unused) 19 + { 20 + int i, j, sbd, idx0, idx1, vidx0, vidx1; 21 + struct npc_priv_t *npc_priv; 22 + char buf0[32], buf1[32]; 23 + struct npc_subbank *sb; 24 + unsigned int bw0, bw1; 25 + bool v0, v1; 26 + int pf1, pf2; 27 + bool e0, e1; 28 + void *map; 29 + 30 + npc_priv = s->private; 31 + 32 + sbd = npc_priv->subbank_depth; 33 + 34 + for (i = npc_priv->num_subbanks - 1; i >= 0; i--) { 35 + sb = &npc_priv->sb[i]; 36 + mutex_lock(&sb->lock); 37 + 38 + if (sb->flags & NPC_SUBBANK_FLAG_FREE) 39 + goto next; 40 + 41 + bw0 = bitmap_weight(sb->b0map, npc_priv->subbank_depth); 42 + if (sb->key_type == NPC_MCAM_KEY_X4) { 43 + seq_printf(s, "\n\nsubbank:%u, x4, free=%u, used=%u\n", 44 + sb->idx, sb->free_cnt, bw0); 45 + 46 + for (j = sbd - 1; j >= 0; j--) { 47 + if (!test_bit(j, sb->b0map)) 48 + continue; 49 + 50 + idx0 = sb->b0b + j; 51 + map = xa_load(&npc_priv->xa_idx2pf_map, idx0); 52 + pf1 = xa_to_value(map); 53 + 54 + map = xa_load(&npc_priv->xa_idx2vidx_map, idx0); 55 + if (map) { 56 + vidx0 = xa_to_value(map); 57 + snprintf(buf0, sizeof(buf0), 58 + "v:%u", vidx0); 59 + } 60 + 61 + seq_printf(s, "\t%u(%#x) %s\n", idx0, pf1, 62 + map ? buf0 : " "); 63 + } 64 + goto next; 65 + } 66 + 67 + bw1 = bitmap_weight(sb->b1map, npc_priv->subbank_depth); 68 + seq_printf(s, "\n\nsubbank:%u, x2, free=%u, used=%u\n", 69 + sb->idx, sb->free_cnt, bw0 + bw1); 70 + seq_printf(s, "bank1(%u)\t\tbank0(%u)\n", bw1, bw0); 71 + 72 + for (j = sbd - 1; j >= 0; j--) { 73 + e0 = test_bit(j, sb->b0map); 74 + e1 = test_bit(j, sb->b1map); 75 + 76 + if (!e1 && !e0) 77 + continue; 78 + 79 + if (e1 && e0) { 80 + idx0 = sb->b0b + j; 81 + map = xa_load(&npc_priv->xa_idx2pf_map, idx0); 82 + pf1 = xa_to_value(map); 83 + 84 + map = xa_load(&npc_priv->xa_idx2vidx_map, idx0); 85 + v0 = !!map; 86 + if (v0) { 87 + vidx0 = xa_to_value(map); 88 + snprintf(buf0, sizeof(buf0), "v:%05u", 89 + vidx0); 90 + } 91 + 92 + idx1 = sb->b1b + j; 93 + map = xa_load(&npc_priv->xa_idx2pf_map, idx1); 94 + pf2 = xa_to_value(map); 95 + 96 + map = xa_load(&npc_priv->xa_idx2vidx_map, idx1); 97 + v1 = !!map; 98 + if (v1) { 99 + vidx1 = xa_to_value(map); 100 + snprintf(buf1, sizeof(buf1), "v:%05u", 101 + vidx1); 102 + } 103 + 104 + seq_printf(s, "%05u(%#x) %s\t\t%05u(%#x) %s\n", 105 + idx1, pf2, v1 ? buf1 : " ", 106 + idx0, pf1, v0 ? buf0 : " "); 107 + 108 + continue; 109 + } 110 + 111 + if (e0) { 112 + idx0 = sb->b0b + j; 113 + map = xa_load(&npc_priv->xa_idx2pf_map, idx0); 114 + pf1 = xa_to_value(map); 115 + 116 + map = xa_load(&npc_priv->xa_idx2vidx_map, idx0); 117 + if (map) { 118 + vidx0 = xa_to_value(map); 119 + snprintf(buf0, sizeof(buf0), "v:%05u", 120 + vidx0); 121 + } 122 + 123 + seq_printf(s, "\t\t \t\t%05u(%#x) %s\n", idx0, 124 + pf1, map ? buf0 : " "); 125 + continue; 126 + } 127 + 128 + idx1 = sb->b1b + j; 129 + map = xa_load(&npc_priv->xa_idx2pf_map, idx1); 130 + pf1 = xa_to_value(map); 131 + map = xa_load(&npc_priv->xa_idx2vidx_map, idx1); 132 + if (map) { 133 + vidx1 = xa_to_value(map); 134 + snprintf(buf1, sizeof(buf1), "v:%05u", vidx1); 135 + } 136 + 137 + seq_printf(s, "%05u(%#x) %s\n", idx1, pf1, 138 + map ? buf1 : " "); 139 + } 140 + next: 141 + mutex_unlock(&sb->lock); 142 + } 143 + return 0; 144 + } 145 + 146 + DEFINE_SHOW_ATTRIBUTE(npc_mcam_layout); 147 + 148 + static int npc_mcam_default_show(struct seq_file *s, void *unused) 149 + { 150 + struct npc_priv_t *npc_priv; 151 + unsigned long index; 152 + u16 ptr[4], pcifunc; 153 + struct rvu *rvu; 154 + int rc, i; 155 + void *map; 156 + 157 + npc_priv = npc_priv_get(); 158 + rvu = s->private; 159 + 160 + seq_puts(s, "\npcifunc\tBcast\tmcast\tpromisc\tucast\n"); 161 + 162 + xa_for_each(&npc_priv->xa_pf_map, index, map) { 163 + pcifunc = index; 164 + 165 + for (i = 0; i < ARRAY_SIZE(ptr); i++) 166 + ptr[i] = USHRT_MAX; 167 + 168 + rc = npc_cn20k_dft_rules_idx_get(rvu, pcifunc, &ptr[0], 169 + &ptr[1], &ptr[2], &ptr[3]); 170 + if (rc) 171 + continue; 172 + 173 + seq_printf(s, "%#x\t", pcifunc); 174 + for (i = 0; i < ARRAY_SIZE(ptr); i++) { 175 + if (ptr[i] != USHRT_MAX) 176 + seq_printf(s, "%u\t", ptr[i]); 177 + else 178 + seq_puts(s, "\t"); 179 + } 180 + seq_puts(s, "\n"); 181 + } 182 + 183 + return 0; 184 + } 185 + DEFINE_SHOW_ATTRIBUTE(npc_mcam_default); 186 + 187 + static int npc_vidx2idx_map_show(struct seq_file *s, void *unused) 188 + { 189 + struct npc_priv_t *npc_priv; 190 + unsigned long index, start; 191 + struct xarray *xa; 192 + void *map; 193 + 194 + npc_priv = s->private; 195 + start = npc_priv->bank_depth * 2; 196 + xa = &npc_priv->xa_vidx2idx_map; 197 + 198 + seq_puts(s, "\nvidx\tmcam_idx\n"); 199 + 200 + xa_for_each_start(xa, index, map, start) 201 + seq_printf(s, "%lu\t%lu\n", index, xa_to_value(map)); 202 + return 0; 203 + } 204 + DEFINE_SHOW_ATTRIBUTE(npc_vidx2idx_map); 205 + 206 + static int npc_idx2vidx_map_show(struct seq_file *s, void *unused) 207 + { 208 + struct npc_priv_t *npc_priv; 209 + unsigned long index; 210 + struct xarray *xa; 211 + void *map; 212 + 213 + npc_priv = s->private; 214 + xa = &npc_priv->xa_idx2vidx_map; 215 + 216 + seq_puts(s, "\nmidx\tvidx\n"); 217 + 218 + xa_for_each(xa, index, map) 219 + seq_printf(s, "%lu\t%lu\n", index, xa_to_value(map)); 220 + return 0; 221 + } 222 + DEFINE_SHOW_ATTRIBUTE(npc_idx2vidx_map); 223 + 224 + static int npc_defrag_show(struct seq_file *s, void *unused) 225 + { 226 + struct npc_defrag_show_node *node; 227 + struct npc_priv_t *npc_priv; 228 + u16 sbd, bdm; 229 + 230 + npc_priv = s->private; 231 + bdm = npc_priv->bank_depth - 1; 232 + sbd = npc_priv->subbank_depth; 233 + 234 + seq_puts(s, "\nold(sb) -> new(sb)\t\tvidx\n"); 235 + 236 + mutex_lock(&npc_priv->lock); 237 + list_for_each_entry(node, &npc_priv->defrag_lh, list) 238 + seq_printf(s, "%u(%u)\t%u(%u)\t%u\n", node->old_midx, 239 + (node->old_midx & bdm) / sbd, 240 + node->new_midx, 241 + (node->new_midx & bdm) / sbd, 242 + node->vidx); 243 + mutex_unlock(&npc_priv->lock); 244 + return 0; 245 + } 246 + 247 + DEFINE_SHOW_ATTRIBUTE(npc_defrag); 248 + 249 + int npc_cn20k_debugfs_init(struct rvu *rvu) 250 + { 251 + struct npc_priv_t *npc_priv = npc_priv_get(); 252 + struct dentry *npc_dentry; 253 + 254 + npc_dentry = debugfs_create_file("mcam_layout", 0444, rvu->rvu_dbg.npc, 255 + npc_priv, &npc_mcam_layout_fops); 256 + 257 + if (!npc_dentry) 258 + return -EFAULT; 259 + 260 + npc_dentry = debugfs_create_file("mcam_default", 0444, rvu->rvu_dbg.npc, 261 + rvu, &npc_mcam_default_fops); 262 + 263 + if (!npc_dentry) 264 + return -EFAULT; 265 + 266 + npc_dentry = debugfs_create_file("vidx2idx", 0444, rvu->rvu_dbg.npc, 267 + npc_priv, &npc_vidx2idx_map_fops); 268 + if (!npc_dentry) 269 + return -EFAULT; 270 + 271 + npc_dentry = debugfs_create_file("idx2vidx", 0444, rvu->rvu_dbg.npc, 272 + npc_priv, &npc_idx2vidx_map_fops); 273 + if (!npc_dentry) 274 + return -EFAULT; 275 + 276 + npc_dentry = debugfs_create_file("defrag", 0444, rvu->rvu_dbg.npc, 277 + npc_priv, &npc_defrag_fops); 278 + if (!npc_dentry) 279 + return -EFAULT; 280 + 281 + return 0; 282 + } 283 + 284 + void npc_cn20k_debugfs_deinit(struct rvu *rvu) 285 + { 286 + debugfs_remove_recursive(rvu->rvu_dbg.npc); 287 + } 15 288 16 289 void print_nix_cn20k_sq_ctx(struct seq_file *m, 17 290 struct nix_cn20k_sq_ctx_s *sq_ctx)
+3
drivers/net/ethernet/marvell/octeontx2/af/cn20k/debugfs.h
··· 16 16 #include "struct.h" 17 17 #include "../mbox.h" 18 18 19 + int npc_cn20k_debugfs_init(struct rvu *rvu); 20 + void npc_cn20k_debugfs_deinit(struct rvu *rvu); 21 + 19 22 void print_nix_cn20k_sq_ctx(struct seq_file *m, 20 23 struct nix_cn20k_sq_ctx_s *sq_ctx); 21 24 void print_nix_cn20k_cq_ctx(struct seq_file *m,
+17
drivers/net/ethernet/marvell/octeontx2/af/cn20k/mbox_init.c
··· 397 397 if (is_rvu_otx2(rvu) || is_cn20k(rvu->pdev)) 398 398 return 0; 399 399 400 + /* sanity check */ 401 + cfg = rvu_read64(rvu, BLKADDR_RVUM, RVU_PRIV_PFX_NIXX_CFG(0) | 402 + (RVU_AFPF << 16)); 403 + if (!cfg) 404 + return 0; 405 + 400 406 ctx_cfg = rvu_read64(rvu, blkaddr, NIX_AF_CONST3); 401 407 /* Alloc memory for CQINT's HW contexts */ 402 408 cfg = rvu_read64(rvu, blkaddr, NIX_AF_CONST2); ··· 425 419 426 420 rvu_write64(rvu, blkaddr, NIX_AF_LFX_QINTS_BASE(nixlf), 427 421 (u64)pfvf->nix_qints_ctx->iova); 422 + 423 + rvu_write64(rvu, BLKADDR_NIX0, RVU_AF_BAR2_SEL, RVU_AF_BAR2_PFID); 424 + rvu_write64(rvu, BLKADDR_NIX0, 425 + AF_BAR2_ALIASX(0, NIX_GINT_INT_W1S), ALTAF_RDY); 426 + /* wait for ack */ 427 + err = rvu_poll_reg(rvu, BLKADDR_NIX0, 428 + AF_BAR2_ALIASX(0, NIX_GINT_INT), ALTAF_RDY, true); 429 + if (err) 430 + rvu->altaf_ready = false; 431 + else 432 + rvu->altaf_ready = true; 428 433 429 434 return 0; 430 435 }
+4522
drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Marvell RVU Admin Function driver 3 + * 4 + * Copyright (C) 2026 Marvell. 5 + * 6 + */ 7 + #include <linux/xarray.h> 8 + #include <linux/bitfield.h> 9 + 10 + #include "rvu.h" 11 + #include "npc.h" 12 + #include "npc_profile.h" 13 + #include "rvu_npc_hash.h" 14 + #include "rvu_npc.h" 15 + #include "cn20k/npc.h" 16 + #include "cn20k/reg.h" 17 + #include "rvu_npc_fs.h" 18 + 19 + static struct npc_priv_t npc_priv = { 20 + .num_banks = MAX_NUM_BANKS, 21 + }; 22 + 23 + static const char *npc_kw_name[NPC_MCAM_KEY_MAX] = { 24 + [NPC_MCAM_KEY_DYN] = "DYNAMIC", 25 + [NPC_MCAM_KEY_X2] = "X2", 26 + [NPC_MCAM_KEY_X4] = "X4", 27 + }; 28 + 29 + static const char *npc_dft_rule_name[NPC_DFT_RULE_MAX_ID] = { 30 + [NPC_DFT_RULE_PROMISC_ID] = "Promisc", 31 + [NPC_DFT_RULE_MCAST_ID] = "Mcast", 32 + [NPC_DFT_RULE_BCAST_ID] = "Bcast", 33 + [NPC_DFT_RULE_UCAST_ID] = "Ucast", 34 + }; 35 + 36 + #define KEX_EXTR_CFG(bytesm1, hdr_ofs, ena, key_ofs) \ 37 + (((bytesm1) << 16) | ((hdr_ofs) << 8) | ((ena) << 7) | \ 38 + ((key_ofs) & 0x3F)) 39 + 40 + #define NPC_DFT_RULE_ID_MK(pcifunc, id) \ 41 + ((pcifunc) | FIELD_PREP(GENMASK_ULL(31, 16), id)) 42 + 43 + #define NPC_DFT_RULE_ID_2_PCIFUNC(rid) \ 44 + FIELD_GET(GENMASK_ULL(15, 0), rid) 45 + 46 + #define NPC_DFT_RULE_ID_2_ID(rid) \ 47 + FIELD_GET(GENMASK_ULL(31, 16), rid) 48 + 49 + #define NPC_DFT_RULE_PRIO 127 50 + 51 + static const char cn20k_def_pfl_name[] = "default"; 52 + 53 + static struct npc_mcam_kex_extr npc_mkex_extr_default = { 54 + .mkex_sign = MKEX_CN20K_SIGN, 55 + .name = "default", 56 + .kpu_version = NPC_KPU_PROFILE_VER, 57 + .keyx_cfg = { 58 + /* nibble: LA..LE (ltype only) + Error code + Channel */ 59 + [NIX_INTF_RX] = ((u64)NPC_MCAM_KEY_DYN << 32) | 60 + NPC_PARSE_NIBBLE_INTF_RX | 61 + NPC_CN20K_PARSE_NIBBLE_ERRCODE, 62 + 63 + /* nibble: LA..LE (ltype only) */ 64 + [NIX_INTF_TX] = ((u64)NPC_MCAM_KEY_X2 << 32) | 65 + NPC_CN20K_PARSE_NIBBLE_INTF_TX, 66 + }, 67 + .intf_extr_lid = { 68 + /* Default RX MCAM KEX profile */ 69 + [NIX_INTF_RX] = { NPC_LID_LA, NPC_LID_LA, NPC_LID_LB, NPC_LID_LB, 70 + NPC_LID_LC, NPC_LID_LC, NPC_LID_LD }, 71 + [NIX_INTF_TX] = { NPC_LID_LA, NPC_LID_LA, NPC_LID_LB, NPC_LID_LB, 72 + NPC_LID_LC, NPC_LID_LD }, 73 + }, 74 + .intf_extr_lt = { 75 + /* Default RX MCAM KEX profile */ 76 + [NIX_INTF_RX] = { 77 + [0] = { 78 + /* Layer A: Ethernet: */ 79 + [NPC_LT_LA_ETHER] = 80 + /* DMAC: 6 bytes, KW1[63:15] */ 81 + KEX_EXTR_CFG(0x05, 0x0, 0x1, 82 + NPC_KEXOF_DMAC + 1), 83 + [NPC_LT_LA_CPT_HDR] = 84 + /* DMAC: 6 bytes, KW1[63:15] */ 85 + KEX_EXTR_CFG(0x05, 0x0, 0x1, 86 + NPC_KEXOF_DMAC + 1), 87 + }, 88 + [1] = { 89 + /* Layer A: Ethernet: */ 90 + [NPC_LT_LA_ETHER] = 91 + /* Ethertype: 2 bytes, KW0[63:48] */ 92 + KEX_EXTR_CFG(0x01, 0xc, 0x1, 0x6), 93 + [NPC_LT_LA_CPT_HDR] = 94 + /* Ethertype: 2 bytes, KW0[63:48] */ 95 + KEX_EXTR_CFG(0x01, 0xc, 0x1, 0x6), 96 + }, 97 + [2] = { 98 + /* Layer B: Single VLAN (CTAG) */ 99 + [NPC_LT_LB_CTAG] = 100 + /* CTAG VLAN: 2 bytes, KW1[15:0] */ 101 + KEX_EXTR_CFG(0x01, 0x2, 0x1, 0x8), 102 + /* Layer B: Stacked VLAN (STAG|QinQ) */ 103 + [NPC_LT_LB_STAG_QINQ] = 104 + /* Outer VLAN: 2 bytes, KW1[15:0] */ 105 + KEX_EXTR_CFG(0x01, 0x2, 0x1, 0x8), 106 + [NPC_LT_LB_FDSA] = 107 + /* SWITCH PORT: 1 byte, KW1[7:0] */ 108 + KEX_EXTR_CFG(0x0, 0x1, 0x1, 0x8), 109 + }, 110 + [3] = { 111 + [NPC_LT_LB_CTAG] = 112 + /* Ethertype: 2 bytes, KW0[63:48] */ 113 + KEX_EXTR_CFG(0x01, 0x4, 0x1, 0x6), 114 + [NPC_LT_LB_STAG_QINQ] = 115 + /* Ethertype: 2 bytes, KW0[63:48] */ 116 + KEX_EXTR_CFG(0x01, 0x8, 0x1, 0x6), 117 + [NPC_LT_LB_FDSA] = 118 + /* Ethertype: 2 bytes, KW0[63:48] */ 119 + KEX_EXTR_CFG(0x01, 0x4, 0x1, 0x6), 120 + }, 121 + [4] = { 122 + /* Layer C: IPv4 */ 123 + [NPC_LT_LC_IP] = 124 + /* SIP+DIP: 8 bytes, KW3[7:0], KW2[63:8] */ 125 + KEX_EXTR_CFG(0x07, 0xc, 0x1, 0x11), 126 + /* Layer C: IPv6 */ 127 + [NPC_LT_LC_IP6] = 128 + /* Everything up to SADDR: 8 bytes, KW3[7:0], 129 + * KW2[63:8] 130 + */ 131 + KEX_EXTR_CFG(0x07, 0x0, 0x1, 0x11), 132 + }, 133 + [5] = { 134 + [NPC_LT_LC_IP] = 135 + /* TOS: 1 byte, KW2[7:0] */ 136 + KEX_EXTR_CFG(0x0, 0x1, 0x1, 0x10), 137 + }, 138 + [6] = { 139 + /* Layer D:UDP */ 140 + [NPC_LT_LD_UDP] = 141 + /* SPORT+DPORT: 4 bytes, KW3[39:8] */ 142 + KEX_EXTR_CFG(0x3, 0x0, 0x1, 0x19), 143 + /* Layer D:TCP */ 144 + [NPC_LT_LD_TCP] = 145 + /* SPORT+DPORT: 4 bytes, KW3[39:8] */ 146 + KEX_EXTR_CFG(0x3, 0x0, 0x1, 0x19), 147 + }, 148 + }, 149 + /* Default TX MCAM KEX profile */ 150 + [NIX_INTF_TX] = { 151 + [0] = { 152 + /* Layer A: NIX_INST_HDR_S + Ethernet */ 153 + /* NIX appends 8 bytes of NIX_INST_HDR_S at the 154 + * start of each TX packet supplied to NPC. 155 + */ 156 + [NPC_LT_LA_IH_NIX_ETHER] = 157 + /* PF_FUNC: 2B , KW0 [47:32] */ 158 + KEX_EXTR_CFG(0x01, 0x0, 0x1, 0x4), 159 + /* Layer A: HiGig2: */ 160 + [NPC_LT_LA_IH_NIX_HIGIG2_ETHER] = 161 + /* PF_FUNC: 2B , KW0 [47:32] */ 162 + KEX_EXTR_CFG(0x01, 0x0, 0x1, 0x4), 163 + }, 164 + [1] = { 165 + [NPC_LT_LA_IH_NIX_ETHER] = 166 + /* SQ_ID 3 bytes, KW1[63:16] */ 167 + KEX_EXTR_CFG(0x02, 0x02, 0x1, 0xa), 168 + [NPC_LT_LA_IH_NIX_HIGIG2_ETHER] = 169 + /* VID: 2 bytes, KW1[31:16] */ 170 + KEX_EXTR_CFG(0x01, 0x10, 0x1, 0xa), 171 + }, 172 + [2] = { 173 + /* Layer B: Single VLAN (CTAG) */ 174 + [NPC_LT_LB_CTAG] = 175 + /* CTAG VLAN[2..3] KW0[63:48] */ 176 + KEX_EXTR_CFG(0x01, 0x2, 0x1, 0x6), 177 + /* Layer B: Stacked VLAN (STAG|QinQ) */ 178 + [NPC_LT_LB_STAG_QINQ] = 179 + /* Outer VLAN: 2 bytes, KW0[63:48] */ 180 + KEX_EXTR_CFG(0x01, 0x2, 0x1, 0x6), 181 + }, 182 + [3] = { 183 + [NPC_LT_LB_CTAG] = 184 + /* CTAG VLAN[2..3] KW1[15:0] */ 185 + KEX_EXTR_CFG(0x01, 0x4, 0x1, 0x8), 186 + [NPC_LT_LB_STAG_QINQ] = 187 + /* Outer VLAN: 2 Bytes, KW1[15:0] */ 188 + KEX_EXTR_CFG(0x01, 0x8, 0x1, 0x8), 189 + }, 190 + [4] = { 191 + /* Layer C: IPv4 */ 192 + [NPC_LT_LC_IP] = 193 + /* SIP+DIP: 8 bytes, KW2[63:0] */ 194 + KEX_EXTR_CFG(0x07, 0xc, 0x1, 0x10), 195 + /* Layer C: IPv6 */ 196 + [NPC_LT_LC_IP6] = 197 + /* Everything up to SADDR: 8 bytes, KW2[63:0] */ 198 + KEX_EXTR_CFG(0x07, 0x0, 0x1, 0x10), 199 + }, 200 + [5] = { 201 + /* Layer D:UDP */ 202 + [NPC_LT_LD_UDP] = 203 + /* SPORT+DPORT: 4 bytes, KW3[31:0] */ 204 + KEX_EXTR_CFG(0x3, 0x0, 0x1, 0x18), 205 + /* Layer D:TCP */ 206 + [NPC_LT_LD_TCP] = 207 + /* SPORT+DPORT: 4 bytes, KW3[31:0] */ 208 + KEX_EXTR_CFG(0x3, 0x0, 0x1, 0x18), 209 + }, 210 + }, 211 + }, 212 + }; 213 + 214 + struct npc_mcam_kex_extr *npc_mkex_extr_default_get(void) 215 + { 216 + return &npc_mkex_extr_default; 217 + } 218 + 219 + static u16 npc_idx2vidx(u16 idx) 220 + { 221 + unsigned long index; 222 + void *map; 223 + u16 vidx; 224 + int val; 225 + 226 + vidx = idx; 227 + index = idx; 228 + 229 + map = xa_load(&npc_priv.xa_idx2vidx_map, index); 230 + if (!map) 231 + goto done; 232 + 233 + val = xa_to_value(map); 234 + if (val == -1) 235 + goto done; 236 + 237 + vidx = val; 238 + 239 + done: 240 + return vidx; 241 + } 242 + 243 + static bool npc_is_vidx(u16 vidx) 244 + { 245 + return vidx >= npc_priv.bank_depth * 2; 246 + } 247 + 248 + static u16 npc_vidx2idx(u16 vidx) 249 + { 250 + unsigned long sentinel = (unsigned long)-1; 251 + unsigned long index; 252 + void *map; 253 + int val; 254 + u16 idx; 255 + 256 + idx = vidx; 257 + index = vidx; 258 + 259 + map = xa_load(&npc_priv.xa_vidx2idx_map, index); 260 + if (!map) 261 + goto done; 262 + 263 + val = xa_to_value(map); 264 + if (val == sentinel) 265 + goto done; 266 + 267 + idx = val; 268 + 269 + done: 270 + return idx; 271 + } 272 + 273 + u16 npc_cn20k_vidx2idx(u16 idx) 274 + { 275 + if (!npc_priv.init_done) 276 + return idx; 277 + 278 + if (!npc_is_vidx(idx)) 279 + return idx; 280 + 281 + return npc_vidx2idx(idx); 282 + } 283 + 284 + u16 npc_cn20k_idx2vidx(u16 idx) 285 + { 286 + if (!npc_priv.init_done) 287 + return idx; 288 + 289 + if (npc_is_vidx(idx)) 290 + return idx; 291 + 292 + return npc_idx2vidx(idx); 293 + } 294 + 295 + static int npc_vidx_maps_del_entry(struct rvu *rvu, u16 vidx, u16 *old_midx) 296 + { 297 + u16 mcam_idx; 298 + void *map; 299 + 300 + if (!npc_is_vidx(vidx)) { 301 + dev_err(rvu->dev, 302 + "%s: vidx(%u) does not map to proper mcam idx\n", 303 + __func__, vidx); 304 + return -ESRCH; 305 + } 306 + 307 + mcam_idx = npc_vidx2idx(vidx); 308 + 309 + map = xa_erase(&npc_priv.xa_vidx2idx_map, vidx); 310 + if (!map) { 311 + dev_err(rvu->dev, 312 + "%s: vidx(%u) does not map to proper mcam idx\n", 313 + __func__, vidx); 314 + return -ESRCH; 315 + } 316 + 317 + map = xa_erase(&npc_priv.xa_idx2vidx_map, mcam_idx); 318 + if (!map) { 319 + dev_err(rvu->dev, 320 + "%s: vidx(%u) is not valid\n", 321 + __func__, vidx); 322 + return -ESRCH; 323 + } 324 + 325 + if (old_midx) 326 + *old_midx = mcam_idx; 327 + 328 + return 0; 329 + } 330 + 331 + static int npc_vidx_maps_modify(struct rvu *rvu, u16 vidx, u16 new_midx) 332 + { 333 + u16 old_midx; 334 + void *map; 335 + int rc; 336 + 337 + if (!npc_is_vidx(vidx)) { 338 + dev_err(rvu->dev, 339 + "%s: vidx(%u) does not map to proper mcam idx\n", 340 + __func__, vidx); 341 + return -ESRCH; 342 + } 343 + 344 + map = xa_erase(&npc_priv.xa_vidx2idx_map, vidx); 345 + if (!map) { 346 + dev_err(rvu->dev, 347 + "%s: vidx(%u) could not be deleted from vidx2idx map\n", 348 + __func__, vidx); 349 + return -ESRCH; 350 + } 351 + 352 + old_midx = xa_to_value(map); 353 + 354 + rc = xa_insert(&npc_priv.xa_vidx2idx_map, vidx, 355 + xa_mk_value(new_midx), GFP_KERNEL); 356 + if (rc) { 357 + dev_err(rvu->dev, 358 + "%s: vidx(%u) cannot be added to vidx2idx map\n", 359 + __func__, vidx); 360 + goto fail1; 361 + } 362 + 363 + map = xa_erase(&npc_priv.xa_idx2vidx_map, old_midx); 364 + if (!map) { 365 + dev_err(rvu->dev, 366 + "%s: old_midx(%u, vidx(%u)) cannot be added to idx2vidx map\n", 367 + __func__, old_midx, vidx); 368 + rc = -ESRCH; 369 + goto fail2; 370 + } 371 + 372 + rc = xa_insert(&npc_priv.xa_idx2vidx_map, new_midx, 373 + xa_mk_value(vidx), GFP_KERNEL); 374 + if (rc) { 375 + dev_err(rvu->dev, 376 + "%s: new_midx(%u, vidx(%u)) cannot be added to idx2vidx map\n", 377 + __func__, new_midx, vidx); 378 + goto fail3; 379 + } 380 + 381 + return 0; 382 + 383 + fail3: 384 + /* Restore vidx at old_midx location */ 385 + if (xa_insert(&npc_priv.xa_idx2vidx_map, old_midx, 386 + xa_mk_value(vidx), GFP_KERNEL)) 387 + dev_err(rvu->dev, 388 + "%s: Error to roll back idx2vidx old_midx=%u vidx=%u\n", 389 + __func__, old_midx, vidx); 390 + fail2: 391 + /* Erase new_midx inserted at vidx */ 392 + if (!xa_erase(&npc_priv.xa_vidx2idx_map, vidx)) 393 + dev_err(rvu->dev, 394 + "%s: Failed to roll back vidx2idx vidx=%u\n", 395 + __func__, vidx); 396 + 397 + fail1: 398 + /* Restore old_midx at vidx location */ 399 + if (xa_insert(&npc_priv.xa_vidx2idx_map, vidx, 400 + xa_mk_value(old_midx), GFP_KERNEL)) 401 + dev_err(rvu->dev, 402 + "%s: Failed to roll back vidx2idx to old_midx=%u, vidx=%u\n", 403 + __func__, old_midx, vidx); 404 + 405 + return rc; 406 + } 407 + 408 + static int npc_vidx_maps_add_entry(struct rvu *rvu, u16 mcam_idx, int pcifunc, 409 + u16 *vidx) 410 + { 411 + int rc, max, min; 412 + u32 id; 413 + 414 + /* Virtual index start from maximum mcam index + 1 */ 415 + max = npc_priv.bank_depth * 2 * 2 - 1; 416 + min = npc_priv.bank_depth * 2; 417 + 418 + rc = xa_alloc(&npc_priv.xa_vidx2idx_map, &id, 419 + xa_mk_value(mcam_idx), 420 + XA_LIMIT(min, max), GFP_KERNEL); 421 + if (rc) { 422 + dev_err(rvu->dev, 423 + "%s: Failed to add to vidx2idx map (%u)\n", 424 + __func__, mcam_idx); 425 + goto fail1; 426 + } 427 + 428 + rc = xa_insert(&npc_priv.xa_idx2vidx_map, mcam_idx, 429 + xa_mk_value(id), GFP_KERNEL); 430 + if (rc) { 431 + dev_err(rvu->dev, 432 + "%s: Failed to add to idx2vidx map (%u)\n", 433 + __func__, mcam_idx); 434 + goto fail2; 435 + } 436 + 437 + if (vidx) 438 + *vidx = id; 439 + 440 + return 0; 441 + 442 + fail2: 443 + xa_erase(&npc_priv.xa_vidx2idx_map, id); 444 + fail1: 445 + return rc; 446 + } 447 + 448 + static void npc_config_kpmcam(struct rvu *rvu, int blkaddr, 449 + const struct npc_kpu_profile_cam *kpucam, 450 + int kpm, int entry) 451 + { 452 + struct npc_kpu_cam cam0 = {0}; 453 + struct npc_kpu_cam cam1 = {0}; 454 + 455 + cam1.state = kpucam->state & kpucam->state_mask; 456 + cam1.dp0_data = kpucam->dp0 & kpucam->dp0_mask; 457 + cam1.dp1_data = kpucam->dp1 & kpucam->dp1_mask; 458 + cam1.dp2_data = kpucam->dp2 & kpucam->dp2_mask; 459 + 460 + cam0.state = ~kpucam->state & kpucam->state_mask; 461 + cam0.dp0_data = ~kpucam->dp0 & kpucam->dp0_mask; 462 + cam0.dp1_data = ~kpucam->dp1 & kpucam->dp1_mask; 463 + cam0.dp2_data = ~kpucam->dp2 & kpucam->dp2_mask; 464 + 465 + rvu_write64(rvu, blkaddr, 466 + NPC_AF_KPMX_ENTRYX_CAMX(kpm, entry, 0), *(u64 *)&cam0); 467 + rvu_write64(rvu, blkaddr, 468 + NPC_AF_KPMX_ENTRYX_CAMX(kpm, entry, 1), *(u64 *)&cam1); 469 + } 470 + 471 + static void 472 + npc_config_kpmaction(struct rvu *rvu, int blkaddr, 473 + const struct npc_kpu_profile_action *kpuaction, 474 + int kpm, int entry, bool pkind) 475 + { 476 + struct npc_kpm_action0 action0 = {0}; 477 + struct npc_kpu_action1 action1 = {0}; 478 + u64 reg; 479 + 480 + action1.errlev = kpuaction->errlev; 481 + action1.errcode = kpuaction->errcode; 482 + action1.dp0_offset = kpuaction->dp0_offset; 483 + action1.dp1_offset = kpuaction->dp1_offset; 484 + action1.dp2_offset = kpuaction->dp2_offset; 485 + 486 + if (pkind) 487 + reg = NPC_AF_PKINDX_ACTION1(entry); 488 + else 489 + reg = NPC_AF_KPMX_ENTRYX_ACTION1(kpm, entry); 490 + 491 + rvu_write64(rvu, blkaddr, reg, *(u64 *)&action1); 492 + 493 + action0.byp_count = kpuaction->bypass_count & 0x7; 494 + action0.capture_ena = kpuaction->cap_ena & 1; 495 + action0.parse_done = kpuaction->parse_done & 1; 496 + action0.next_state = kpuaction->next_state & 0xf; 497 + action0.capture_lid = kpuaction->lid & 0x7; 498 + 499 + /* Parser functionality will work correctly even though 500 + * upper flag bits are silently discarded 501 + */ 502 + action0.capture_ltype = kpuaction->ltype & 0xf; 503 + action0.capture_flags = kpuaction->flags & 0xf; 504 + action0.ptr_advance = kpuaction->ptr_advance; 505 + 506 + action0.var_len_offset = kpuaction->offset; 507 + action0.var_len_mask = kpuaction->mask; 508 + action0.var_len_right = kpuaction->right & 1; 509 + action0.var_len_shift = kpuaction->shift & 1; 510 + 511 + if (pkind) 512 + reg = NPC_AF_PKINDX_ACTION0(entry); 513 + else 514 + reg = NPC_AF_KPMX_ENTRYX_ACTION0(kpm, entry); 515 + 516 + rvu_write64(rvu, blkaddr, reg, *(u64 *)&action0); 517 + } 518 + 519 + static void 520 + npc_program_single_kpm_profile(struct rvu *rvu, int blkaddr, 521 + int kpm, int start_entry, 522 + const struct npc_kpu_profile *profile) 523 + { 524 + int entry, num_entries, max_entries; 525 + u64 idx; 526 + 527 + if (profile->cam_entries != profile->action_entries) { 528 + dev_err(rvu->dev, 529 + "kpm%d: CAM and action entries [%d != %d] not equal\n", 530 + kpm, profile->cam_entries, profile->action_entries); 531 + 532 + WARN(1, "Fatal error\n"); 533 + return; 534 + } 535 + 536 + max_entries = rvu->hw->npc_kpu_entries / 2; 537 + entry = start_entry; 538 + /* Program CAM match entries for previous kpm extracted data */ 539 + num_entries = min_t(int, profile->cam_entries, max_entries); 540 + for (idx = 0; entry < num_entries + start_entry; entry++, idx++) 541 + npc_config_kpmcam(rvu, blkaddr, &profile->cam[idx], 542 + kpm, entry); 543 + 544 + entry = start_entry; 545 + /* Program this kpm's actions */ 546 + num_entries = min_t(int, profile->action_entries, max_entries); 547 + for (idx = 0; entry < num_entries + start_entry; entry++, idx++) 548 + npc_config_kpmaction(rvu, blkaddr, &profile->action[idx], 549 + kpm, entry, false); 550 + } 551 + 552 + static void 553 + npc_enable_kpm_entry(struct rvu *rvu, int blkaddr, int kpm, int num_entries) 554 + { 555 + u64 entry_mask; 556 + 557 + entry_mask = npc_enable_mask(num_entries); 558 + /* Disable first KPU_CN20K_MAX_CST_ENT entries for built-in profile */ 559 + if (!rvu->kpu.custom) 560 + entry_mask |= GENMASK_ULL(KPU_CN20K_MAX_CST_ENT - 1, 0); 561 + rvu_write64(rvu, blkaddr, 562 + NPC_AF_KPMX_ENTRY_DISX(kpm, 0), entry_mask); 563 + if (num_entries <= 64) { 564 + /* Disable all the entries in W1, W2 and W3 */ 565 + rvu_write64(rvu, blkaddr, 566 + NPC_AF_KPMX_ENTRY_DISX(kpm, 1), 567 + npc_enable_mask(0)); 568 + rvu_write64(rvu, blkaddr, 569 + NPC_AF_KPMX_ENTRY_DISX(kpm, 2), 570 + npc_enable_mask(0)); 571 + rvu_write64(rvu, blkaddr, 572 + NPC_AF_KPMX_ENTRY_DISX(kpm, 3), 573 + npc_enable_mask(0)); 574 + return; 575 + } 576 + 577 + num_entries = num_entries - 64; 578 + entry_mask = npc_enable_mask(num_entries); 579 + rvu_write64(rvu, blkaddr, 580 + NPC_AF_KPMX_ENTRY_DISX(kpm, 1), entry_mask); 581 + if (num_entries <= 64) { 582 + /* Disable all the entries in W2 and W3 */ 583 + rvu_write64(rvu, blkaddr, 584 + NPC_AF_KPMX_ENTRY_DISX(kpm, 2), 585 + npc_enable_mask(0)); 586 + rvu_write64(rvu, blkaddr, 587 + NPC_AF_KPMX_ENTRY_DISX(kpm, 3), 588 + npc_enable_mask(0)); 589 + return; 590 + } 591 + 592 + num_entries = num_entries - 64; 593 + entry_mask = npc_enable_mask(num_entries); 594 + rvu_write64(rvu, blkaddr, 595 + NPC_AF_KPMX_ENTRY_DISX(kpm, 2), entry_mask); 596 + if (num_entries <= 64) { 597 + /* Disable all the entries in W3 */ 598 + rvu_write64(rvu, blkaddr, 599 + NPC_AF_KPMX_ENTRY_DISX(kpm, 3), 600 + npc_enable_mask(0)); 601 + return; 602 + } 603 + 604 + num_entries = num_entries - 64; 605 + entry_mask = npc_enable_mask(num_entries); 606 + rvu_write64(rvu, blkaddr, 607 + NPC_AF_KPMX_ENTRY_DISX(kpm, 3), entry_mask); 608 + } 609 + 610 + #define KPU_OFFSET 8 611 + static void npc_program_kpm_profile(struct rvu *rvu, int blkaddr, int num_kpms) 612 + { 613 + const struct npc_kpu_profile *profile1, *profile2; 614 + int idx, total_cam_entries; 615 + 616 + for (idx = 0; idx < num_kpms; idx++) { 617 + profile1 = &rvu->kpu.kpu[idx]; 618 + npc_program_single_kpm_profile(rvu, blkaddr, idx, 0, profile1); 619 + profile2 = &rvu->kpu.kpu[idx + KPU_OFFSET]; 620 + npc_program_single_kpm_profile(rvu, blkaddr, idx, 621 + profile1->cam_entries, 622 + profile2); 623 + total_cam_entries = profile1->cam_entries + 624 + profile2->cam_entries; 625 + npc_enable_kpm_entry(rvu, blkaddr, idx, total_cam_entries); 626 + rvu_write64(rvu, blkaddr, NPC_AF_KPMX_PASS2_OFFSET(idx), 627 + profile1->cam_entries); 628 + /* Enable the KPUs associated with this KPM */ 629 + rvu_write64(rvu, blkaddr, NPC_AF_KPUX_CFG(idx), 0x01); 630 + rvu_write64(rvu, blkaddr, NPC_AF_KPUX_CFG(idx + KPU_OFFSET), 631 + 0x01); 632 + } 633 + } 634 + 635 + void npc_cn20k_parser_profile_init(struct rvu *rvu, int blkaddr) 636 + { 637 + struct rvu_hwinfo *hw = rvu->hw; 638 + int num_pkinds, idx; 639 + 640 + /* Disable all KPMs and their entries */ 641 + for (idx = 0; idx < hw->npc_kpms; idx++) { 642 + rvu_write64(rvu, blkaddr, 643 + NPC_AF_KPMX_ENTRY_DISX(idx, 0), ~0ULL); 644 + rvu_write64(rvu, blkaddr, 645 + NPC_AF_KPMX_ENTRY_DISX(idx, 1), ~0ULL); 646 + rvu_write64(rvu, blkaddr, 647 + NPC_AF_KPMX_ENTRY_DISX(idx, 2), ~0ULL); 648 + rvu_write64(rvu, blkaddr, 649 + NPC_AF_KPMX_ENTRY_DISX(idx, 3), ~0ULL); 650 + } 651 + 652 + for (idx = 0; idx < hw->npc_kpus; idx++) 653 + rvu_write64(rvu, blkaddr, NPC_AF_KPUX_CFG(idx), 0x00); 654 + 655 + /* Load and customize KPU profile. */ 656 + npc_load_kpu_profile(rvu); 657 + 658 + /* Configure KPU and KPM mapping for second pass */ 659 + rvu_write64(rvu, blkaddr, NPC_AF_KPM_PASS2_CFG, 0x76543210); 660 + 661 + /* First program IKPU profile i.e PKIND configs. 662 + * Check HW max count to avoid configuring junk or 663 + * writing to unsupported CSR addresses. 664 + */ 665 + num_pkinds = rvu->kpu.pkinds; 666 + num_pkinds = min_t(int, hw->npc_pkinds, num_pkinds); 667 + 668 + for (idx = 0; idx < num_pkinds; idx++) 669 + npc_config_kpmaction(rvu, blkaddr, &rvu->kpu.ikpu[idx], 670 + 0, idx, true); 671 + 672 + /* Program KPM CAM and Action profiles */ 673 + npc_program_kpm_profile(rvu, blkaddr, hw->npc_kpms); 674 + } 675 + 676 + struct npc_priv_t *npc_priv_get(void) 677 + { 678 + return &npc_priv; 679 + } 680 + 681 + static void npc_program_mkex_rx(struct rvu *rvu, int blkaddr, 682 + struct npc_mcam_kex_extr *mkex_extr, 683 + u8 intf) 684 + { 685 + u8 num_extr = rvu->hw->npc_kex_extr; 686 + int extr, lt; 687 + u64 val; 688 + 689 + if (is_npc_intf_tx(intf)) 690 + return; 691 + 692 + rvu_write64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(intf), 693 + mkex_extr->keyx_cfg[NIX_INTF_RX]); 694 + 695 + /* Program EXTRACTOR */ 696 + for (extr = 0; extr < num_extr; extr++) 697 + rvu_write64(rvu, blkaddr, 698 + NPC_AF_INTFX_EXTRACTORX_CFG(intf, extr), 699 + mkex_extr->intf_extr_lid[intf][extr]); 700 + 701 + /* Program EXTRACTOR_LTYPE */ 702 + for (extr = 0; extr < num_extr; extr++) { 703 + for (lt = 0; lt < NPC_MAX_LT; lt++) { 704 + val = mkex_extr->intf_extr_lt[intf][extr][lt]; 705 + CN20K_SET_EXTR_LT(intf, extr, lt, val); 706 + } 707 + } 708 + } 709 + 710 + static void npc_program_mkex_tx(struct rvu *rvu, int blkaddr, 711 + struct npc_mcam_kex_extr *mkex_extr, 712 + u8 intf) 713 + { 714 + u8 num_extr = rvu->hw->npc_kex_extr; 715 + int extr, lt; 716 + u64 val; 717 + 718 + if (is_npc_intf_rx(intf)) 719 + return; 720 + 721 + rvu_write64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(intf), 722 + mkex_extr->keyx_cfg[NIX_INTF_TX]); 723 + 724 + /* Program EXTRACTOR */ 725 + for (extr = 0; extr < num_extr; extr++) 726 + rvu_write64(rvu, blkaddr, 727 + NPC_AF_INTFX_EXTRACTORX_CFG(intf, extr), 728 + mkex_extr->intf_extr_lid[intf][extr]); 729 + 730 + /* Program EXTRACTOR_LTYPE */ 731 + for (extr = 0; extr < num_extr; extr++) { 732 + for (lt = 0; lt < NPC_MAX_LT; lt++) { 733 + val = mkex_extr->intf_extr_lt[intf][extr][lt]; 734 + CN20K_SET_EXTR_LT(intf, extr, lt, val); 735 + } 736 + } 737 + } 738 + 739 + static void npc_program_mkex_profile(struct rvu *rvu, int blkaddr, 740 + struct npc_mcam_kex_extr *mkex_extr) 741 + { 742 + struct rvu_hwinfo *hw = rvu->hw; 743 + u8 intf; 744 + 745 + for (intf = 0; intf < hw->npc_intfs; intf++) { 746 + npc_program_mkex_rx(rvu, blkaddr, mkex_extr, intf); 747 + npc_program_mkex_tx(rvu, blkaddr, mkex_extr, intf); 748 + } 749 + 750 + /* Programme mkex hash profile */ 751 + npc_program_mkex_hash(rvu, blkaddr); 752 + } 753 + 754 + void npc_cn20k_load_mkex_profile(struct rvu *rvu, int blkaddr, 755 + const char *mkex_profile) 756 + { 757 + struct npc_mcam_kex_extr *mcam_kex_extr; 758 + struct device *dev = &rvu->pdev->dev; 759 + void __iomem *mkex_prfl_addr = NULL; 760 + u64 prfl_sz; 761 + int ret; 762 + 763 + /* If user not selected mkex profile */ 764 + if (rvu->kpu_fwdata_sz || 765 + !strncmp(mkex_profile, cn20k_def_pfl_name, MKEX_NAME_LEN)) 766 + goto program_mkex_extr; 767 + 768 + /* Setting up the mapping for mkex profile image */ 769 + ret = npc_fwdb_prfl_img_map(rvu, &mkex_prfl_addr, &prfl_sz); 770 + if (ret < 0) 771 + goto program_mkex_extr; 772 + 773 + mcam_kex_extr = (struct npc_mcam_kex_extr __force *)mkex_prfl_addr; 774 + 775 + while (((s64)prfl_sz > 0) && 776 + (mcam_kex_extr->mkex_sign != MKEX_END_SIGN)) { 777 + /* Compare with mkex mod_param name string */ 778 + if (mcam_kex_extr->mkex_sign == MKEX_CN20K_SIGN && 779 + !strncmp(mcam_kex_extr->name, mkex_profile, 780 + MKEX_NAME_LEN)) { 781 + rvu->kpu.mcam_kex_prfl.mkex_extr = mcam_kex_extr; 782 + goto program_mkex_extr; 783 + } 784 + 785 + mcam_kex_extr++; 786 + prfl_sz -= sizeof(struct npc_mcam_kex_extr); 787 + } 788 + dev_warn(dev, "Failed to load requested profile: %s\n", mkex_profile); 789 + rvu->kpu.mcam_kex_prfl.mkex_extr = npc_mkex_extr_default_get(); 790 + 791 + program_mkex_extr: 792 + dev_info(rvu->dev, "Using %s mkex profile\n", 793 + rvu->kpu.mcam_kex_prfl.mkex_extr->name); 794 + /* Program selected mkex profile */ 795 + npc_program_mkex_profile(rvu, blkaddr, 796 + rvu->kpu.mcam_kex_prfl.mkex_extr); 797 + if (mkex_prfl_addr) 798 + iounmap(mkex_prfl_addr); 799 + } 800 + 801 + void 802 + npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkaddr, 803 + int index, bool enable) 804 + { 805 + struct npc_mcam *mcam = &rvu->hw->mcam; 806 + int mcam_idx = index % mcam->banksize; 807 + int bank = index / mcam->banksize; 808 + u64 cfg, hw_prio; 809 + u8 kw_type; 810 + 811 + npc_mcam_idx_2_key_type(rvu, index, &kw_type); 812 + if (kw_type == NPC_MCAM_KEY_X2) { 813 + cfg = rvu_read64(rvu, blkaddr, 814 + NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(mcam_idx, 815 + bank)); 816 + hw_prio = cfg & GENMASK_ULL(30, 24); 817 + cfg = enable ? 1 : 0; 818 + cfg |= hw_prio; 819 + rvu_write64(rvu, blkaddr, 820 + NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(mcam_idx, bank), 821 + cfg); 822 + return; 823 + } 824 + 825 + /* For NPC_CN20K_MCAM_KEY_X4 keys, both the banks 826 + * need to be programmed with the same value. 827 + */ 828 + for (bank = 0; bank < mcam->banks_per_entry; bank++) { 829 + cfg = rvu_read64(rvu, blkaddr, 830 + NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(mcam_idx, 831 + bank)); 832 + hw_prio = cfg & GENMASK_ULL(30, 24); 833 + cfg = enable ? 1 : 0; 834 + cfg |= hw_prio; 835 + rvu_write64(rvu, blkaddr, 836 + NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(mcam_idx, bank), 837 + cfg); 838 + } 839 + } 840 + 841 + void 842 + npc_cn20k_clear_mcam_entry(struct rvu *rvu, int blkaddr, int bank, int index) 843 + { 844 + rvu_write64(rvu, blkaddr, 845 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_INTF_EXT(index, bank, 1), 846 + 0); 847 + rvu_write64(rvu, blkaddr, 848 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_INTF_EXT(index, bank, 0), 849 + 0); 850 + 851 + rvu_write64(rvu, blkaddr, 852 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W0_EXT(index, bank, 1), 0); 853 + rvu_write64(rvu, blkaddr, 854 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W0_EXT(index, bank, 0), 0); 855 + 856 + rvu_write64(rvu, blkaddr, 857 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W1_EXT(index, bank, 1), 0); 858 + rvu_write64(rvu, blkaddr, 859 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W1_EXT(index, bank, 0), 0); 860 + 861 + rvu_write64(rvu, blkaddr, 862 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W2_EXT(index, bank, 1), 0); 863 + rvu_write64(rvu, blkaddr, 864 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W2_EXT(index, bank, 0), 0); 865 + 866 + rvu_write64(rvu, blkaddr, 867 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W3_EXT(index, bank, 1), 0); 868 + rvu_write64(rvu, blkaddr, 869 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W3_EXT(index, bank, 0), 0); 870 + 871 + /* Clear corresponding stats register */ 872 + rvu_write64(rvu, blkaddr, 873 + NPC_AF_CN20K_MCAMEX_BANKX_STAT_EXT(index, bank), 0); 874 + } 875 + 876 + static void npc_cn20k_get_keyword(struct cn20k_mcam_entry *entry, int idx, 877 + u64 *cam0, u64 *cam1) 878 + { 879 + u64 kw_mask; 880 + 881 + /* The two banks of every MCAM entry are used as a single double-wide 882 + * entry that is compared with the search key as follows: 883 + * 884 + * NPC_AF_MCAME()_BANK(0)_CAM(0..1)_W0_EXT[MD] ->NPC_MCAM_KEY_X4_S[KW0] 885 + * NPC_AF_MCAME()_BANK(0)_CAM(0..1)_W1_EXT[MD] ->NPC_MCAM_KEY_X4_S[KW1] 886 + * NPC_AF_MCAME()_BANK(0)_CAM(0..1)_W2_EXT[MD] ->NPC_MCAM_KEY_X4_S[KW2] 887 + * NPC_AF_MCAME()_BANK(0)_CAM(0..1)_W3_EXT[MD] ->NPC_MCAM_KEY_X4_S[KW3] 888 + * NPC_AF_MCAME()_BANK(1)_CAM(0..1)_W0_EXT[MD] ->NPC_MCAM_KEY_X4_S[KW4] 889 + * NPC_AF_MCAME()_BANK(1)_CAM(0..1)_W1_EXT[MD] ->NPC_MCAM_KEY_X4_S[KW5] 890 + * NPC_AF_MCAME()_BANK(1)_CAM(0..1)_W2_EXT[MD] ->NPC_MCAM_KEY_X4_S[KW6] 891 + * NPC_AF_MCAME()_BANK(1)_CAM(0..1)_W3_EXT[MD] ->NPC_MCAM_KEY_X4_S[KW7] 892 + */ 893 + *cam1 = entry->kw[idx]; 894 + kw_mask = entry->kw_mask[idx]; 895 + *cam1 &= kw_mask; 896 + *cam0 = ~*cam1 & kw_mask; 897 + } 898 + 899 + /*------------------------------------------------------------------------- 900 + *Kex type| mcam | cam1 |cam0 | req_kwtype||<----- output > | 901 + * in | | | | || | | 902 + * profile| len | | | ||len | type | 903 + *------------------------------------------------------------------------- 904 + *X2 | 256 (X2) | 001b |110b | 0 ||X2 | X2 | 905 + *------------------------------------------------------------------------| 906 + *X4 | 256 (X2) | 000b |000b | 0 ||X2 | DYN | 907 + *------------------------------------------------------------------------| 908 + *X4 | 512 (X4) | 010b |101b | 0 ||X4 | X4 | 909 + *------------------------------------------------------------------------| 910 + *DYN | 256 (X2) | 000b |000b | 0 ||X2 | DYN | 911 + *------------------------------------------------------------------------| 912 + *DYN | 512 (X4) | 010b |101b | 0 ||X4 | X4 | 913 + *------------------------------------------------------------------------| 914 + *X4 | 256 (X2) | 000b |000b | X2 ||DYN | DYN | 915 + *------------------------------------------------------------------------| 916 + *DYNC | 256 (X2) | 000b |000b | X2 ||DYN | DYN | 917 + *------------------------------------------------------------------------| 918 + * X2 | 512 (X4) | xxxb |xxxb | X4 ||INVAL | INVAL | 919 + *------------------------------------------------------------------------| 920 + */ 921 + static void npc_cn20k_config_kw_x2(struct rvu *rvu, struct npc_mcam *mcam, 922 + int blkaddr, int index, u8 intf, 923 + struct cn20k_mcam_entry *entry, 924 + int bank, u8 kw_type, int kw, 925 + u8 req_kw_type) 926 + { 927 + u64 intf_ext = 0, intf_ext_mask = 0; 928 + u8 tx_intf_mask = ~intf & 0x3; 929 + u8 tx_intf = intf, kex_type; 930 + u8 kw_type_mask = ~kw_type; 931 + u64 cam0, cam1, kex_cfg; 932 + 933 + if (is_npc_intf_tx(intf)) { 934 + /* Last bit must be set and rest don't care 935 + * for TX interfaces 936 + */ 937 + tx_intf_mask = 0x1; 938 + tx_intf = intf & tx_intf_mask; 939 + tx_intf_mask = ~tx_intf & tx_intf_mask; 940 + } 941 + 942 + kex_cfg = rvu_read64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(intf)); 943 + kex_type = (kex_cfg & GENMASK_ULL(34, 32)) >> 32; 944 + if ((kex_type == NPC_MCAM_KEY_DYN || kex_type == NPC_MCAM_KEY_X4) && 945 + kw_type == NPC_MCAM_KEY_X2) { 946 + kw_type = 0; 947 + kw_type_mask = 0; 948 + } 949 + 950 + /* Say, we need to write x2 keyword in an x4 subbank. 951 + * req_kw_type will be x2, and kw_type will be x4. 952 + * So in the case ignore kw bits in mcam. 953 + */ 954 + if (kw_type == NPC_MCAM_KEY_X4 && req_kw_type == NPC_MCAM_KEY_X2) { 955 + kw_type = 0; 956 + kw_type_mask = 0; 957 + } 958 + 959 + intf_ext = ((u64)kw_type << 16) | tx_intf; 960 + intf_ext_mask = (((u64)kw_type_mask << 16) & GENMASK_ULL(18, 16)) | 961 + tx_intf_mask; 962 + rvu_write64(rvu, blkaddr, 963 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_INTF_EXT(index, bank, 1), 964 + intf_ext); 965 + rvu_write64(rvu, blkaddr, 966 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_INTF_EXT(index, bank, 0), 967 + intf_ext_mask); 968 + 969 + /* Set the match key */ 970 + npc_cn20k_get_keyword(entry, kw, &cam0, &cam1); 971 + rvu_write64(rvu, blkaddr, 972 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W0_EXT(index, bank, 1), 973 + cam1); 974 + rvu_write64(rvu, blkaddr, 975 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W0_EXT(index, bank, 0), 976 + cam0); 977 + 978 + npc_cn20k_get_keyword(entry, kw + 1, &cam0, &cam1); 979 + rvu_write64(rvu, blkaddr, 980 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W1_EXT(index, bank, 1), 981 + cam1); 982 + rvu_write64(rvu, blkaddr, 983 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W1_EXT(index, bank, 0), 984 + cam0); 985 + 986 + npc_cn20k_get_keyword(entry, kw + 2, &cam0, &cam1); 987 + rvu_write64(rvu, blkaddr, 988 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W2_EXT(index, bank, 1), 989 + cam1); 990 + rvu_write64(rvu, blkaddr, 991 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W2_EXT(index, bank, 0), 992 + cam0); 993 + 994 + npc_cn20k_get_keyword(entry, kw + 3, &cam0, &cam1); 995 + rvu_write64(rvu, blkaddr, 996 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W3_EXT(index, bank, 1), 997 + cam1); 998 + rvu_write64(rvu, blkaddr, 999 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W3_EXT(index, bank, 0), 1000 + cam0); 1001 + } 1002 + 1003 + static void npc_cn20k_config_kw_x4(struct rvu *rvu, struct npc_mcam *mcam, 1004 + int blkaddr, int index, u8 intf, 1005 + struct cn20k_mcam_entry *entry, 1006 + u8 kw_type, u8 req_kw_type) 1007 + { 1008 + int kw = 0, bank; 1009 + 1010 + for (bank = 0; bank < mcam->banks_per_entry; bank++, kw = kw + 4) 1011 + npc_cn20k_config_kw_x2(rvu, mcam, blkaddr, 1012 + index, intf, 1013 + entry, bank, kw_type, 1014 + kw, req_kw_type); 1015 + } 1016 + 1017 + static void 1018 + npc_cn20k_set_mcam_bank_cfg(struct rvu *rvu, int blkaddr, int mcam_idx, 1019 + int bank, u8 kw_type, bool enable, u8 hw_prio) 1020 + { 1021 + struct npc_mcam *mcam = &rvu->hw->mcam; 1022 + u64 bank_cfg; 1023 + 1024 + bank_cfg = (u64)hw_prio << 24; 1025 + if (enable) 1026 + bank_cfg |= 0x1; 1027 + 1028 + if (kw_type == NPC_MCAM_KEY_X2) { 1029 + rvu_write64(rvu, blkaddr, 1030 + NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(mcam_idx, bank), 1031 + bank_cfg); 1032 + return; 1033 + } 1034 + 1035 + /* For NPC_MCAM_KEY_X4 keys, both the banks 1036 + * need to be programmed with the same value. 1037 + */ 1038 + for (bank = 0; bank < mcam->banks_per_entry; bank++) { 1039 + rvu_write64(rvu, blkaddr, 1040 + NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(mcam_idx, bank), 1041 + bank_cfg); 1042 + } 1043 + } 1044 + 1045 + void npc_cn20k_config_mcam_entry(struct rvu *rvu, int blkaddr, int index, 1046 + u8 intf, struct cn20k_mcam_entry *entry, 1047 + bool enable, u8 hw_prio, u8 req_kw_type) 1048 + { 1049 + struct npc_mcam *mcam = &rvu->hw->mcam; 1050 + int mcam_idx = index % mcam->banksize; 1051 + int bank = index / mcam->banksize; 1052 + int kw = 0; 1053 + u8 kw_type; 1054 + 1055 + /* Disable before mcam entry update */ 1056 + npc_cn20k_enable_mcam_entry(rvu, blkaddr, index, false); 1057 + 1058 + npc_mcam_idx_2_key_type(rvu, index, &kw_type); 1059 + /* CAM1 takes the comparison value and 1060 + * CAM0 specifies match for a bit in key being '0' or '1' or 'dontcare'. 1061 + * CAM1<n> = 0 & CAM0<n> = 1 => match if key<n> = 0 1062 + * CAM1<n> = 1 & CAM0<n> = 0 => match if key<n> = 1 1063 + * CAM1<n> = 0 & CAM0<n> = 0 => always match i.e dontcare. 1064 + */ 1065 + if (kw_type == NPC_MCAM_KEY_X2) { 1066 + /* Clear mcam entry to avoid writes being suppressed by NPC */ 1067 + npc_cn20k_clear_mcam_entry(rvu, blkaddr, bank, mcam_idx); 1068 + npc_cn20k_config_kw_x2(rvu, mcam, blkaddr, 1069 + mcam_idx, intf, entry, 1070 + bank, kw_type, kw, req_kw_type); 1071 + /* Set 'action' */ 1072 + rvu_write64(rvu, blkaddr, 1073 + NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(mcam_idx, 1074 + bank, 0), 1075 + entry->action); 1076 + 1077 + /* Set 'action2' for inline receive */ 1078 + rvu_write64(rvu, blkaddr, 1079 + NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(mcam_idx, 1080 + bank, 2), 1081 + entry->action2); 1082 + 1083 + /* Set TAG 'action' */ 1084 + rvu_write64(rvu, blkaddr, 1085 + NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(mcam_idx, 1086 + bank, 1), 1087 + entry->vtag_action); 1088 + goto set_cfg; 1089 + } 1090 + 1091 + /* Clear mcam entry to avoid writes being suppressed by NPC */ 1092 + npc_cn20k_clear_mcam_entry(rvu, blkaddr, 0, mcam_idx); 1093 + npc_cn20k_clear_mcam_entry(rvu, blkaddr, 1, mcam_idx); 1094 + 1095 + npc_cn20k_config_kw_x4(rvu, mcam, blkaddr, 1096 + mcam_idx, intf, entry, 1097 + kw_type, req_kw_type); 1098 + for (bank = 0; bank < mcam->banks_per_entry; bank++) { 1099 + /* Set 'action' */ 1100 + rvu_write64(rvu, blkaddr, 1101 + NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(mcam_idx, 1102 + bank, 0), 1103 + entry->action); 1104 + 1105 + /* Set TAG 'action' */ 1106 + rvu_write64(rvu, blkaddr, 1107 + NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(mcam_idx, 1108 + bank, 1), 1109 + entry->vtag_action); 1110 + 1111 + /* Set 'action2' for inline receive */ 1112 + rvu_write64(rvu, blkaddr, 1113 + NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(mcam_idx, 1114 + bank, 2), 1115 + entry->action2); 1116 + } 1117 + 1118 + set_cfg: 1119 + /* TODO: */ 1120 + /* PF installing VF rule */ 1121 + npc_cn20k_set_mcam_bank_cfg(rvu, blkaddr, mcam_idx, bank, 1122 + kw_type, enable, hw_prio); 1123 + } 1124 + 1125 + void npc_cn20k_copy_mcam_entry(struct rvu *rvu, int blkaddr, u16 src, u16 dest) 1126 + { 1127 + struct npc_mcam *mcam = &rvu->hw->mcam; 1128 + u64 cfg, sreg, dreg, soff, doff; 1129 + u8 src_kwtype, dest_kwtype; 1130 + int bank, i, sb, db; 1131 + int dbank, sbank; 1132 + 1133 + dbank = npc_get_bank(mcam, dest); 1134 + sbank = npc_get_bank(mcam, src); 1135 + npc_mcam_idx_2_key_type(rvu, src, &src_kwtype); 1136 + npc_mcam_idx_2_key_type(rvu, dest, &dest_kwtype); 1137 + if (src_kwtype != dest_kwtype) 1138 + return; 1139 + 1140 + src &= (mcam->banksize - 1); 1141 + dest &= (mcam->banksize - 1); 1142 + 1143 + /* Copy INTF's, W0's, W1's, W2's, W3s CAM0 and CAM1 configuration */ 1144 + for (bank = 0; bank < mcam->banks_per_entry; bank++) { 1145 + sb = sbank + bank; 1146 + sreg = NPC_AF_CN20K_MCAMEX_BANKX_CAMX_INTF_EXT(src, sb, 0); 1147 + db = dbank + bank; 1148 + dreg = NPC_AF_CN20K_MCAMEX_BANKX_CAMX_INTF_EXT(dest, db, 0); 1149 + for (i = 0; i < 10; i++) { 1150 + cfg = rvu_read64(rvu, blkaddr, sreg + (i * 8)); 1151 + rvu_write64(rvu, blkaddr, dreg + (i * 8), cfg); 1152 + } 1153 + 1154 + /* Copy action */ 1155 + for (i = 0; i < 3; i++) { 1156 + soff = NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(src, 1157 + sb, i); 1158 + cfg = rvu_read64(rvu, blkaddr, soff); 1159 + 1160 + doff = NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(dest, db, 1161 + i); 1162 + rvu_write64(rvu, blkaddr, doff, cfg); 1163 + } 1164 + 1165 + /* Copy bank configuration */ 1166 + cfg = rvu_read64(rvu, blkaddr, 1167 + NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(src, sb)); 1168 + rvu_write64(rvu, blkaddr, 1169 + NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(dest, db), cfg); 1170 + if (src_kwtype == NPC_MCAM_KEY_X2) 1171 + break; 1172 + } 1173 + } 1174 + 1175 + static void npc_cn20k_fill_entryword(struct cn20k_mcam_entry *entry, int idx, 1176 + u64 cam0, u64 cam1) 1177 + { 1178 + entry->kw[idx] = cam1; 1179 + entry->kw_mask[idx] = cam1 ^ cam0; 1180 + } 1181 + 1182 + void npc_cn20k_read_mcam_entry(struct rvu *rvu, int blkaddr, u16 index, 1183 + struct cn20k_mcam_entry *entry, 1184 + u8 *intf, u8 *ena, u8 *hw_prio) 1185 + { 1186 + struct npc_mcam *mcam = &rvu->hw->mcam; 1187 + u64 cam0, cam1, bank_cfg, cfg; 1188 + int kw = 0, bank; 1189 + u8 kw_type; 1190 + 1191 + npc_mcam_idx_2_key_type(rvu, index, &kw_type); 1192 + 1193 + bank = npc_get_bank(mcam, index); 1194 + index &= (mcam->banksize - 1); 1195 + 1196 + cfg = rvu_read64(rvu, blkaddr, 1197 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_INTF_EXT(index, 1198 + bank, 1)) & 3; 1199 + *intf = cfg; 1200 + 1201 + bank_cfg = rvu_read64(rvu, blkaddr, 1202 + NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(index, bank)); 1203 + *ena = bank_cfg & 0x1; 1204 + *hw_prio = (bank_cfg & GENMASK_ULL(30, 24)) >> 24; 1205 + if (kw_type == NPC_MCAM_KEY_X2) { 1206 + cam1 = rvu_read64(rvu, blkaddr, 1207 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W0_EXT(index, 1208 + bank, 1209 + 1)); 1210 + cam0 = rvu_read64(rvu, blkaddr, 1211 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W0_EXT(index, 1212 + bank, 1213 + 0)); 1214 + npc_cn20k_fill_entryword(entry, kw, cam0, cam1); 1215 + 1216 + cam1 = rvu_read64(rvu, blkaddr, 1217 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W1_EXT(index, 1218 + bank, 1219 + 1)); 1220 + cam0 = rvu_read64(rvu, blkaddr, 1221 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W1_EXT(index, 1222 + bank, 1223 + 0)); 1224 + npc_cn20k_fill_entryword(entry, kw + 1, cam0, cam1); 1225 + 1226 + cam1 = rvu_read64(rvu, blkaddr, 1227 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W2_EXT(index, 1228 + bank, 1229 + 1)); 1230 + cam0 = rvu_read64(rvu, blkaddr, 1231 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W2_EXT(index, 1232 + bank, 1233 + 0)); 1234 + npc_cn20k_fill_entryword(entry, kw + 2, cam0, cam1); 1235 + 1236 + cam1 = rvu_read64(rvu, blkaddr, 1237 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W3_EXT(index, 1238 + bank, 1239 + 1)); 1240 + cam0 = rvu_read64(rvu, blkaddr, 1241 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W3_EXT(index, 1242 + bank, 1243 + 0)); 1244 + npc_cn20k_fill_entryword(entry, kw + 3, cam0, cam1); 1245 + goto read_action; 1246 + } 1247 + 1248 + for (bank = 0; bank < mcam->banks_per_entry; bank++, kw = kw + 4) { 1249 + cam1 = rvu_read64(rvu, blkaddr, 1250 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W0_EXT(index, 1251 + bank, 1252 + 1)); 1253 + cam0 = rvu_read64(rvu, blkaddr, 1254 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W0_EXT(index, 1255 + bank, 1256 + 0)); 1257 + npc_cn20k_fill_entryword(entry, kw, cam0, cam1); 1258 + 1259 + cam1 = rvu_read64(rvu, blkaddr, 1260 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W1_EXT(index, 1261 + bank, 1262 + 1)); 1263 + cam0 = rvu_read64(rvu, blkaddr, 1264 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W1_EXT(index, 1265 + bank, 1266 + 0)); 1267 + npc_cn20k_fill_entryword(entry, kw + 1, cam0, cam1); 1268 + 1269 + cam1 = rvu_read64(rvu, blkaddr, 1270 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W2_EXT(index, 1271 + bank, 1272 + 1)); 1273 + cam0 = rvu_read64(rvu, blkaddr, 1274 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W2_EXT(index, 1275 + bank, 1276 + 0)); 1277 + npc_cn20k_fill_entryword(entry, kw + 2, cam0, cam1); 1278 + 1279 + cam1 = rvu_read64(rvu, blkaddr, 1280 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W3_EXT(index, 1281 + bank, 1282 + 1)); 1283 + cam0 = rvu_read64(rvu, blkaddr, 1284 + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W3_EXT(index, 1285 + bank, 1286 + 0)); 1287 + npc_cn20k_fill_entryword(entry, kw + 3, cam0, cam1); 1288 + } 1289 + 1290 + read_action: 1291 + /* 'action' is set to same value for both bank '0' and '1'. 1292 + * Hence, reading bank '0' should be enough. 1293 + */ 1294 + cfg = rvu_read64(rvu, blkaddr, 1295 + NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(index, 0, 0)); 1296 + entry->action = cfg; 1297 + 1298 + cfg = rvu_read64(rvu, blkaddr, 1299 + NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(index, 0, 1)); 1300 + entry->vtag_action = cfg; 1301 + } 1302 + 1303 + int rvu_mbox_handler_npc_cn20k_mcam_write_entry(struct rvu *rvu, 1304 + struct npc_cn20k_mcam_write_entry_req *req, 1305 + struct msg_rsp *rsp) 1306 + { 1307 + struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, req->hdr.pcifunc); 1308 + struct npc_mcam *mcam = &rvu->hw->mcam; 1309 + u16 pcifunc = req->hdr.pcifunc; 1310 + int blkaddr, rc; 1311 + u8 nix_intf; 1312 + 1313 + req->entry = npc_cn20k_vidx2idx(req->entry); 1314 + 1315 + blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); 1316 + if (blkaddr < 0) 1317 + return NPC_MCAM_INVALID_REQ; 1318 + 1319 + mutex_lock(&mcam->lock); 1320 + rc = npc_mcam_verify_entry(mcam, pcifunc, req->entry); 1321 + if (rc) 1322 + goto exit; 1323 + 1324 + if (!is_npc_interface_valid(rvu, req->intf)) { 1325 + rc = NPC_MCAM_INVALID_REQ; 1326 + goto exit; 1327 + } 1328 + 1329 + if (is_npc_intf_tx(req->intf)) 1330 + nix_intf = pfvf->nix_tx_intf; 1331 + else 1332 + nix_intf = pfvf->nix_rx_intf; 1333 + 1334 + /* For AF installed rules, the nix_intf should be set to target NIX */ 1335 + if (is_pffunc_af(req->hdr.pcifunc)) 1336 + nix_intf = req->intf; 1337 + 1338 + npc_cn20k_config_mcam_entry(rvu, blkaddr, req->entry, nix_intf, 1339 + &req->entry_data, req->enable_entry, 1340 + req->hw_prio, req->req_kw_type); 1341 + 1342 + rc = 0; 1343 + exit: 1344 + mutex_unlock(&mcam->lock); 1345 + return rc; 1346 + } 1347 + 1348 + int rvu_mbox_handler_npc_cn20k_mcam_read_entry(struct rvu *rvu, 1349 + struct npc_mcam_read_entry_req *req, 1350 + struct npc_cn20k_mcam_read_entry_rsp *rsp) 1351 + { 1352 + struct npc_mcam *mcam = &rvu->hw->mcam; 1353 + u16 pcifunc = req->hdr.pcifunc; 1354 + int blkaddr, rc; 1355 + 1356 + req->entry = npc_cn20k_vidx2idx(req->entry); 1357 + 1358 + blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); 1359 + if (blkaddr < 0) 1360 + return NPC_MCAM_INVALID_REQ; 1361 + 1362 + mutex_lock(&mcam->lock); 1363 + rc = npc_mcam_verify_entry(mcam, pcifunc, req->entry); 1364 + if (!rc) 1365 + npc_cn20k_read_mcam_entry(rvu, blkaddr, req->entry, 1366 + &rsp->entry_data, &rsp->intf, 1367 + &rsp->enable, &rsp->hw_prio); 1368 + 1369 + mutex_unlock(&mcam->lock); 1370 + return rc; 1371 + } 1372 + 1373 + int rvu_mbox_handler_npc_cn20k_mcam_alloc_and_write_entry(struct rvu *rvu, 1374 + struct npc_cn20k_mcam_alloc_and_write_entry_req *req, 1375 + struct npc_mcam_alloc_and_write_entry_rsp *rsp) 1376 + { 1377 + struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, req->hdr.pcifunc); 1378 + struct npc_mcam_alloc_entry_req entry_req; 1379 + struct npc_mcam_alloc_entry_rsp entry_rsp; 1380 + struct npc_mcam *mcam = &rvu->hw->mcam; 1381 + u16 entry = NPC_MCAM_ENTRY_INVALID; 1382 + int blkaddr, rc; 1383 + u8 nix_intf; 1384 + 1385 + blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); 1386 + if (blkaddr < 0) 1387 + return NPC_MCAM_INVALID_REQ; 1388 + 1389 + if (!is_npc_interface_valid(rvu, req->intf)) 1390 + return NPC_MCAM_INVALID_REQ; 1391 + 1392 + /* Try to allocate a MCAM entry */ 1393 + entry_req.hdr.pcifunc = req->hdr.pcifunc; 1394 + entry_req.contig = true; 1395 + entry_req.ref_prio = req->ref_prio; 1396 + entry_req.ref_entry = req->ref_entry; 1397 + entry_req.count = 1; 1398 + entry_req.virt = req->virt; 1399 + 1400 + rc = rvu_mbox_handler_npc_mcam_alloc_entry(rvu, 1401 + &entry_req, &entry_rsp); 1402 + if (rc) 1403 + return rc; 1404 + 1405 + if (!entry_rsp.count) 1406 + return NPC_MCAM_ALLOC_FAILED; 1407 + 1408 + /* entry_req.count is 1, so single entry is allocated */ 1409 + entry = npc_cn20k_vidx2idx(entry_rsp.entry); 1410 + 1411 + mutex_lock(&mcam->lock); 1412 + 1413 + if (is_npc_intf_tx(req->intf)) 1414 + nix_intf = pfvf->nix_tx_intf; 1415 + else 1416 + nix_intf = pfvf->nix_rx_intf; 1417 + 1418 + npc_cn20k_config_mcam_entry(rvu, blkaddr, entry, nix_intf, 1419 + &req->entry_data, req->enable_entry, 1420 + req->hw_prio, req->req_kw_type); 1421 + 1422 + mutex_unlock(&mcam->lock); 1423 + 1424 + rsp->entry = entry_rsp.entry; 1425 + return 0; 1426 + } 1427 + 1428 + static int rvu_npc_get_base_steer_rule_type(struct rvu *rvu, u16 pcifunc) 1429 + { 1430 + if (is_lbk_vf(rvu, pcifunc)) 1431 + return NIXLF_PROMISC_ENTRY; 1432 + 1433 + return NIXLF_UCAST_ENTRY; 1434 + } 1435 + 1436 + int rvu_mbox_handler_npc_cn20k_read_base_steer_rule(struct rvu *rvu, 1437 + struct msg_req *req, 1438 + struct npc_cn20k_mcam_read_base_rule_rsp *rsp) 1439 + { 1440 + struct npc_mcam *mcam = &rvu->hw->mcam; 1441 + int index, blkaddr, nixlf, rc = 0; 1442 + u16 pcifunc = req->hdr.pcifunc; 1443 + u8 intf, enable, hw_prio; 1444 + struct rvu_pfvf *pfvf; 1445 + int rl_type; 1446 + 1447 + blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); 1448 + if (blkaddr < 0) 1449 + return NPC_MCAM_INVALID_REQ; 1450 + 1451 + /* Return the channel number in case of PF */ 1452 + if (!(pcifunc & RVU_PFVF_FUNC_MASK)) { 1453 + pfvf = rvu_get_pfvf(rvu, pcifunc); 1454 + rsp->entry.kw[0] = pfvf->rx_chan_base; 1455 + rsp->entry.kw_mask[0] = 0xFFFULL; 1456 + goto out; 1457 + } 1458 + 1459 + /* Find the pkt steering rule installed by PF to this VF */ 1460 + mutex_lock(&mcam->lock); 1461 + for (index = 0; index < mcam->bmap_entries; index++) { 1462 + if (mcam->entry2target_pffunc[index] == pcifunc) 1463 + goto read_entry; 1464 + } 1465 + 1466 + rc = nix_get_nixlf(rvu, pcifunc, &nixlf, NULL); 1467 + if (rc < 0) { 1468 + mutex_unlock(&mcam->lock); 1469 + goto out; 1470 + } 1471 + 1472 + rl_type = rvu_npc_get_base_steer_rule_type(rvu, pcifunc); 1473 + 1474 + /* Read the default ucast entry if there is no pkt steering rule */ 1475 + index = npc_get_nixlf_mcam_index(mcam, pcifunc, nixlf, rl_type); 1476 + if (index < 0) { 1477 + mutex_unlock(&mcam->lock); 1478 + goto out; 1479 + } 1480 + 1481 + read_entry: 1482 + /* Read the mcam entry */ 1483 + npc_cn20k_read_mcam_entry(rvu, blkaddr, index, 1484 + &rsp->entry, &intf, 1485 + &enable, &hw_prio); 1486 + mutex_unlock(&mcam->lock); 1487 + out: 1488 + return rc; 1489 + } 1490 + 1491 + static u8 npc_map2cn20k_flag(u8 flag) 1492 + { 1493 + switch (flag) { 1494 + case NPC_F_LC_U_IP_FRAG: 1495 + return NPC_CN20K_F_LC_L_IP_FRAG; 1496 + 1497 + case NPC_F_LC_U_IP6_FRAG: 1498 + return NPC_CN20K_F_LC_L_IP6_FRAG; 1499 + 1500 + case NPC_F_LC_L_6TO4: 1501 + return NPC_CN20K_F_LC_L_6TO4; 1502 + 1503 + case NPC_F_LC_L_MPLS_IN_IP: 1504 + return NPC_CN20K_F_LC_U_MPLS_IN_IP; 1505 + 1506 + case NPC_F_LC_L_IP6_TUN_IP6: 1507 + return NPC_CN20K_F_LC_U_IP6_TUN_IP6; 1508 + 1509 + case NPC_F_LC_L_IP6_MPLS_IN_IP: 1510 + return NPC_CN20K_F_LC_U_IP6_MPLS_IN_IP; 1511 + 1512 + default: 1513 + break; 1514 + } 1515 + 1516 + WARN(1, "%s: Invalid flag=%u\n", __func__, flag); 1517 + return 0xff; 1518 + } 1519 + 1520 + void 1521 + npc_cn20k_update_action_entries_n_flags(struct rvu *rvu, 1522 + struct npc_kpu_profile_adapter *pfl) 1523 + { 1524 + struct npc_kpu_profile_action *action; 1525 + int entries, ltype; 1526 + u8 flags, val; 1527 + 1528 + for (int i = 0; i < pfl->kpus; i++) { 1529 + action = pfl->kpu[i].action; 1530 + entries = pfl->kpu[i].action_entries; 1531 + 1532 + for (int j = 0; j < entries; j++) { 1533 + if (action[j].lid != NPC_LID_LC) 1534 + continue; 1535 + 1536 + ltype = action[j].ltype; 1537 + 1538 + if (ltype != NPC_LT_LC_IP && 1539 + ltype != NPC_LT_LC_IP6 && 1540 + ltype != NPC_LT_LC_IP_OPT && 1541 + ltype != NPC_LT_LC_IP6_EXT) 1542 + continue; 1543 + 1544 + flags = action[j].flags; 1545 + 1546 + switch (flags) { 1547 + case NPC_F_LC_U_IP_FRAG: 1548 + case NPC_F_LC_U_IP6_FRAG: 1549 + case NPC_F_LC_L_6TO4: 1550 + case NPC_F_LC_L_MPLS_IN_IP: 1551 + case NPC_F_LC_L_IP6_TUN_IP6: 1552 + case NPC_F_LC_L_IP6_MPLS_IN_IP: 1553 + val = npc_map2cn20k_flag(flags); 1554 + if (val == 0xFF) { 1555 + dev_err(rvu->dev, 1556 + "%s: Error to get flag value\n", 1557 + __func__); 1558 + return; 1559 + } 1560 + 1561 + action[j].flags = val; 1562 + break; 1563 + default: 1564 + break; 1565 + } 1566 + } 1567 + } 1568 + } 1569 + 1570 + int npc_cn20k_apply_custom_kpu(struct rvu *rvu, 1571 + struct npc_kpu_profile_adapter *profile) 1572 + { 1573 + size_t hdr_sz = sizeof(struct npc_cn20k_kpu_profile_fwdata); 1574 + struct npc_cn20k_kpu_profile_fwdata *fw = rvu->kpu_fwdata; 1575 + struct npc_kpu_profile_action *action; 1576 + struct npc_kpu_profile_cam *cam; 1577 + struct npc_kpu_fwdata *fw_kpu; 1578 + size_t offset = 0; 1579 + u16 kpu, entry; 1580 + int entries; 1581 + 1582 + hdr_sz = sizeof(struct npc_cn20k_kpu_profile_fwdata); 1583 + 1584 + if (rvu->kpu_fwdata_sz < hdr_sz) { 1585 + dev_warn(rvu->dev, "Invalid KPU profile size\n"); 1586 + return -EINVAL; 1587 + } 1588 + 1589 + if (le64_to_cpu(fw->signature) != KPU_SIGN) { 1590 + dev_warn(rvu->dev, "Invalid KPU profile signature %llx\n", 1591 + fw->signature); 1592 + return -EINVAL; 1593 + } 1594 + 1595 + /* Verify if the using known profile structure */ 1596 + if (NPC_KPU_VER_MAJ(profile->version) > 1597 + NPC_KPU_VER_MAJ(NPC_KPU_PROFILE_VER)) { 1598 + dev_warn(rvu->dev, "Not supported Major version: %d > %d\n", 1599 + NPC_KPU_VER_MAJ(profile->version), 1600 + NPC_KPU_VER_MAJ(NPC_KPU_PROFILE_VER)); 1601 + return -EINVAL; 1602 + } 1603 + 1604 + /* Verify if profile is aligned with the required kernel changes */ 1605 + if (NPC_KPU_VER_MIN(profile->version) < 1606 + NPC_KPU_VER_MIN(NPC_KPU_PROFILE_VER)) { 1607 + dev_warn(rvu->dev, 1608 + "Invalid KPU profile version: %d.%d.%d expected version <= %d.%d.%d\n", 1609 + NPC_KPU_VER_MAJ(profile->version), 1610 + NPC_KPU_VER_MIN(profile->version), 1611 + NPC_KPU_VER_PATCH(profile->version), 1612 + NPC_KPU_VER_MAJ(NPC_KPU_PROFILE_VER), 1613 + NPC_KPU_VER_MIN(NPC_KPU_PROFILE_VER), 1614 + NPC_KPU_VER_PATCH(NPC_KPU_PROFILE_VER)); 1615 + return -EINVAL; 1616 + } 1617 + 1618 + /* Verify if profile fits the HW */ 1619 + if (fw->kpus > profile->kpus) { 1620 + dev_warn(rvu->dev, "Not enough KPUs: %d > %ld\n", fw->kpus, 1621 + profile->kpus); 1622 + return -EINVAL; 1623 + } 1624 + 1625 + profile->mcam_kex_prfl.mkex_extr = &fw->mkex; 1626 + if (profile->mcam_kex_prfl.mkex_extr->mkex_sign != MKEX_CN20K_SIGN) { 1627 + dev_warn(rvu->dev, "Invalid MKEX profile signature:%llx\n", 1628 + profile->mcam_kex_prfl.mkex_extr->mkex_sign); 1629 + return -EINVAL; 1630 + } 1631 + 1632 + profile->custom = 1; 1633 + profile->name = fw->name; 1634 + profile->version = le64_to_cpu(fw->version); 1635 + profile->lt_def = &fw->lt_def; 1636 + 1637 + for (kpu = 0; kpu < fw->kpus; kpu++) { 1638 + fw_kpu = (struct npc_kpu_fwdata *)(fw->data + offset); 1639 + if (fw_kpu->entries > KPU_CN20K_MAX_CST_ENT) 1640 + dev_warn(rvu->dev, 1641 + "Too many custom entries on KPU%d: %d > %d\n", 1642 + kpu, fw_kpu->entries, KPU_CN20K_MAX_CST_ENT); 1643 + entries = min(fw_kpu->entries, KPU_CN20K_MAX_CST_ENT); 1644 + cam = (struct npc_kpu_profile_cam *)fw_kpu->data; 1645 + offset += sizeof(*fw_kpu) + fw_kpu->entries * sizeof(*cam); 1646 + action = (struct npc_kpu_profile_action *)(fw->data + offset); 1647 + offset += fw_kpu->entries * sizeof(*action); 1648 + if (rvu->kpu_fwdata_sz < hdr_sz + offset) { 1649 + dev_warn(rvu->dev, 1650 + "Profile size mismatch on KPU%i parsing.\n", 1651 + kpu + 1); 1652 + return -EINVAL; 1653 + } 1654 + 1655 + for (entry = 0; entry < entries; entry++) { 1656 + profile->kpu[kpu].cam[entry] = cam[entry]; 1657 + profile->kpu[kpu].action[entry] = action[entry]; 1658 + } 1659 + } 1660 + npc_cn20k_update_action_entries_n_flags(rvu, profile); 1661 + 1662 + return 0; 1663 + } 1664 + 1665 + int npc_mcam_idx_2_key_type(struct rvu *rvu, u16 mcam_idx, u8 *key_type) 1666 + { 1667 + struct npc_subbank *sb; 1668 + int bank_off, sb_id; 1669 + 1670 + /* mcam_idx should be less than (2 * bank depth) */ 1671 + if (mcam_idx >= npc_priv.bank_depth * 2) { 1672 + dev_err(rvu->dev, "%s: bad params\n", 1673 + __func__); 1674 + return -EINVAL; 1675 + } 1676 + 1677 + /* find mcam offset per bank */ 1678 + bank_off = mcam_idx & (npc_priv.bank_depth - 1); 1679 + 1680 + /* Find subbank id */ 1681 + sb_id = bank_off / npc_priv.subbank_depth; 1682 + 1683 + /* Check if subbank id is more than maximum 1684 + * number of subbanks available 1685 + */ 1686 + if (sb_id >= npc_priv.num_subbanks) { 1687 + dev_err(rvu->dev, "%s: invalid subbank %d\n", 1688 + __func__, sb_id); 1689 + return -EINVAL; 1690 + } 1691 + 1692 + sb = &npc_priv.sb[sb_id]; 1693 + 1694 + *key_type = sb->key_type; 1695 + 1696 + return 0; 1697 + } 1698 + 1699 + static int npc_subbank_idx_2_mcam_idx(struct rvu *rvu, struct npc_subbank *sb, 1700 + u16 sub_off, u16 *mcam_idx) 1701 + { 1702 + int off, bot; 1703 + 1704 + /* for x4 section, maximum allowed subbank index = 1705 + * subsection depth - 1 1706 + */ 1707 + if (sb->key_type == NPC_MCAM_KEY_X4 && 1708 + sub_off >= npc_priv.subbank_depth) { 1709 + dev_err(rvu->dev, 1710 + "%s: Failed to get mcam idx (x4) sb->idx=%u sub_off=%u", 1711 + __func__, sb->idx, sub_off); 1712 + return -EINVAL; 1713 + } 1714 + 1715 + /* for x2 section, maximum allowed subbank index = 1716 + * 2 * subsection depth - 1 1717 + */ 1718 + if (sb->key_type == NPC_MCAM_KEY_X2 && 1719 + sub_off >= npc_priv.subbank_depth * 2) { 1720 + dev_err(rvu->dev, 1721 + "%s: Failed to get mcam idx (x2) sb->idx=%u sub_off=%u", 1722 + __func__, sb->idx, sub_off); 1723 + return -EINVAL; 1724 + } 1725 + 1726 + /* Find subbank offset from respective subbank (w.r.t bank) */ 1727 + off = sub_off & (npc_priv.subbank_depth - 1); 1728 + 1729 + /* if subsection idx is in bank1, add bank depth, 1730 + * which is part of sb->b1b 1731 + */ 1732 + bot = sub_off >= npc_priv.subbank_depth ? sb->b1b : sb->b0b; 1733 + 1734 + *mcam_idx = bot + off; 1735 + return 0; 1736 + } 1737 + 1738 + static int npc_mcam_idx_2_subbank_idx(struct rvu *rvu, u16 mcam_idx, 1739 + struct npc_subbank **sb, 1740 + int *sb_off) 1741 + { 1742 + int bank_off, sb_id; 1743 + 1744 + /* mcam_idx should be less than (2 * bank depth) */ 1745 + if (mcam_idx >= npc_priv.bank_depth * 2) { 1746 + dev_err(rvu->dev, "%s: Invalid mcam idx %u\n", 1747 + __func__, mcam_idx); 1748 + return -EINVAL; 1749 + } 1750 + 1751 + /* find mcam offset per bank */ 1752 + bank_off = mcam_idx & (npc_priv.bank_depth - 1); 1753 + 1754 + /* Find subbank id */ 1755 + sb_id = bank_off / npc_priv.subbank_depth; 1756 + 1757 + /* Check if subbank id is more than maximum 1758 + * number of subbanks available 1759 + */ 1760 + if (sb_id >= npc_priv.num_subbanks) { 1761 + dev_err(rvu->dev, "%s: invalid subbank %d\n", 1762 + __func__, sb_id); 1763 + return -EINVAL; 1764 + } 1765 + 1766 + *sb = &npc_priv.sb[sb_id]; 1767 + 1768 + /* Subbank offset per bank */ 1769 + *sb_off = bank_off % npc_priv.subbank_depth; 1770 + 1771 + /* Index in a subbank should add subbank depth 1772 + * if it is in bank1 1773 + */ 1774 + if (mcam_idx >= npc_priv.bank_depth) 1775 + *sb_off += npc_priv.subbank_depth; 1776 + 1777 + return 0; 1778 + } 1779 + 1780 + static int __npc_subbank_contig_alloc(struct rvu *rvu, 1781 + struct npc_subbank *sb, 1782 + int key_type, int sidx, 1783 + int eidx, int prio, 1784 + int count, int t, int b, 1785 + unsigned long *bmap, 1786 + u16 *save) 1787 + { 1788 + int k, offset, delta = 0; 1789 + int cnt = 0, sbd; 1790 + 1791 + sbd = npc_priv.subbank_depth; 1792 + 1793 + if (sidx >= npc_priv.bank_depth) 1794 + delta = sbd; 1795 + 1796 + switch (prio) { 1797 + case NPC_MCAM_LOWER_PRIO: 1798 + case NPC_MCAM_ANY_PRIO: 1799 + /* Find an area of size 'count' from sidx to eidx */ 1800 + offset = bitmap_find_next_zero_area(bmap, sbd, sidx - b, 1801 + count, 0); 1802 + 1803 + if (offset >= sbd) { 1804 + dev_err(rvu->dev, 1805 + "%s: Could not find contiguous(%d) entries\n", 1806 + __func__, count); 1807 + return -EFAULT; 1808 + } 1809 + 1810 + dev_dbg(rvu->dev, 1811 + "%s: sidx=%d eidx=%d t=%d b=%d offset=%d count=%d delta=%d\n", 1812 + __func__, sidx, eidx, t, b, offset, 1813 + count, delta); 1814 + 1815 + for (cnt = 0; cnt < count; cnt++) 1816 + save[cnt] = offset + cnt + delta; 1817 + 1818 + break; 1819 + 1820 + case NPC_MCAM_HIGHER_PRIO: 1821 + /* Find an area of 'count' from eidx to sidx */ 1822 + for (k = eidx - b; cnt < count && k >= (sidx - b); k--) { 1823 + /* If an intermediate slot is not free, 1824 + * reset the counter (cnt) to zero as 1825 + * request is for contiguous. 1826 + */ 1827 + if (test_bit(k, bmap)) { 1828 + cnt = 0; 1829 + continue; 1830 + } 1831 + 1832 + save[cnt++] = k + delta; 1833 + } 1834 + break; 1835 + } 1836 + 1837 + /* Found 'count' number of free slots */ 1838 + if (cnt == count) 1839 + return 0; 1840 + 1841 + dev_dbg(rvu->dev, 1842 + "%s: Could not find contiguous(%d) entries in subbank=%u\n", 1843 + __func__, count, sb->idx); 1844 + return -EFAULT; 1845 + } 1846 + 1847 + static int __npc_subbank_non_contig_alloc(struct rvu *rvu, 1848 + struct npc_subbank *sb, 1849 + int key_type, int sidx, 1850 + int eidx, int prio, 1851 + int t, int b, 1852 + unsigned long *bmap, 1853 + int count, u16 *save, 1854 + bool max_alloc, int *alloc_cnt) 1855 + { 1856 + unsigned long index; 1857 + int cnt = 0, delta; 1858 + int k, sbd; 1859 + 1860 + sbd = npc_priv.subbank_depth; 1861 + delta = sidx >= npc_priv.bank_depth ? sbd : 0; 1862 + 1863 + switch (prio) { 1864 + /* Find an area of size 'count' from sidx to eidx */ 1865 + case NPC_MCAM_LOWER_PRIO: 1866 + case NPC_MCAM_ANY_PRIO: 1867 + index = find_next_zero_bit(bmap, sbd, sidx - b); 1868 + if (index >= sbd) { 1869 + dev_err(rvu->dev, 1870 + "%s: Error happened to alloc %u, bitmap_weight=%u, sb->idx=%u\n", 1871 + __func__, count, 1872 + bitmap_weight(bmap, sbd), 1873 + sb->idx); 1874 + break; 1875 + } 1876 + 1877 + for (k = index; cnt < count && k <= (eidx - b); k++) { 1878 + /* Skip used slots */ 1879 + if (test_bit(k, bmap)) 1880 + continue; 1881 + 1882 + save[cnt++] = k + delta; 1883 + } 1884 + break; 1885 + 1886 + /* Find an area of 'count' from eidx to sidx */ 1887 + case NPC_MCAM_HIGHER_PRIO: 1888 + for (k = eidx - b; cnt < count && k >= (sidx - b); k--) { 1889 + /* Skip used slots */ 1890 + if (test_bit(k, bmap)) 1891 + continue; 1892 + 1893 + save[cnt++] = k + delta; 1894 + } 1895 + break; 1896 + } 1897 + 1898 + /* Update allocated 'cnt' to alloc_cnt */ 1899 + *alloc_cnt = cnt; 1900 + 1901 + /* Successfully allocated requested count slots */ 1902 + if (cnt == count) 1903 + return 0; 1904 + 1905 + /* Allocation successful for cnt < count */ 1906 + if (max_alloc && cnt > 0) 1907 + return 0; 1908 + 1909 + dev_dbg(rvu->dev, 1910 + "%s: Could not find non contiguous entries(%u) in subbank(%u) cnt=%d max_alloc=%d\n", 1911 + __func__, count, sb->idx, cnt, max_alloc); 1912 + 1913 + return -EFAULT; 1914 + } 1915 + 1916 + static void __npc_subbank_sboff_2_off(struct rvu *rvu, struct npc_subbank *sb, 1917 + int sb_off, unsigned long **bmap, 1918 + int *off) 1919 + { 1920 + int sbd; 1921 + 1922 + sbd = npc_priv.subbank_depth; 1923 + 1924 + *off = sb_off & (sbd - 1); 1925 + *bmap = (sb_off >= sbd) ? sb->b1map : sb->b0map; 1926 + } 1927 + 1928 + /* set/clear bitmap */ 1929 + static bool __npc_subbank_mark_slot(struct rvu *rvu, 1930 + struct npc_subbank *sb, 1931 + int sb_off, bool set) 1932 + { 1933 + unsigned long *bmap; 1934 + int off; 1935 + 1936 + /* if sb_off >= subbank.depth, then slots are in 1937 + * bank1 1938 + */ 1939 + __npc_subbank_sboff_2_off(rvu, sb, sb_off, &bmap, &off); 1940 + 1941 + dev_dbg(rvu->dev, 1942 + "%s: Marking set=%d sb_off=%d sb->idx=%d off=%d\n", 1943 + __func__, set, sb_off, sb->idx, off); 1944 + 1945 + if (set) { 1946 + /* Slot is already used */ 1947 + if (test_bit(off, bmap)) 1948 + return false; 1949 + 1950 + sb->free_cnt--; 1951 + set_bit(off, bmap); 1952 + return true; 1953 + } 1954 + 1955 + /* Slot is already free */ 1956 + if (!test_bit(off, bmap)) 1957 + return false; 1958 + 1959 + sb->free_cnt++; 1960 + clear_bit(off, bmap); 1961 + return true; 1962 + } 1963 + 1964 + static int __npc_subbank_mark_free(struct rvu *rvu, struct npc_subbank *sb) 1965 + { 1966 + int rc, blkaddr; 1967 + 1968 + sb->flags = NPC_SUBBANK_FLAG_FREE; 1969 + sb->key_type = 0; 1970 + 1971 + bitmap_clear(sb->b0map, 0, npc_priv.subbank_depth); 1972 + bitmap_clear(sb->b1map, 0, npc_priv.subbank_depth); 1973 + 1974 + if (!xa_erase(&npc_priv.xa_sb_used, sb->arr_idx)) { 1975 + dev_err(rvu->dev, 1976 + "%s: Error to delete from xa_sb_used array\n", 1977 + __func__); 1978 + return -EFAULT; 1979 + } 1980 + 1981 + rc = xa_insert(&npc_priv.xa_sb_free, sb->arr_idx, 1982 + xa_mk_value(sb->idx), GFP_KERNEL); 1983 + if (rc) { 1984 + rc = xa_insert(&npc_priv.xa_sb_used, sb->arr_idx, 1985 + xa_mk_value(sb->idx), GFP_KERNEL); 1986 + if (rc) 1987 + dev_err(rvu->dev, 1988 + "%s: Failed to roll back sb(%u) arr_idx=%d\n", 1989 + __func__, sb->idx, sb->arr_idx); 1990 + 1991 + dev_err(rvu->dev, 1992 + "%s: Error to add sb(%u) to xa_sb_free array at arr_idx=%d\n", 1993 + __func__, sb->idx, sb->arr_idx); 1994 + return rc; 1995 + } 1996 + 1997 + blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); 1998 + rvu_write64(rvu, blkaddr, 1999 + NPC_AF_MCAM_SECTIONX_CFG_EXT(sb->idx), 2000 + NPC_MCAM_KEY_X2); 2001 + 2002 + return rc; 2003 + } 2004 + 2005 + static int __npc_subbank_mark_used(struct rvu *rvu, struct npc_subbank *sb, 2006 + int key_type) 2007 + { 2008 + int rc; 2009 + 2010 + sb->flags = NPC_SUBBANK_FLAG_USED; 2011 + sb->key_type = key_type; 2012 + if (key_type == NPC_MCAM_KEY_X4) 2013 + sb->free_cnt = npc_priv.subbank_depth; 2014 + else 2015 + sb->free_cnt = 2 * npc_priv.subbank_depth; 2016 + 2017 + bitmap_clear(sb->b0map, 0, npc_priv.subbank_depth); 2018 + bitmap_clear(sb->b1map, 0, npc_priv.subbank_depth); 2019 + 2020 + if (!xa_erase(&npc_priv.xa_sb_free, sb->arr_idx)) { 2021 + dev_err(rvu->dev, 2022 + "%s: Error to delete from xa_sb_free array\n", 2023 + __func__); 2024 + return -EFAULT; 2025 + } 2026 + 2027 + rc = xa_insert(&npc_priv.xa_sb_used, sb->arr_idx, 2028 + xa_mk_value(sb->idx), GFP_KERNEL); 2029 + if (rc) 2030 + dev_err(rvu->dev, 2031 + "%s: Error to add to xa_sb_used array\n", __func__); 2032 + 2033 + return rc; 2034 + } 2035 + 2036 + static bool __npc_subbank_free(struct rvu *rvu, struct npc_subbank *sb, 2037 + u16 sb_off) 2038 + { 2039 + bool deleted = false; 2040 + unsigned long *bmap; 2041 + int rc, off; 2042 + 2043 + deleted = __npc_subbank_mark_slot(rvu, sb, sb_off, false); 2044 + if (!deleted) 2045 + goto done; 2046 + 2047 + __npc_subbank_sboff_2_off(rvu, sb, sb_off, &bmap, &off); 2048 + 2049 + /* Check whether we can mark whole subbank as free */ 2050 + if (sb->key_type == NPC_MCAM_KEY_X4) { 2051 + if (sb->free_cnt < npc_priv.subbank_depth) 2052 + goto done; 2053 + } else { 2054 + if (sb->free_cnt < 2 * npc_priv.subbank_depth) 2055 + goto done; 2056 + } 2057 + 2058 + /* All slots in subbank are unused. Mark the subbank as free 2059 + * and add to free pool 2060 + */ 2061 + rc = __npc_subbank_mark_free(rvu, sb); 2062 + if (rc) 2063 + dev_err(rvu->dev, "%s: Error to free subbank\n", __func__); 2064 + 2065 + done: 2066 + return deleted; 2067 + } 2068 + 2069 + static int 2070 + npc_subbank_free(struct rvu *rvu, struct npc_subbank *sb, u16 sb_off) 2071 + { 2072 + bool deleted; 2073 + 2074 + mutex_lock(&sb->lock); 2075 + deleted = __npc_subbank_free(rvu, sb, sb_off); 2076 + mutex_unlock(&sb->lock); 2077 + 2078 + return deleted ? 0 : -EFAULT; 2079 + } 2080 + 2081 + static int __npc_subbank_alloc(struct rvu *rvu, struct npc_subbank *sb, 2082 + int key_type, int ref, int limit, int prio, 2083 + bool contig, int count, u16 *mcam_idx, 2084 + int idx_sz, bool max_alloc, int *alloc_cnt) 2085 + { 2086 + int cnt, t, b, i, blkaddr; 2087 + bool new_sub_bank = false; 2088 + unsigned long *bmap; 2089 + u16 *save = NULL; 2090 + int sidx, eidx; 2091 + bool diffbank; 2092 + int bw, bfree; 2093 + int rc = 0; 2094 + bool ret; 2095 + 2096 + /* Check if enough space is there to return requested number of 2097 + * mcam indexes in case of contiguous allocation 2098 + */ 2099 + if (!max_alloc && count > idx_sz) { 2100 + dev_err(rvu->dev, 2101 + "%s: Less space, count=%d idx_sz=%d sb_id=%d\n", 2102 + __func__, count, idx_sz, sb->idx); 2103 + return -ENOSPC; 2104 + } 2105 + 2106 + /* Allocation on multiple subbank is not supported by this function. 2107 + * it means that ref and limit should be on same subbank. 2108 + * 2109 + * ref and limit values should be validated w.r.t prio as below. 2110 + * say ref = 100, limit = 200, 2111 + * if NPC_MCAM_LOWER_PRIO, allocate index 100 2112 + * if NPC_MCAM_HIGHER_PRIO, below sanity test returns error. 2113 + * if NPC_MCAM_ANY_PRIO, allocate index 100 2114 + * 2115 + * say ref = 200, limit = 100 2116 + * if NPC_MCAM_LOWER_PRIO, below sanity test returns error. 2117 + * if NPC_MCAM_HIGHER_PRIO, allocate index 200 2118 + * if NPC_MCAM_ANY_PRIO, allocate index 100 2119 + * 2120 + * Please note that NPC_MCAM_ANY_PRIO does not have any restriction 2121 + * on "ref" and "limit" values. ie, ref > limit and limit > ref 2122 + * are valid cases. 2123 + */ 2124 + if ((prio == NPC_MCAM_LOWER_PRIO && ref > limit) || 2125 + (prio == NPC_MCAM_HIGHER_PRIO && ref < limit)) { 2126 + dev_err(rvu->dev, "%s: Wrong ref_enty(%d) or limit(%d)\n", 2127 + __func__, ref, limit); 2128 + return -EINVAL; 2129 + } 2130 + 2131 + /* x4 indexes are from 0 to bank size as it combines two x2 banks */ 2132 + if (key_type == NPC_MCAM_KEY_X4 && 2133 + (ref >= npc_priv.bank_depth || limit >= npc_priv.bank_depth)) { 2134 + dev_err(rvu->dev, 2135 + "%s: Wrong ref_enty(%d) or limit(%d) for x4\n", 2136 + __func__, ref, limit); 2137 + return -EINVAL; 2138 + } 2139 + 2140 + /* This function is called either bank0 or bank1 portion of a subbank. 2141 + * so ref and limit should be on same bank. 2142 + */ 2143 + diffbank = !!((ref & npc_priv.bank_depth) ^ 2144 + (limit & npc_priv.bank_depth)); 2145 + if (diffbank) { 2146 + dev_err(rvu->dev, 2147 + "%s: request ref and limit should be from same bank\n", 2148 + __func__); 2149 + return -EINVAL; 2150 + } 2151 + 2152 + sidx = min_t(int, limit, ref); 2153 + eidx = max_t(int, limit, ref); 2154 + 2155 + /* Find total number of slots available; both used and free */ 2156 + cnt = eidx - sidx + 1; 2157 + if (contig && cnt < count) { 2158 + dev_err(rvu->dev, 2159 + "%s: Wrong ref_enty(%d) or limit(%d) for count(%d)\n", 2160 + __func__, ref, limit, count); 2161 + return -EINVAL; 2162 + } 2163 + 2164 + /* If subbank is free, check if requested number of indexes is less than 2165 + * or equal to mcam entries available in the subbank if contig. 2166 + */ 2167 + if (sb->flags & NPC_SUBBANK_FLAG_FREE) { 2168 + if (contig && count > npc_priv.subbank_depth) { 2169 + dev_err(rvu->dev, "%s: Less number of entries\n", 2170 + __func__); 2171 + return -ENOSPC; 2172 + } 2173 + 2174 + new_sub_bank = true; 2175 + goto process; 2176 + } 2177 + 2178 + /* Flag should be set for all used subbanks */ 2179 + WARN_ONCE(!(sb->flags & NPC_SUBBANK_FLAG_USED), 2180 + "Used flag is not set(%#x)\n", sb->flags); 2181 + 2182 + /* If subbank key type does not match with requested key_type, 2183 + * return error 2184 + */ 2185 + if (sb->key_type != key_type) { 2186 + dev_dbg(rvu->dev, "%s: subbank key_type mismatch\n", __func__); 2187 + return -EINVAL; 2188 + } 2189 + 2190 + process: 2191 + /* if ref or limit >= npc_priv.bank_depth, index are in bank1. 2192 + * else bank0. 2193 + */ 2194 + if (ref >= npc_priv.bank_depth) { 2195 + bmap = sb->b1map; 2196 + t = sb->b1t; 2197 + b = sb->b1b; 2198 + } else { 2199 + bmap = sb->b0map; 2200 + t = sb->b0t; 2201 + b = sb->b0b; 2202 + } 2203 + 2204 + /* Calculate free slots */ 2205 + bw = bitmap_weight(bmap, npc_priv.subbank_depth); 2206 + bfree = npc_priv.subbank_depth - bw; 2207 + 2208 + if (!bfree) { 2209 + dev_dbg(rvu->dev, "%s: subbank is full\n", __func__); 2210 + return -ENOSPC; 2211 + } 2212 + 2213 + /* If request is for contiguous , then max we can allocate is 2214 + * equal to subbank_depth 2215 + */ 2216 + if (contig && bfree < count) { 2217 + dev_dbg(rvu->dev, "%s: no space for entry\n", __func__); 2218 + return -ENOSPC; 2219 + } 2220 + 2221 + /* 'save' array stores available indexes temporarily before 2222 + * marking it as allocated 2223 + */ 2224 + save = kcalloc(count, sizeof(u16), GFP_KERNEL); 2225 + if (!save) { 2226 + rc = -ENOMEM; 2227 + goto err1; 2228 + } 2229 + 2230 + if (contig) { 2231 + rc = __npc_subbank_contig_alloc(rvu, sb, key_type, 2232 + sidx, eidx, prio, 2233 + count, t, b, 2234 + bmap, save); 2235 + /* contiguous allocation success means that 2236 + * requested number of free slots got 2237 + * allocated 2238 + */ 2239 + if (!rc) 2240 + *alloc_cnt = count; 2241 + 2242 + } else { 2243 + rc = __npc_subbank_non_contig_alloc(rvu, sb, key_type, 2244 + sidx, eidx, prio, 2245 + t, b, bmap, 2246 + count, save, 2247 + max_alloc, alloc_cnt); 2248 + } 2249 + 2250 + if (rc) 2251 + goto err1; 2252 + 2253 + /* Mark new subbank bank as used */ 2254 + if (new_sub_bank) { 2255 + blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); 2256 + if (blkaddr < 0) { 2257 + dev_err(rvu->dev, 2258 + "%s: NPC block not implemented\n", __func__); 2259 + rc = -EFAULT; 2260 + goto err1; 2261 + } 2262 + 2263 + rc = __npc_subbank_mark_used(rvu, sb, key_type); 2264 + if (rc) { 2265 + dev_err(rvu->dev, 2266 + "%s: Error to mark subbank as used\n", 2267 + __func__); 2268 + goto err2; 2269 + } 2270 + 2271 + /* Configure section type to key_type */ 2272 + rvu_write64(rvu, blkaddr, 2273 + NPC_AF_MCAM_SECTIONX_CFG_EXT(sb->idx), 2274 + key_type); 2275 + } 2276 + 2277 + for (i = 0; i < *alloc_cnt; i++) { 2278 + rc = npc_subbank_idx_2_mcam_idx(rvu, sb, save[i], 2279 + &mcam_idx[i]); 2280 + if (rc) { 2281 + dev_err(rvu->dev, 2282 + "%s: Error to find mcam idx for %u\n", 2283 + __func__, save[i]); 2284 + /* TODO: handle err case gracefully */ 2285 + goto err3; 2286 + } 2287 + 2288 + /* Mark all slots as used */ 2289 + ret = __npc_subbank_mark_slot(rvu, sb, save[i], true); 2290 + if (!ret) { 2291 + dev_err(rvu->dev, "%s: Error to mark mcam_idx %u\n", 2292 + __func__, mcam_idx[i]); 2293 + rc = -EFAULT; 2294 + goto err3; 2295 + } 2296 + } 2297 + kfree(save); 2298 + return 0; 2299 + 2300 + err3: 2301 + for (int j = 0; j < i; j++) 2302 + __npc_subbank_mark_slot(rvu, sb, save[j], false); 2303 + err2: 2304 + if (new_sub_bank) 2305 + __npc_subbank_mark_free(rvu, sb); 2306 + err1: 2307 + kfree(save); 2308 + return rc; 2309 + } 2310 + 2311 + static int 2312 + npc_subbank_alloc(struct rvu *rvu, struct npc_subbank *sb, 2313 + int key_type, int ref, int limit, int prio, 2314 + bool contig, int count, u16 *mcam_idx, 2315 + int idx_sz, bool max_alloc, int *alloc_cnt) 2316 + { 2317 + int rc; 2318 + 2319 + mutex_lock(&sb->lock); 2320 + rc = __npc_subbank_alloc(rvu, sb, key_type, ref, limit, prio, 2321 + contig, count, mcam_idx, idx_sz, 2322 + max_alloc, alloc_cnt); 2323 + mutex_unlock(&sb->lock); 2324 + 2325 + return rc; 2326 + } 2327 + 2328 + static int 2329 + npc_del_from_pf_maps(struct rvu *rvu, u16 mcam_idx) 2330 + { 2331 + int pcifunc, idx; 2332 + void *map; 2333 + 2334 + map = xa_erase(&npc_priv.xa_idx2pf_map, mcam_idx); 2335 + if (!map) { 2336 + dev_err(rvu->dev, 2337 + "%s: failed to erase mcam_idx(%u) from xa_idx2pf map\n", 2338 + __func__, mcam_idx); 2339 + return -EFAULT; 2340 + } 2341 + 2342 + pcifunc = xa_to_value(map); 2343 + map = xa_load(&npc_priv.xa_pf_map, pcifunc); 2344 + if (!map) { 2345 + dev_err(rvu->dev, 2346 + "%s: failed to find entry for (%u) from xa_pf_map, mcam=%u\n", 2347 + __func__, pcifunc, mcam_idx); 2348 + return -ESRCH; 2349 + } 2350 + 2351 + idx = xa_to_value(map); 2352 + 2353 + map = xa_erase(&npc_priv.xa_pf2idx_map[idx], mcam_idx); 2354 + if (!map) { 2355 + dev_err(rvu->dev, 2356 + "%s: failed to erase mcam_idx(%u) from xa_pf2idx_map map\n", 2357 + __func__, mcam_idx); 2358 + return -EFAULT; 2359 + } 2360 + return 0; 2361 + } 2362 + 2363 + static int 2364 + npc_add_to_pf_maps(struct rvu *rvu, u16 mcam_idx, int pcifunc) 2365 + { 2366 + int rc, idx; 2367 + void *map; 2368 + 2369 + dev_dbg(rvu->dev, 2370 + "%s: add2maps mcam_idx(%u) to xa_idx2pf map pcifunc=%#x\n", 2371 + __func__, mcam_idx, pcifunc); 2372 + 2373 + rc = xa_insert(&npc_priv.xa_idx2pf_map, mcam_idx, 2374 + xa_mk_value(pcifunc), GFP_KERNEL); 2375 + 2376 + if (rc) { 2377 + map = xa_load(&npc_priv.xa_idx2pf_map, mcam_idx); 2378 + dev_err(rvu->dev, 2379 + "%s: failed to insert mcam_idx(%u) to xa_idx2pf map, existing value=%lu\n", 2380 + __func__, mcam_idx, xa_to_value(map)); 2381 + return -EFAULT; 2382 + } 2383 + 2384 + map = xa_load(&npc_priv.xa_pf_map, pcifunc); 2385 + if (!map) { 2386 + dev_err(rvu->dev, 2387 + "%s: failed to find pf map entry for pcifunc=%#x, mcam=%u\n", 2388 + __func__, pcifunc, mcam_idx); 2389 + return -ESRCH; 2390 + } 2391 + 2392 + idx = xa_to_value(map); 2393 + 2394 + rc = xa_insert(&npc_priv.xa_pf2idx_map[idx], mcam_idx, 2395 + xa_mk_value(pcifunc), GFP_KERNEL); 2396 + 2397 + if (rc) { 2398 + map = xa_load(&npc_priv.xa_pf2idx_map[idx], mcam_idx); 2399 + xa_erase(&npc_priv.xa_idx2pf_map, mcam_idx); 2400 + dev_err(rvu->dev, 2401 + "%s: failed to insert mcam_idx(%u) to xa_pf2idx_map map, earlier value=%lu idx=%u\n", 2402 + __func__, mcam_idx, xa_to_value(map), idx); 2403 + 2404 + return -EFAULT; 2405 + } 2406 + 2407 + return 0; 2408 + } 2409 + 2410 + static bool 2411 + npc_subbank_suits(struct npc_subbank *sb, int key_type) 2412 + { 2413 + mutex_lock(&sb->lock); 2414 + 2415 + if (!sb->key_type) { 2416 + mutex_unlock(&sb->lock); 2417 + return true; 2418 + } 2419 + 2420 + if (sb->key_type == key_type) { 2421 + mutex_unlock(&sb->lock); 2422 + return true; 2423 + } 2424 + 2425 + mutex_unlock(&sb->lock); 2426 + return false; 2427 + } 2428 + 2429 + #define SB_ALIGN_UP(val) (((val) + npc_priv.subbank_depth) & \ 2430 + ~((npc_priv.subbank_depth) - 1)) 2431 + #define SB_ALIGN_DOWN(val) ALIGN_DOWN((val), npc_priv.subbank_depth) 2432 + 2433 + static void npc_subbank_iter_down(struct rvu *rvu, 2434 + int ref, int limit, 2435 + int *cur_ref, int *cur_limit, 2436 + bool *start, bool *stop) 2437 + { 2438 + int align; 2439 + 2440 + *stop = false; 2441 + 2442 + /* ALIGN_DOWN the limit to current subbank boundary bottom index */ 2443 + if (*start) { 2444 + *start = false; 2445 + *cur_ref = ref; 2446 + align = SB_ALIGN_DOWN(ref); 2447 + if (align < limit) { 2448 + *stop = true; 2449 + *cur_limit = limit; 2450 + return; 2451 + } 2452 + *cur_limit = align; 2453 + return; 2454 + } 2455 + 2456 + *cur_ref = *cur_limit - 1; 2457 + align = *cur_ref - npc_priv.subbank_depth + 1; 2458 + if (align <= limit) { 2459 + *stop = true; 2460 + *cur_limit = limit; 2461 + return; 2462 + } 2463 + 2464 + *cur_limit = align; 2465 + } 2466 + 2467 + static void npc_subbank_iter_up(struct rvu *rvu, 2468 + int ref, int limit, 2469 + int *cur_ref, int *cur_limit, 2470 + bool *start, bool *stop) 2471 + { 2472 + int align; 2473 + 2474 + *stop = false; 2475 + 2476 + /* ALIGN_UP the limit to current subbank boundary top index */ 2477 + if (*start) { 2478 + *start = false; 2479 + *cur_ref = ref; 2480 + 2481 + /* Find next lower prio subbank's bottom index */ 2482 + align = SB_ALIGN_UP(ref); 2483 + 2484 + /* Crosses limit ? */ 2485 + if (align - 1 > limit) { 2486 + *stop = true; 2487 + *cur_limit = limit; 2488 + return; 2489 + } 2490 + 2491 + /* Current subbank's top index */ 2492 + *cur_limit = align - 1; 2493 + return; 2494 + } 2495 + 2496 + *cur_ref = *cur_limit + 1; 2497 + align = *cur_ref + npc_priv.subbank_depth - 1; 2498 + 2499 + if (align >= limit) { 2500 + *stop = true; 2501 + *cur_limit = limit; 2502 + return; 2503 + } 2504 + 2505 + *cur_limit = align; 2506 + } 2507 + 2508 + static int 2509 + npc_subbank_iter(struct rvu *rvu, int key_type, 2510 + int ref, int limit, int prio, 2511 + int *cur_ref, int *cur_limit, 2512 + bool *start, bool *stop) 2513 + { 2514 + if (prio != NPC_MCAM_HIGHER_PRIO) 2515 + npc_subbank_iter_up(rvu, ref, limit, 2516 + cur_ref, cur_limit, 2517 + start, stop); 2518 + else 2519 + npc_subbank_iter_down(rvu, ref, limit, 2520 + cur_ref, cur_limit, 2521 + start, stop); 2522 + 2523 + /* limit and ref should < bank_depth for x4 */ 2524 + if (key_type == NPC_MCAM_KEY_X4) { 2525 + if (*cur_ref >= npc_priv.bank_depth) 2526 + return -EINVAL; 2527 + 2528 + if (*cur_limit >= npc_priv.bank_depth) 2529 + return -EINVAL; 2530 + } 2531 + /* limit and ref should < 2 * bank_depth, for x2 */ 2532 + if (*cur_ref >= 2 * npc_priv.bank_depth) 2533 + return -EINVAL; 2534 + 2535 + if (*cur_limit >= 2 * npc_priv.bank_depth) 2536 + return -EINVAL; 2537 + 2538 + return 0; 2539 + } 2540 + 2541 + static int npc_idx_free(struct rvu *rvu, u16 *mcam_idx, int count, 2542 + bool maps_del) 2543 + { 2544 + struct npc_subbank *sb; 2545 + u16 vidx, midx; 2546 + int sb_off, i; 2547 + bool ret; 2548 + int rc; 2549 + 2550 + /* Check if we can dealloc indexes properly ? */ 2551 + for (i = 0; i < count; i++) { 2552 + rc = npc_mcam_idx_2_subbank_idx(rvu, npc_vidx2idx(mcam_idx[i]), 2553 + &sb, &sb_off); 2554 + if (rc) { 2555 + dev_err(rvu->dev, 2556 + "Failed to free mcam idx=%u\n", mcam_idx[i]); 2557 + return rc; 2558 + } 2559 + } 2560 + 2561 + for (i = 0; i < count; i++) { 2562 + if (npc_is_vidx(mcam_idx[i])) { 2563 + vidx = mcam_idx[i]; 2564 + midx = npc_vidx2idx(vidx); 2565 + } else { 2566 + midx = mcam_idx[i]; 2567 + vidx = npc_idx2vidx(midx); 2568 + } 2569 + 2570 + if (midx >= npc_priv.bank_depth * npc_priv.num_banks) { 2571 + dev_err(rvu->dev, 2572 + "%s: Invalid mcam_idx=%u cannot be deleted\n", 2573 + __func__, mcam_idx[i]); 2574 + return -EINVAL; 2575 + } 2576 + 2577 + rc = npc_mcam_idx_2_subbank_idx(rvu, midx, 2578 + &sb, &sb_off); 2579 + if (rc) { 2580 + dev_err(rvu->dev, 2581 + "%s: Failed to find subbank info for vidx=%u\n", 2582 + __func__, vidx); 2583 + return rc; 2584 + } 2585 + 2586 + ret = npc_subbank_free(rvu, sb, sb_off); 2587 + if (ret) { 2588 + dev_err(rvu->dev, 2589 + "%s: Failed to find subbank info for vidx=%u\n", 2590 + __func__, vidx); 2591 + return -EINVAL; 2592 + } 2593 + 2594 + if (!maps_del) 2595 + continue; 2596 + 2597 + rc = npc_del_from_pf_maps(rvu, midx); 2598 + if (rc) 2599 + return rc; 2600 + 2601 + /* If there is no vidx mapping; continue */ 2602 + if (vidx == midx) 2603 + continue; 2604 + 2605 + rc = npc_vidx_maps_del_entry(rvu, vidx, NULL); 2606 + if (rc) 2607 + return rc; 2608 + } 2609 + 2610 + return 0; 2611 + } 2612 + 2613 + static int npc_multi_subbank_ref_alloc(struct rvu *rvu, int key_type, 2614 + int ref, int limit, int prio, 2615 + bool contig, int count, 2616 + u16 *mcam_idx) 2617 + { 2618 + struct npc_subbank *sb; 2619 + unsigned long *bmap; 2620 + int sb_off, off, rc; 2621 + int cnt = 0; 2622 + bool bitset; 2623 + 2624 + if (prio != NPC_MCAM_HIGHER_PRIO) { 2625 + while (ref <= limit) { 2626 + /* Calculate subbank and subbank index */ 2627 + rc = npc_mcam_idx_2_subbank_idx(rvu, ref, 2628 + &sb, &sb_off); 2629 + if (rc) 2630 + goto err; 2631 + 2632 + /* If subbank is not suitable for requested key type 2633 + * restart search from next subbank 2634 + */ 2635 + if (!npc_subbank_suits(sb, key_type)) { 2636 + ref = SB_ALIGN_UP(ref); 2637 + if (contig) { 2638 + rc = npc_idx_free(rvu, mcam_idx, 2639 + cnt, false); 2640 + if (rc) 2641 + return rc; 2642 + cnt = 0; 2643 + } 2644 + continue; 2645 + } 2646 + 2647 + mutex_lock(&sb->lock); 2648 + 2649 + /* If subbank is free; mark it as used */ 2650 + if (sb->flags & NPC_SUBBANK_FLAG_FREE) { 2651 + rc = __npc_subbank_mark_used(rvu, sb, 2652 + key_type); 2653 + if (rc) { 2654 + mutex_unlock(&sb->lock); 2655 + dev_err(rvu->dev, 2656 + "%s:Error to add to use array\n", 2657 + __func__); 2658 + goto err; 2659 + } 2660 + } 2661 + 2662 + /* Find correct bmap */ 2663 + __npc_subbank_sboff_2_off(rvu, sb, sb_off, &bmap, &off); 2664 + 2665 + /* if bit is already set, reset 'cnt' */ 2666 + bitset = test_bit(off, bmap); 2667 + if (bitset) { 2668 + mutex_unlock(&sb->lock); 2669 + if (contig) { 2670 + rc = npc_idx_free(rvu, mcam_idx, 2671 + cnt, false); 2672 + if (rc) 2673 + return rc; 2674 + cnt = 0; 2675 + } 2676 + 2677 + ref++; 2678 + continue; 2679 + } 2680 + 2681 + set_bit(off, bmap); 2682 + sb->free_cnt--; 2683 + mcam_idx[cnt++] = ref; 2684 + mutex_unlock(&sb->lock); 2685 + 2686 + if (cnt == count) 2687 + return 0; 2688 + ref++; 2689 + } 2690 + 2691 + /* Could not allocate request count slots */ 2692 + goto err; 2693 + } 2694 + while (ref >= limit) { 2695 + rc = npc_mcam_idx_2_subbank_idx(rvu, ref, 2696 + &sb, &sb_off); 2697 + if (rc) 2698 + goto err; 2699 + 2700 + if (!npc_subbank_suits(sb, key_type)) { 2701 + ref = SB_ALIGN_DOWN(ref) - 1; 2702 + if (contig) { 2703 + rc = npc_idx_free(rvu, mcam_idx, cnt, false); 2704 + if (rc) 2705 + return rc; 2706 + 2707 + cnt = 0; 2708 + } 2709 + continue; 2710 + } 2711 + 2712 + mutex_lock(&sb->lock); 2713 + 2714 + if (sb->flags & NPC_SUBBANK_FLAG_FREE) { 2715 + rc = __npc_subbank_mark_used(rvu, sb, key_type); 2716 + if (rc) { 2717 + mutex_unlock(&sb->lock); 2718 + dev_err(rvu->dev, 2719 + "%s:Error to add to use array\n", 2720 + __func__); 2721 + goto err; 2722 + } 2723 + } 2724 + 2725 + __npc_subbank_sboff_2_off(rvu, sb, sb_off, &bmap, &off); 2726 + bitset = test_bit(off, bmap); 2727 + if (bitset) { 2728 + mutex_unlock(&sb->lock); 2729 + if (contig) { 2730 + rc = npc_idx_free(rvu, mcam_idx, cnt, false); 2731 + if (rc) 2732 + return rc; 2733 + 2734 + cnt = 0; 2735 + } 2736 + ref--; 2737 + continue; 2738 + } 2739 + 2740 + mcam_idx[cnt++] = ref; 2741 + sb->free_cnt--; 2742 + set_bit(off, bmap); 2743 + mutex_unlock(&sb->lock); 2744 + 2745 + if (cnt == count) 2746 + return 0; 2747 + ref--; 2748 + } 2749 + 2750 + err: 2751 + rc = npc_idx_free(rvu, mcam_idx, cnt, false); 2752 + if (rc) 2753 + dev_err(rvu->dev, 2754 + "%s: Error happened while freeing cnt=%u indexes\n", 2755 + __func__, cnt); 2756 + 2757 + return -ENOSPC; 2758 + } 2759 + 2760 + static int npc_subbank_free_cnt(struct rvu *rvu, struct npc_subbank *sb, 2761 + int key_type) 2762 + { 2763 + int cnt, spd; 2764 + 2765 + spd = npc_priv.subbank_depth; 2766 + mutex_lock(&sb->lock); 2767 + 2768 + if (sb->flags & NPC_SUBBANK_FLAG_FREE) 2769 + cnt = key_type == NPC_MCAM_KEY_X4 ? spd : 2 * spd; 2770 + else 2771 + cnt = sb->free_cnt; 2772 + 2773 + mutex_unlock(&sb->lock); 2774 + return cnt; 2775 + } 2776 + 2777 + static int npc_subbank_ref_alloc(struct rvu *rvu, int key_type, 2778 + int ref, int limit, int prio, 2779 + bool contig, int count, 2780 + u16 *mcam_idx) 2781 + { 2782 + struct npc_subbank *sb1, *sb2; 2783 + bool max_alloc, start, stop; 2784 + int r, l, sb_idx1, sb_idx2; 2785 + int tot = 0, rc; 2786 + int alloc_cnt; 2787 + 2788 + max_alloc = !contig; 2789 + 2790 + start = true; 2791 + stop = false; 2792 + 2793 + /* Loop until we cross the ref/limit boundary */ 2794 + while (!stop) { 2795 + rc = npc_subbank_iter(rvu, key_type, ref, limit, prio, 2796 + &r, &l, &start, &stop); 2797 + 2798 + dev_dbg(rvu->dev, 2799 + "%s: ref=%d limit=%d r=%d l=%d start=%d stop=%d tot=%d count=%d rc=%d\n", 2800 + __func__, ref, limit, r, l, 2801 + start, stop, tot, count, rc); 2802 + 2803 + if (rc) 2804 + goto err; 2805 + 2806 + /* Find subbank and subbank index for ref */ 2807 + rc = npc_mcam_idx_2_subbank_idx(rvu, r, &sb1, 2808 + &sb_idx1); 2809 + if (rc) 2810 + goto err; 2811 + 2812 + dev_dbg(rvu->dev, 2813 + "%s: ref subbank=%d off=%d\n", 2814 + __func__, sb1->idx, sb_idx1); 2815 + 2816 + /* Skip subbank if it is not available for the keytype */ 2817 + if (!npc_subbank_suits(sb1, key_type)) { 2818 + dev_dbg(rvu->dev, 2819 + "%s: not suitable sb=%d key_type=%d\n", 2820 + __func__, sb1->idx, key_type); 2821 + continue; 2822 + } 2823 + 2824 + /* Find subbank and subbank index for limit */ 2825 + rc = npc_mcam_idx_2_subbank_idx(rvu, l, &sb2, 2826 + &sb_idx2); 2827 + if (rc) 2828 + goto err; 2829 + 2830 + dev_dbg(rvu->dev, 2831 + "%s: limit subbank=%d off=%d\n", 2832 + __func__, sb_idx1, sb_idx2); 2833 + 2834 + /* subbank of ref and limit should be same */ 2835 + if (sb1 != sb2) { 2836 + dev_err(rvu->dev, 2837 + "%s: l(%d) and r(%d) are not in same subbank\n", 2838 + __func__, r, l); 2839 + goto err; 2840 + } 2841 + 2842 + if (contig && 2843 + npc_subbank_free_cnt(rvu, sb1, key_type) < count) { 2844 + dev_dbg(rvu->dev, "%s: less count =%d\n", 2845 + __func__, 2846 + npc_subbank_free_cnt(rvu, sb1, key_type)); 2847 + continue; 2848 + } 2849 + 2850 + /* Try in one bank of a subbank */ 2851 + alloc_cnt = 0; 2852 + rc = npc_subbank_alloc(rvu, sb1, key_type, 2853 + r, l, prio, contig, 2854 + count - tot, mcam_idx + tot, 2855 + count - tot, max_alloc, 2856 + &alloc_cnt); 2857 + 2858 + tot += alloc_cnt; 2859 + 2860 + dev_dbg(rvu->dev, "%s: Allocated tot=%d alloc_cnt=%d\n", 2861 + __func__, tot, alloc_cnt); 2862 + 2863 + if (!rc && count == tot) 2864 + return 0; 2865 + } 2866 + err: 2867 + dev_dbg(rvu->dev, "%s: Error to allocate\n", 2868 + __func__); 2869 + 2870 + /* non contiguous allocation fails. We need to do clean up */ 2871 + if (max_alloc) { 2872 + rc = npc_idx_free(rvu, mcam_idx, tot, false); 2873 + if (rc) 2874 + dev_err(rvu->dev, 2875 + "%s: failed to free %u indexes\n", 2876 + __func__, tot); 2877 + } 2878 + 2879 + return -EFAULT; 2880 + } 2881 + 2882 + /* Minimize allocation from bottom and top subbanks for noref allocations. 2883 + * Default allocations are ref based, and will be allocated from top 2884 + * subbanks (least priority subbanks). Since default allocation is at very 2885 + * early stage of kernel netdev probes, this subbanks will be moved to 2886 + * used subbanks list. This will pave a way for noref allocation from these 2887 + * used subbanks. Skip allocation for these top and bottom, and try free 2888 + * bank next. If none slot is available, come back and search in these 2889 + * subbanks. 2890 + */ 2891 + 2892 + static int npc_subbank_restricted_idxs[2]; 2893 + static bool restrict_valid = true; 2894 + 2895 + static bool npc_subbank_restrict_usage(struct rvu *rvu, int index) 2896 + { 2897 + int i; 2898 + 2899 + if (!restrict_valid) 2900 + return false; 2901 + 2902 + for (i = 0; i < ARRAY_SIZE(npc_subbank_restricted_idxs); i++) { 2903 + if (index == npc_subbank_restricted_idxs[i]) 2904 + return true; 2905 + } 2906 + 2907 + return false; 2908 + } 2909 + 2910 + static int npc_subbank_noref_alloc(struct rvu *rvu, int key_type, bool contig, 2911 + int count, u16 *mcam_idx) 2912 + { 2913 + struct npc_subbank *sb; 2914 + unsigned long index; 2915 + int tot = 0, rc; 2916 + bool max_alloc; 2917 + int alloc_cnt; 2918 + int idx, i; 2919 + void *val; 2920 + 2921 + max_alloc = !contig; 2922 + 2923 + /* Check used subbanks for free slots */ 2924 + xa_for_each(&npc_priv.xa_sb_used, index, val) { 2925 + idx = xa_to_value(val); 2926 + 2927 + /* Minimize allocation from restricted subbanks 2928 + * in noref allocations. 2929 + */ 2930 + if (npc_subbank_restrict_usage(rvu, idx)) 2931 + continue; 2932 + 2933 + sb = &npc_priv.sb[idx]; 2934 + 2935 + /* Skip if not suitable subbank */ 2936 + if (!npc_subbank_suits(sb, key_type)) 2937 + continue; 2938 + 2939 + if (contig && npc_subbank_free_cnt(rvu, sb, key_type) < count) 2940 + continue; 2941 + 2942 + /* try in bank 0. Try passing ref and limit equal to 2943 + * subbank boundaries 2944 + */ 2945 + alloc_cnt = 0; 2946 + rc = npc_subbank_alloc(rvu, sb, key_type, 2947 + sb->b0b, sb->b0t, 0, 2948 + contig, count - tot, 2949 + mcam_idx + tot, 2950 + count - tot, 2951 + max_alloc, &alloc_cnt); 2952 + 2953 + /* Non contiguous allocation may allocate less than 2954 + * requested 'count'. 2955 + */ 2956 + tot += alloc_cnt; 2957 + 2958 + dev_dbg(rvu->dev, 2959 + "%s: Allocated %d from subbank %d, tot=%d count=%d\n", 2960 + __func__, alloc_cnt, sb->idx, tot, count); 2961 + 2962 + /* Successfully allocated */ 2963 + if (!rc && count == tot) 2964 + return 0; 2965 + 2966 + /* x4 entries can be allocated from bank 0 only */ 2967 + if (key_type == NPC_MCAM_KEY_X4) 2968 + continue; 2969 + 2970 + /* try in bank 1 for x2 */ 2971 + alloc_cnt = 0; 2972 + rc = npc_subbank_alloc(rvu, sb, key_type, 2973 + sb->b1b, sb->b1t, 0, 2974 + contig, count - tot, 2975 + mcam_idx + tot, 2976 + count - tot, max_alloc, 2977 + &alloc_cnt); 2978 + 2979 + tot += alloc_cnt; 2980 + 2981 + dev_dbg(rvu->dev, 2982 + "%s: Allocated %d from subbank %d, tot=%d count=%d\n", 2983 + __func__, alloc_cnt, sb->idx, tot, count); 2984 + 2985 + if (!rc && count == tot) 2986 + return 0; 2987 + } 2988 + 2989 + /* Allocate in free subbanks */ 2990 + xa_for_each(&npc_priv.xa_sb_free, index, val) { 2991 + idx = xa_to_value(val); 2992 + sb = &npc_priv.sb[idx]; 2993 + 2994 + /* Minimize allocation from restricted subbanks 2995 + * in noref allocations. 2996 + */ 2997 + if (npc_subbank_restrict_usage(rvu, idx)) 2998 + continue; 2999 + 3000 + if (!npc_subbank_suits(sb, key_type)) 3001 + continue; 3002 + 3003 + /* try in bank 0 */ 3004 + alloc_cnt = 0; 3005 + rc = npc_subbank_alloc(rvu, sb, key_type, 3006 + sb->b0b, sb->b0t, 0, 3007 + contig, count - tot, 3008 + mcam_idx + tot, 3009 + count - tot, 3010 + max_alloc, &alloc_cnt); 3011 + 3012 + tot += alloc_cnt; 3013 + 3014 + dev_dbg(rvu->dev, 3015 + "%s: Allocated %d from subbank %d, tot=%d count=%d\n", 3016 + __func__, alloc_cnt, sb->idx, tot, count); 3017 + 3018 + /* Successfully allocated */ 3019 + if (!rc && count == tot) 3020 + return 0; 3021 + 3022 + /* x4 entries can be allocated from bank 0 only */ 3023 + if (key_type == NPC_MCAM_KEY_X4) 3024 + continue; 3025 + 3026 + /* try in bank 1 for x2 */ 3027 + alloc_cnt = 0; 3028 + rc = npc_subbank_alloc(rvu, sb, 3029 + key_type, sb->b1b, sb->b1t, 0, 3030 + contig, count - tot, 3031 + mcam_idx + tot, count - tot, 3032 + max_alloc, &alloc_cnt); 3033 + 3034 + tot += alloc_cnt; 3035 + 3036 + dev_dbg(rvu->dev, 3037 + "%s: Allocated %d from subbank %d, tot=%d count=%d\n", 3038 + __func__, alloc_cnt, sb->idx, tot, count); 3039 + 3040 + if (!rc && count == tot) 3041 + return 0; 3042 + } 3043 + 3044 + /* Allocate from restricted subbanks */ 3045 + for (i = 0; restrict_valid && 3046 + (i < ARRAY_SIZE(npc_subbank_restricted_idxs)); i++) { 3047 + idx = npc_subbank_restricted_idxs[i]; 3048 + sb = &npc_priv.sb[idx]; 3049 + 3050 + /* Skip if not suitable subbank */ 3051 + if (!npc_subbank_suits(sb, key_type)) 3052 + continue; 3053 + 3054 + if (contig && npc_subbank_free_cnt(rvu, sb, key_type) < count) 3055 + continue; 3056 + 3057 + /* try in bank 0. Try passing ref and limit equal to 3058 + * subbank boundaries 3059 + */ 3060 + alloc_cnt = 0; 3061 + rc = npc_subbank_alloc(rvu, sb, key_type, 3062 + sb->b0b, sb->b0t, 0, 3063 + contig, count - tot, 3064 + mcam_idx + tot, 3065 + count - tot, 3066 + max_alloc, &alloc_cnt); 3067 + 3068 + /* Non contiguous allocation may allocate less than 3069 + * requested 'count'. 3070 + */ 3071 + tot += alloc_cnt; 3072 + 3073 + dev_dbg(rvu->dev, 3074 + "%s: Allocated %d from subbank %d, tot=%d count=%d\n", 3075 + __func__, alloc_cnt, sb->idx, tot, count); 3076 + 3077 + /* Successfully allocated */ 3078 + if (!rc && count == tot) 3079 + return 0; 3080 + 3081 + /* x4 entries can be allocated from bank 0 only */ 3082 + if (key_type == NPC_MCAM_KEY_X4) 3083 + continue; 3084 + 3085 + /* try in bank 1 for x2 */ 3086 + alloc_cnt = 0; 3087 + rc = npc_subbank_alloc(rvu, sb, key_type, 3088 + sb->b1b, sb->b1t, 0, 3089 + contig, count - tot, 3090 + mcam_idx + tot, 3091 + count - tot, max_alloc, 3092 + &alloc_cnt); 3093 + 3094 + tot += alloc_cnt; 3095 + 3096 + dev_dbg(rvu->dev, 3097 + "%s: Allocated %d from subbank %d, tot=%d count=%d\n", 3098 + __func__, alloc_cnt, sb->idx, tot, count); 3099 + 3100 + if (!rc && count == tot) 3101 + return 0; 3102 + } 3103 + 3104 + /* non contiguous allocation fails. We need to do clean up */ 3105 + if (max_alloc) 3106 + npc_idx_free(rvu, mcam_idx, tot, false); 3107 + 3108 + dev_dbg(rvu->dev, "%s: non-contig allocation fails\n", 3109 + __func__); 3110 + 3111 + return -EFAULT; 3112 + } 3113 + 3114 + int npc_cn20k_idx_free(struct rvu *rvu, u16 *mcam_idx, int count) 3115 + { 3116 + return npc_idx_free(rvu, mcam_idx, count, true); 3117 + } 3118 + 3119 + int npc_cn20k_ref_idx_alloc(struct rvu *rvu, int pcifunc, int key_type, 3120 + int prio, u16 *mcam_idx, int ref, int limit, 3121 + bool contig, int count, bool virt) 3122 + { 3123 + bool defrag_candidate = false; 3124 + int i, eidx, rc, bd; 3125 + bool ref_valid; 3126 + u16 vidx; 3127 + 3128 + bd = npc_priv.bank_depth; 3129 + 3130 + /* Special case: ref == 0 && limit= 0 && prio == HIGH && count == 1 3131 + * Here user wants to allocate 0th entry 3132 + */ 3133 + if (!ref && !limit && prio == NPC_MCAM_HIGHER_PRIO && 3134 + count == 1) { 3135 + rc = npc_subbank_ref_alloc(rvu, key_type, ref, limit, 3136 + prio, contig, count, mcam_idx); 3137 + 3138 + if (rc) 3139 + return rc; 3140 + goto add2map; 3141 + } 3142 + 3143 + ref_valid = !!(limit || ref); 3144 + defrag_candidate = !ref_valid && !contig && virt; 3145 + if (!ref_valid) { 3146 + if (contig && count > npc_priv.subbank_depth) 3147 + goto try_noref_multi_subbank; 3148 + 3149 + rc = npc_subbank_noref_alloc(rvu, key_type, contig, 3150 + count, mcam_idx); 3151 + if (!rc) 3152 + goto add2map; 3153 + 3154 + try_noref_multi_subbank: 3155 + eidx = (key_type == NPC_MCAM_KEY_X4) ? bd - 1 : 2 * bd - 1; 3156 + 3157 + if (prio == NPC_MCAM_HIGHER_PRIO) 3158 + rc = npc_multi_subbank_ref_alloc(rvu, key_type, 3159 + eidx, 0, 3160 + NPC_MCAM_HIGHER_PRIO, 3161 + contig, count, 3162 + mcam_idx); 3163 + else 3164 + rc = npc_multi_subbank_ref_alloc(rvu, key_type, 3165 + 0, eidx, 3166 + NPC_MCAM_LOWER_PRIO, 3167 + contig, count, 3168 + mcam_idx); 3169 + 3170 + if (!rc) 3171 + goto add2map; 3172 + 3173 + return rc; 3174 + } 3175 + 3176 + if ((prio == NPC_MCAM_LOWER_PRIO && ref > limit) || 3177 + (prio == NPC_MCAM_HIGHER_PRIO && ref < limit)) { 3178 + dev_err(rvu->dev, "%s: Wrong ref_enty(%d) or limit(%d)\n", 3179 + __func__, ref, limit); 3180 + return -EINVAL; 3181 + } 3182 + 3183 + if ((key_type == NPC_MCAM_KEY_X4 && (ref >= bd || limit >= bd)) || 3184 + (key_type == NPC_MCAM_KEY_X2 && 3185 + (ref >= 2 * bd || limit >= 2 * bd))) { 3186 + dev_err(rvu->dev, "%s: Wrong ref_enty(%d) or limit(%d)\n", 3187 + __func__, ref, limit); 3188 + return -EINVAL; 3189 + } 3190 + 3191 + if (contig && count > npc_priv.subbank_depth) 3192 + goto try_ref_multi_subbank; 3193 + 3194 + rc = npc_subbank_ref_alloc(rvu, key_type, ref, limit, 3195 + prio, contig, count, mcam_idx); 3196 + if (!rc) 3197 + goto add2map; 3198 + 3199 + try_ref_multi_subbank: 3200 + rc = npc_multi_subbank_ref_alloc(rvu, key_type, 3201 + ref, limit, prio, 3202 + contig, count, mcam_idx); 3203 + if (!rc) 3204 + goto add2map; 3205 + 3206 + return rc; 3207 + 3208 + add2map: 3209 + for (i = 0; i < count; i++) { 3210 + rc = npc_add_to_pf_maps(rvu, mcam_idx[i], pcifunc); 3211 + if (rc) 3212 + goto err; 3213 + 3214 + if (!defrag_candidate) 3215 + continue; 3216 + 3217 + rc = npc_vidx_maps_add_entry(rvu, mcam_idx[i], pcifunc, &vidx); 3218 + if (rc) { 3219 + npc_del_from_pf_maps(rvu, mcam_idx[i]); 3220 + goto err; 3221 + } 3222 + 3223 + /* Return vidx to caller */ 3224 + mcam_idx[i] = vidx; 3225 + } 3226 + 3227 + return 0; 3228 + err: 3229 + for (int j = 0; j < i; j++) { 3230 + npc_del_from_pf_maps(rvu, npc_vidx2idx(mcam_idx[j])); 3231 + 3232 + if (!defrag_candidate) 3233 + continue; 3234 + 3235 + npc_vidx_maps_del_entry(rvu, mcam_idx[j], NULL); 3236 + } 3237 + 3238 + return rc; 3239 + 3240 + } 3241 + 3242 + void npc_cn20k_subbank_calc_free(struct rvu *rvu, int *x2_free, 3243 + int *x4_free, int *sb_free) 3244 + { 3245 + struct npc_subbank *sb; 3246 + int i; 3247 + 3248 + /* Reset all stats to zero */ 3249 + *x2_free = 0; 3250 + *x4_free = 0; 3251 + *sb_free = 0; 3252 + 3253 + for (i = 0; i < npc_priv.num_subbanks; i++) { 3254 + sb = &npc_priv.sb[i]; 3255 + mutex_lock(&sb->lock); 3256 + 3257 + /* Count number of free subbanks */ 3258 + if (sb->flags & NPC_SUBBANK_FLAG_FREE) { 3259 + (*sb_free)++; 3260 + goto next; 3261 + } 3262 + 3263 + /* Sumup x4 free count */ 3264 + if (sb->key_type == NPC_MCAM_KEY_X4) { 3265 + (*x4_free) += sb->free_cnt; 3266 + goto next; 3267 + } 3268 + 3269 + /* Sumup x2 free counts */ 3270 + (*x2_free) += sb->free_cnt; 3271 + next: 3272 + mutex_unlock(&sb->lock); 3273 + } 3274 + } 3275 + 3276 + int 3277 + rvu_mbox_handler_npc_cn20k_get_fcnt(struct rvu *rvu, 3278 + struct msg_req *req, 3279 + struct npc_cn20k_get_fcnt_rsp *rsp) 3280 + { 3281 + npc_cn20k_subbank_calc_free(rvu, &rsp->free_x2, 3282 + &rsp->free_x4, &rsp->free_subbanks); 3283 + return 0; 3284 + } 3285 + 3286 + int 3287 + rvu_mbox_handler_npc_cn20k_get_kex_cfg(struct rvu *rvu, 3288 + struct msg_req *req, 3289 + struct npc_cn20k_get_kex_cfg_rsp *rsp) 3290 + { 3291 + int extr, lt; 3292 + 3293 + rsp->rx_keyx_cfg = CN20K_GET_KEX_CFG(NIX_INTF_RX); 3294 + rsp->tx_keyx_cfg = CN20K_GET_KEX_CFG(NIX_INTF_TX); 3295 + 3296 + /* Get EXTRACTOR LID */ 3297 + for (extr = 0; extr < NPC_MAX_EXTRACTOR; extr++) { 3298 + rsp->intf_extr_lid[NIX_INTF_RX][extr] = 3299 + CN20K_GET_EXTR_LID(NIX_INTF_RX, extr); 3300 + rsp->intf_extr_lid[NIX_INTF_TX][extr] = 3301 + CN20K_GET_EXTR_LID(NIX_INTF_TX, extr); 3302 + } 3303 + 3304 + /* Get EXTRACTOR LTYPE */ 3305 + for (extr = 0; extr < NPC_MAX_EXTRACTOR; extr++) { 3306 + for (lt = 0; lt < NPC_MAX_LT; lt++) { 3307 + rsp->intf_extr_lt[NIX_INTF_RX][extr][lt] = 3308 + CN20K_GET_EXTR_LT(NIX_INTF_RX, extr, lt); 3309 + rsp->intf_extr_lt[NIX_INTF_TX][extr][lt] = 3310 + CN20K_GET_EXTR_LT(NIX_INTF_TX, extr, lt); 3311 + } 3312 + } 3313 + 3314 + memcpy(rsp->mkex_pfl_name, rvu->mkex_pfl_name, MKEX_NAME_LEN); 3315 + return 0; 3316 + } 3317 + 3318 + static int *subbank_srch_order; 3319 + 3320 + static void npc_populate_restricted_idxs(int num_subbanks) 3321 + { 3322 + npc_subbank_restricted_idxs[0] = num_subbanks - 1; 3323 + npc_subbank_restricted_idxs[1] = 0; 3324 + } 3325 + 3326 + static int npc_create_srch_order(int cnt) 3327 + { 3328 + int val = 0; 3329 + 3330 + subbank_srch_order = kcalloc(cnt, sizeof(int), 3331 + GFP_KERNEL); 3332 + if (!subbank_srch_order) 3333 + return -ENOMEM; 3334 + 3335 + /* cnt(subbank depth) is always a power of 2. There is a check in 3336 + * npc_priv_init() to check the same. 3337 + */ 3338 + for (int i = 0; i < cnt; i += 2) { 3339 + subbank_srch_order[i] = cnt / 2 - val - 1; 3340 + subbank_srch_order[i + 1] = cnt / 2 + 1 + val; 3341 + val++; 3342 + } 3343 + 3344 + subbank_srch_order[cnt - 1] = cnt / 2; 3345 + return 0; 3346 + } 3347 + 3348 + static void npc_subbank_init(struct rvu *rvu, struct npc_subbank *sb, int idx) 3349 + { 3350 + mutex_init(&sb->lock); 3351 + 3352 + sb->b0b = idx * npc_priv.subbank_depth; 3353 + sb->b0t = sb->b0b + npc_priv.subbank_depth - 1; 3354 + 3355 + sb->b1b = npc_priv.bank_depth + idx * npc_priv.subbank_depth; 3356 + sb->b1t = sb->b1b + npc_priv.subbank_depth - 1; 3357 + 3358 + sb->flags = NPC_SUBBANK_FLAG_FREE; 3359 + sb->idx = idx; 3360 + sb->arr_idx = subbank_srch_order[idx]; 3361 + 3362 + dev_dbg(rvu->dev, "%s: sb->idx=%u sb->arr_idx=%u\n", 3363 + __func__, sb->idx, sb->arr_idx); 3364 + 3365 + /* Keep first and last subbank at end of free array; so that 3366 + * it will be used at last 3367 + */ 3368 + xa_store(&npc_priv.xa_sb_free, sb->arr_idx, 3369 + xa_mk_value(sb->idx), GFP_KERNEL); 3370 + } 3371 + 3372 + static int npc_pcifunc_map_create(struct rvu *rvu) 3373 + { 3374 + int pf, vf, numvfs; 3375 + int cnt = 0; 3376 + u16 pcifunc; 3377 + u64 cfg; 3378 + 3379 + for (pf = 0; pf < rvu->hw->total_pfs; pf++) { 3380 + cfg = rvu_read64(rvu, BLKADDR_RVUM, RVU_PRIV_PFX_CFG(pf)); 3381 + numvfs = (cfg >> 12) & 0xFF; 3382 + 3383 + /* Skip not enabled PFs */ 3384 + if (!(cfg & BIT_ULL(20))) 3385 + goto chk_vfs; 3386 + 3387 + /* If Admin function, check on VFs */ 3388 + if (cfg & BIT_ULL(21)) 3389 + goto chk_vfs; 3390 + 3391 + pcifunc = pf << 9; 3392 + 3393 + xa_store(&npc_priv.xa_pf_map, (unsigned long)pcifunc, 3394 + xa_mk_value(cnt), GFP_KERNEL); 3395 + 3396 + cnt++; 3397 + 3398 + chk_vfs: 3399 + for (vf = 0; vf < numvfs; vf++) { 3400 + pcifunc = (pf << 9) | (vf + 1); 3401 + 3402 + xa_store(&npc_priv.xa_pf_map, (unsigned long)pcifunc, 3403 + xa_mk_value(cnt), GFP_KERNEL); 3404 + cnt++; 3405 + } 3406 + } 3407 + 3408 + return cnt; 3409 + } 3410 + 3411 + struct npc_defrag_node { 3412 + u8 idx; 3413 + u8 key_type; 3414 + bool valid; 3415 + bool refs; 3416 + u16 free_cnt; 3417 + u16 vidx_cnt; 3418 + u16 *vidx; 3419 + struct list_head list; 3420 + }; 3421 + 3422 + static bool npc_defrag_skip_restricted_sb(int sb_id) 3423 + { 3424 + int i; 3425 + 3426 + if (!restrict_valid) 3427 + return false; 3428 + 3429 + for (i = 0; i < ARRAY_SIZE(npc_subbank_restricted_idxs); i++) 3430 + if (sb_id == npc_subbank_restricted_idxs[i]) 3431 + return true; 3432 + return false; 3433 + } 3434 + 3435 + /* Find subbank with minimum number of virtual indexes */ 3436 + static struct npc_defrag_node *npc_subbank_min_vidx(struct list_head *lh) 3437 + { 3438 + struct npc_defrag_node *node, *tnode = NULL; 3439 + int min = INT_MAX; 3440 + 3441 + list_for_each_entry(node, lh, list) { 3442 + if (!node->valid) 3443 + continue; 3444 + 3445 + /* if subbank has ref allocated mcam indexes, that subbank 3446 + * is not a good candidate to move out indexes. 3447 + */ 3448 + if (node->refs) 3449 + continue; 3450 + 3451 + if (min > node->vidx_cnt) { 3452 + min = node->vidx_cnt; 3453 + tnode = node; 3454 + } 3455 + } 3456 + 3457 + return tnode; 3458 + } 3459 + 3460 + /* Find subbank with maximum number of free spaces */ 3461 + static struct npc_defrag_node *npc_subbank_max_free(struct list_head *lh) 3462 + { 3463 + struct npc_defrag_node *node, *tnode = NULL; 3464 + int max = INT_MIN; 3465 + 3466 + list_for_each_entry(node, lh, list) { 3467 + if (!node->valid) 3468 + continue; 3469 + 3470 + if (max < node->free_cnt) { 3471 + max = node->free_cnt; 3472 + tnode = node; 3473 + } 3474 + } 3475 + 3476 + return tnode; 3477 + } 3478 + 3479 + static int npc_defrag_alloc_free_slots(struct rvu *rvu, 3480 + struct npc_defrag_node *f, 3481 + int cnt, u16 *save) 3482 + { 3483 + int alloc_cnt1, alloc_cnt2; 3484 + struct npc_subbank *sb; 3485 + int rc, sb_off, i; 3486 + bool deleted; 3487 + 3488 + sb = &npc_priv.sb[f->idx]; 3489 + 3490 + alloc_cnt1 = 0; 3491 + alloc_cnt2 = 0; 3492 + 3493 + rc = __npc_subbank_alloc(rvu, sb, 3494 + NPC_MCAM_KEY_X2, sb->b0b, 3495 + sb->b0t, 3496 + NPC_MCAM_LOWER_PRIO, 3497 + false, cnt, save, cnt, true, 3498 + &alloc_cnt1); 3499 + if (alloc_cnt1 < cnt) { 3500 + rc = __npc_subbank_alloc(rvu, sb, 3501 + NPC_MCAM_KEY_X2, sb->b1b, 3502 + sb->b1t, 3503 + NPC_MCAM_LOWER_PRIO, 3504 + false, cnt - alloc_cnt1, 3505 + save + alloc_cnt1, 3506 + cnt - alloc_cnt1, 3507 + true, &alloc_cnt2); 3508 + } 3509 + 3510 + if (alloc_cnt1 + alloc_cnt2 != cnt) { 3511 + dev_err(rvu->dev, 3512 + "%s: Failed to alloc cnt=%u alloc_cnt1=%u alloc_cnt2=%u\n", 3513 + __func__, cnt, alloc_cnt1, alloc_cnt2); 3514 + goto fail_free_alloc; 3515 + } 3516 + return 0; 3517 + 3518 + fail_free_alloc: 3519 + for (i = 0; i < alloc_cnt1 + alloc_cnt2; i++) { 3520 + rc = npc_mcam_idx_2_subbank_idx(rvu, save[i], 3521 + &sb, &sb_off); 3522 + if (rc) { 3523 + dev_err(rvu->dev, 3524 + "%s: Error to find subbank for mcam idx=%u\n", 3525 + __func__, save[i]); 3526 + break; 3527 + } 3528 + 3529 + deleted = __npc_subbank_free(rvu, sb, sb_off); 3530 + if (!deleted) { 3531 + dev_err(rvu->dev, 3532 + "%s: Error to free mcam idx=%u\n", 3533 + __func__, save[i]); 3534 + break; 3535 + } 3536 + } 3537 + 3538 + return rc; 3539 + } 3540 + 3541 + static int npc_defrag_add_2_show_list(struct rvu *rvu, u16 old_midx, 3542 + u16 new_midx, u16 vidx) 3543 + { 3544 + struct npc_defrag_show_node *node; 3545 + 3546 + node = kcalloc(1, sizeof(*node), GFP_KERNEL); 3547 + if (!node) 3548 + return -ENOMEM; 3549 + 3550 + node->old_midx = old_midx; 3551 + node->new_midx = new_midx; 3552 + node->vidx = vidx; 3553 + INIT_LIST_HEAD(&node->list); 3554 + 3555 + mutex_lock(&npc_priv.lock); 3556 + list_add_tail(&node->list, &npc_priv.defrag_lh); 3557 + mutex_unlock(&npc_priv.lock); 3558 + 3559 + return 0; 3560 + } 3561 + 3562 + static 3563 + int npc_defrag_move_vdx_to_free(struct rvu *rvu, 3564 + struct npc_defrag_node *f, 3565 + struct npc_defrag_node *v, 3566 + int cnt, u16 *save) 3567 + { 3568 + struct npc_mcam *mcam = &rvu->hw->mcam; 3569 + int i, vidx_cnt, rc, sb_off; 3570 + u16 new_midx, old_midx, vidx; 3571 + struct npc_subbank *sb; 3572 + bool deleted; 3573 + u16 pcifunc; 3574 + int blkaddr; 3575 + void *map; 3576 + u8 bank; 3577 + u16 midx; 3578 + u64 stats; 3579 + 3580 + blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); 3581 + 3582 + vidx_cnt = v->vidx_cnt; 3583 + for (i = 0; i < cnt; i++) { 3584 + vidx = v->vidx[vidx_cnt - i - 1]; 3585 + old_midx = npc_vidx2idx(vidx); 3586 + new_midx = save[cnt - i - 1]; 3587 + 3588 + dev_dbg(rvu->dev, 3589 + "%s: Moving %u ---> %u (vidx=%u)\n", 3590 + __func__, 3591 + old_midx, new_midx, vidx); 3592 + 3593 + rc = npc_defrag_add_2_show_list(rvu, old_midx, new_midx, vidx); 3594 + if (rc) 3595 + dev_err(rvu->dev, 3596 + "%s: Error happened to add to show list vidx=%u\n", 3597 + __func__, vidx); 3598 + 3599 + /* Modify vidx to point to new mcam idx */ 3600 + rc = npc_vidx_maps_modify(rvu, vidx, new_midx); 3601 + if (rc) 3602 + return rc; 3603 + 3604 + midx = old_midx % mcam->banksize; 3605 + bank = old_midx / mcam->banksize; 3606 + stats = rvu_read64(rvu, blkaddr, 3607 + NPC_AF_CN20K_MCAMEX_BANKX_STAT_EXT(midx, 3608 + bank)); 3609 + 3610 + npc_cn20k_enable_mcam_entry(rvu, blkaddr, old_midx, false); 3611 + npc_cn20k_copy_mcam_entry(rvu, blkaddr, old_midx, new_midx); 3612 + npc_cn20k_enable_mcam_entry(rvu, blkaddr, new_midx, true); 3613 + 3614 + midx = new_midx % mcam->banksize; 3615 + bank = new_midx / mcam->banksize; 3616 + rvu_write64(rvu, blkaddr, 3617 + NPC_AF_CN20K_MCAMEX_BANKX_STAT_EXT(midx, bank), 3618 + stats); 3619 + 3620 + /* Free the old mcam idx */ 3621 + rc = npc_mcam_idx_2_subbank_idx(rvu, old_midx, 3622 + &sb, &sb_off); 3623 + if (rc) { 3624 + dev_err(rvu->dev, 3625 + "%s: Unable to calculate subbank off for mcamidx=%u\n", 3626 + __func__, old_midx); 3627 + return rc; 3628 + } 3629 + 3630 + deleted = __npc_subbank_free(rvu, sb, sb_off); 3631 + if (!deleted) { 3632 + dev_err(rvu->dev, 3633 + "%s: Failed to free mcamidx=%u sb=%u sb_off=%u\n", 3634 + __func__, old_midx, sb->idx, sb_off); 3635 + return -EFAULT; 3636 + } 3637 + 3638 + /* save pcifunc */ 3639 + map = xa_load(&npc_priv.xa_idx2pf_map, old_midx); 3640 + pcifunc = xa_to_value(map); 3641 + 3642 + /* delete from pf maps */ 3643 + rc = npc_del_from_pf_maps(rvu, old_midx); 3644 + if (rc) { 3645 + dev_err(rvu->dev, 3646 + "%s: Failed to delete pf maps for mcamidx=%u\n", 3647 + __func__, old_midx); 3648 + return rc; 3649 + } 3650 + 3651 + /* add new mcam_idx to pf map */ 3652 + rc = npc_add_to_pf_maps(rvu, new_midx, pcifunc); 3653 + if (rc) { 3654 + dev_err(rvu->dev, 3655 + "%s: Failed to add pf maps for mcamidx=%u\n", 3656 + __func__, new_midx); 3657 + return rc; 3658 + } 3659 + 3660 + /* Remove from mcam maps */ 3661 + mcam->entry2pfvf_map[old_midx] = NPC_MCAM_INVALID_MAP; 3662 + mcam->entry2cntr_map[old_midx] = NPC_MCAM_INVALID_MAP; 3663 + npc_mcam_clear_bit(mcam, old_midx); 3664 + 3665 + mcam->entry2pfvf_map[new_midx] = pcifunc; 3666 + /* Counter is not preserved */ 3667 + mcam->entry2cntr_map[new_midx] = new_midx; 3668 + npc_mcam_set_bit(mcam, new_midx); 3669 + 3670 + /* Mark as invalid */ 3671 + v->vidx[vidx_cnt - i - 1] = -1; 3672 + save[cnt - i - 1] = -1; 3673 + 3674 + f->free_cnt--; 3675 + v->vidx_cnt--; 3676 + } 3677 + 3678 + return 0; 3679 + } 3680 + 3681 + static int npc_defrag_process(struct rvu *rvu, struct list_head *lh) 3682 + { 3683 + struct npc_defrag_node *v = NULL; 3684 + struct npc_defrag_node *f = NULL; 3685 + int rc = 0, cnt; 3686 + u16 *save; 3687 + 3688 + while (1) { 3689 + /* Find subbank with minimum vidx */ 3690 + if (!v) { 3691 + v = npc_subbank_min_vidx(lh); 3692 + if (!v) 3693 + break; 3694 + } 3695 + 3696 + /* Find subbank with maximum free slots */ 3697 + if (!f) { 3698 + f = npc_subbank_max_free(lh); 3699 + if (!f) 3700 + break; 3701 + } 3702 + 3703 + if (!v->vidx_cnt) { 3704 + list_del_init(&v->list); 3705 + v = NULL; 3706 + continue; 3707 + } 3708 + 3709 + if (!f->free_cnt) { 3710 + list_del_init(&f->list); 3711 + f = NULL; 3712 + continue; 3713 + } 3714 + 3715 + /* If both subbanks are same, choose vidx and 3716 + * search for free list again 3717 + */ 3718 + if (f == v) { 3719 + list_del_init(&f->list); 3720 + f = NULL; 3721 + continue; 3722 + } 3723 + 3724 + /* Calculate minimum free slots needs to be allocated */ 3725 + cnt = f->free_cnt > v->vidx_cnt ? v->vidx_cnt : 3726 + f->free_cnt; 3727 + 3728 + dev_dbg(rvu->dev, 3729 + "%s: cnt=%u free_cnt=%u(sb=%u) vidx_cnt=%u(sb=%u)\n", 3730 + __func__, cnt, f->free_cnt, f->idx, 3731 + v->vidx_cnt, v->idx); 3732 + 3733 + /* Allocate an array to store newly allocated 3734 + * free slots (mcam indexes) 3735 + */ 3736 + save = kcalloc(cnt, sizeof(*save), GFP_KERNEL); 3737 + if (!save) { 3738 + rc = -ENOMEM; 3739 + goto err; 3740 + } 3741 + 3742 + /* Alloc free slots for existing vidx */ 3743 + rc = npc_defrag_alloc_free_slots(rvu, f, cnt, save); 3744 + if (rc) { 3745 + kfree(save); 3746 + goto err; 3747 + } 3748 + 3749 + /* Move vidx to free slots; update pf_map and vidx maps, 3750 + * and free existing vidx mcam slots 3751 + */ 3752 + rc = npc_defrag_move_vdx_to_free(rvu, f, v, cnt, save); 3753 + if (rc) { 3754 + kfree(save); 3755 + goto err; 3756 + } 3757 + 3758 + kfree(save); 3759 + 3760 + if (!f->free_cnt) { 3761 + list_del_init(&f->list); 3762 + f = NULL; 3763 + } 3764 + 3765 + if (!v->vidx_cnt) { 3766 + list_del_init(&v->list); 3767 + v = NULL; 3768 + } 3769 + } 3770 + 3771 + err: 3772 + /* Whole defragmentation process is done within locks. if there 3773 + * is an error, it would be hard to roll back as index remove/add 3774 + * can fail again if it failed before. This would mean that there 3775 + * is bug in the index management algorithm. 3776 + * Return from here than rolling back. 3777 + */ 3778 + return rc; 3779 + } 3780 + 3781 + static void npc_defrag_list_clear(void) 3782 + { 3783 + struct npc_defrag_show_node *node, *next; 3784 + 3785 + mutex_lock(&npc_priv.lock); 3786 + list_for_each_entry_safe(node, next, &npc_priv.defrag_lh, list) { 3787 + list_del_init(&node->list); 3788 + kfree(node); 3789 + } 3790 + 3791 + mutex_unlock(&npc_priv.lock); 3792 + } 3793 + 3794 + static void npc_lock_all_subbank(void) 3795 + { 3796 + int i; 3797 + 3798 + for (i = 0; i < npc_priv.num_subbanks; i++) 3799 + mutex_lock(&npc_priv.sb[i].lock); 3800 + } 3801 + 3802 + static void npc_unlock_all_subbank(void) 3803 + { 3804 + int i; 3805 + 3806 + for (i = npc_priv.num_subbanks - 1; i >= 0; i--) 3807 + mutex_unlock(&npc_priv.sb[i].lock); 3808 + } 3809 + 3810 + /* Only non-ref non-contigous mcam indexes 3811 + * are picked for defrag process 3812 + */ 3813 + int npc_cn20k_defrag(struct rvu *rvu) 3814 + { 3815 + struct npc_mcam *mcam = &rvu->hw->mcam; 3816 + struct npc_defrag_node *node, *tnode; 3817 + struct list_head x4lh, x2lh, *lh; 3818 + int rc = 0, i, sb_off, tot; 3819 + struct npc_subbank *sb; 3820 + unsigned long index; 3821 + void *map; 3822 + u16 midx; 3823 + 3824 + /* Free previous show list */ 3825 + npc_defrag_list_clear(); 3826 + 3827 + INIT_LIST_HEAD(&x4lh); 3828 + INIT_LIST_HEAD(&x2lh); 3829 + 3830 + node = kcalloc(npc_priv.num_subbanks, sizeof(*node), GFP_KERNEL); 3831 + if (!node) 3832 + return -ENOMEM; 3833 + 3834 + /* Lock mcam */ 3835 + mutex_lock(&mcam->lock); 3836 + npc_lock_all_subbank(); 3837 + 3838 + /* Fill in node with subbank properties */ 3839 + for (i = 0; i < npc_priv.num_subbanks; i++) { 3840 + sb = &npc_priv.sb[i]; 3841 + 3842 + node[i].idx = i; 3843 + node[i].key_type = sb->key_type; 3844 + node[i].free_cnt = sb->free_cnt; 3845 + node[i].vidx = kcalloc(npc_priv.subbank_depth * 2, 3846 + sizeof(*node[i].vidx), 3847 + GFP_KERNEL); 3848 + if (!node[i].vidx) { 3849 + rc = -ENOMEM; 3850 + goto free_vidx; 3851 + } 3852 + 3853 + /* If subbank is empty, dont include it in defrag 3854 + * process 3855 + */ 3856 + if (sb->flags & NPC_SUBBANK_FLAG_FREE) { 3857 + node[i].valid = false; 3858 + continue; 3859 + } 3860 + 3861 + if (npc_defrag_skip_restricted_sb(i)) { 3862 + node[i].valid = false; 3863 + continue; 3864 + } 3865 + 3866 + node[i].valid = true; 3867 + INIT_LIST_HEAD(&node[i].list); 3868 + 3869 + /* Add node to x2 or x4 list */ 3870 + lh = sb->key_type == NPC_MCAM_KEY_X2 ? &x2lh : &x4lh; 3871 + list_add_tail(&node[i].list, lh); 3872 + } 3873 + 3874 + /* Filling vidx[] array with all vidx in that subbank */ 3875 + xa_for_each_start(&npc_priv.xa_vidx2idx_map, index, map, 3876 + npc_priv.bank_depth * 2) { 3877 + midx = xa_to_value(map); 3878 + rc = npc_mcam_idx_2_subbank_idx(rvu, midx, 3879 + &sb, &sb_off); 3880 + if (rc) { 3881 + dev_err(rvu->dev, 3882 + "%s: Error to get mcam_idx for vidx=%lu\n", 3883 + __func__, index); 3884 + goto free_vidx; 3885 + } 3886 + 3887 + tnode = &node[sb->idx]; 3888 + tnode->vidx[tnode->vidx_cnt] = index; 3889 + tnode->vidx_cnt++; 3890 + } 3891 + 3892 + /* Mark all subbank which has ref allocation */ 3893 + for (i = 0; i < npc_priv.num_subbanks; i++) { 3894 + tnode = &node[i]; 3895 + 3896 + if (!tnode->valid) 3897 + continue; 3898 + 3899 + tot = (tnode->key_type == NPC_MCAM_KEY_X2) ? 3900 + npc_priv.subbank_depth * 2 : npc_priv.subbank_depth; 3901 + 3902 + if (node[i].vidx_cnt != tot - tnode->free_cnt) 3903 + tnode->refs = true; 3904 + } 3905 + 3906 + rc = npc_defrag_process(rvu, &x2lh); 3907 + if (rc) 3908 + goto free_vidx; 3909 + 3910 + rc = npc_defrag_process(rvu, &x4lh); 3911 + if (rc) 3912 + goto free_vidx; 3913 + 3914 + free_vidx: 3915 + npc_unlock_all_subbank(); 3916 + mutex_unlock(&mcam->lock); 3917 + for (i = 0; i < npc_priv.num_subbanks; i++) 3918 + kfree(node[i].vidx); 3919 + kfree(node); 3920 + return rc; 3921 + } 3922 + 3923 + int rvu_mbox_handler_npc_defrag(struct rvu *rvu, struct msg_req *req, 3924 + struct msg_rsp *rsp) 3925 + { 3926 + return npc_cn20k_defrag(rvu); 3927 + } 3928 + 3929 + int npc_cn20k_dft_rules_idx_get(struct rvu *rvu, u16 pcifunc, u16 *bcast, 3930 + u16 *mcast, u16 *promisc, u16 *ucast) 3931 + { 3932 + u16 *ptr[4] = {promisc, mcast, bcast, ucast}; 3933 + unsigned long idx; 3934 + bool set = false; 3935 + void *val; 3936 + int i, j; 3937 + 3938 + if (!npc_priv.init_done) 3939 + return 0; 3940 + 3941 + if (is_lbk_vf(rvu, pcifunc)) { 3942 + if (!ptr[0]) 3943 + return -EINVAL; 3944 + 3945 + idx = NPC_DFT_RULE_ID_MK(pcifunc, NPC_DFT_RULE_PROMISC_ID); 3946 + val = xa_load(&npc_priv.xa_pf2dfl_rmap, idx); 3947 + if (!val) { 3948 + pr_debug("%s: Failed to find %s index for pcifunc=%#x\n", 3949 + __func__, 3950 + npc_dft_rule_name[NPC_DFT_RULE_PROMISC_ID], 3951 + pcifunc); 3952 + 3953 + *ptr[0] = USHRT_MAX; 3954 + return -ESRCH; 3955 + } 3956 + 3957 + *ptr[0] = xa_to_value(val); 3958 + return 0; 3959 + } 3960 + 3961 + if (is_vf(pcifunc)) { 3962 + if (!ptr[3]) 3963 + return -EINVAL; 3964 + 3965 + idx = NPC_DFT_RULE_ID_MK(pcifunc, NPC_DFT_RULE_UCAST_ID); 3966 + val = xa_load(&npc_priv.xa_pf2dfl_rmap, idx); 3967 + if (!val) { 3968 + pr_debug("%s: Failed to find %s index for pcifunc=%#x\n", 3969 + __func__, 3970 + npc_dft_rule_name[NPC_DFT_RULE_UCAST_ID], 3971 + pcifunc); 3972 + 3973 + *ptr[3] = USHRT_MAX; 3974 + return -ESRCH; 3975 + } 3976 + 3977 + *ptr[3] = xa_to_value(val); 3978 + return 0; 3979 + } 3980 + 3981 + for (i = NPC_DFT_RULE_START_ID, j = 0; i < NPC_DFT_RULE_MAX_ID; i++, 3982 + j++) { 3983 + if (!ptr[j]) 3984 + continue; 3985 + 3986 + idx = NPC_DFT_RULE_ID_MK(pcifunc, i); 3987 + val = xa_load(&npc_priv.xa_pf2dfl_rmap, idx); 3988 + if (!val) { 3989 + pr_debug("%s: Failed to find %s index for pcifunc=%#x\n", 3990 + __func__, 3991 + npc_dft_rule_name[i], pcifunc); 3992 + 3993 + *ptr[j] = USHRT_MAX; 3994 + continue; 3995 + } 3996 + 3997 + *ptr[j] = xa_to_value(val); 3998 + set = true; 3999 + } 4000 + 4001 + return set ? 0 : -ESRCH; 4002 + } 4003 + 4004 + int rvu_mbox_handler_npc_get_pfl_info(struct rvu *rvu, struct msg_req *req, 4005 + struct npc_get_pfl_info_rsp *rsp) 4006 + { 4007 + if (!is_cn20k(rvu->pdev)) { 4008 + dev_err(rvu->dev, "Mbox support is only for cn20k\n"); 4009 + return -EOPNOTSUPP; 4010 + } 4011 + 4012 + rsp->kw_type = npc_priv.kw; 4013 + rsp->x4_slots = npc_priv.bank_depth; 4014 + return 0; 4015 + } 4016 + 4017 + int rvu_mbox_handler_npc_get_num_kws(struct rvu *rvu, 4018 + struct npc_get_num_kws_req *req, 4019 + struct npc_get_num_kws_rsp *rsp) 4020 + { 4021 + u64 kw_mask[NPC_KWS_IN_KEY_SZ_MAX] = { 0 }; 4022 + u64 kw[NPC_KWS_IN_KEY_SZ_MAX] = { 0 }; 4023 + struct rvu_npc_mcam_rule dummy = { 0 }; 4024 + struct mcam_entry_mdata mdata = { }; 4025 + struct npc_install_flow_req *fl; 4026 + int i, cnt = 0, blkaddr; 4027 + 4028 + if (!is_cn20k(rvu->pdev)) { 4029 + dev_err(rvu->dev, "Mbox support is only for cn20k\n"); 4030 + return -EOPNOTSUPP; 4031 + } 4032 + 4033 + fl = &req->fl; 4034 + 4035 + blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); 4036 + if (blkaddr < 0) { 4037 + dev_err(rvu->dev, "%s: NPC block not implemented\n", __func__); 4038 + return NPC_MCAM_INVALID_REQ; 4039 + } 4040 + 4041 + mdata.kw = kw; 4042 + mdata.kw_mask = kw_mask; 4043 + 4044 + npc_update_flow(rvu, &mdata, fl->features, &fl->packet, 4045 + &fl->mask, &dummy, fl->intf, blkaddr); 4046 + 4047 + /* Find the most significant word valid. Traverse from 4048 + * MSB to LSB, check if cam0 or cam1 is set 4049 + */ 4050 + for (i = NPC_KWS_IN_KEY_SZ_MAX - 1; i >= 0; i--) { 4051 + if (kw[i] || kw_mask[i]) { 4052 + cnt = i + 1; 4053 + break; 4054 + } 4055 + } 4056 + 4057 + rsp->kws = cnt; 4058 + 4059 + return 0; 4060 + } 4061 + 4062 + int rvu_mbox_handler_npc_get_dft_rl_idxs(struct rvu *rvu, struct msg_req *req, 4063 + struct npc_get_dft_rl_idxs_rsp *rsp) 4064 + { 4065 + u16 bcast, mcast, promisc, ucast; 4066 + u16 pcifunc; 4067 + int rc; 4068 + 4069 + if (!is_cn20k(rvu->pdev)) { 4070 + dev_err(rvu->dev, "Mbox support is only for cn20k\n"); 4071 + return -EOPNOTSUPP; 4072 + } 4073 + 4074 + pcifunc = req->hdr.pcifunc; 4075 + 4076 + rc = npc_cn20k_dft_rules_idx_get(rvu, pcifunc, &bcast, &mcast, 4077 + &promisc, &ucast); 4078 + if (rc) 4079 + return rc; 4080 + 4081 + rsp->bcast = bcast; 4082 + rsp->mcast = mcast; 4083 + rsp->promisc = promisc; 4084 + rsp->ucast = ucast; 4085 + return 0; 4086 + } 4087 + 4088 + static bool npc_is_cgx_or_lbk(struct rvu *rvu, u16 pcifunc) 4089 + { 4090 + return is_pf_cgxmapped(rvu, rvu_get_pf(rvu->pdev, pcifunc)) || 4091 + is_lbk_vf(rvu, pcifunc); 4092 + } 4093 + 4094 + void npc_cn20k_dft_rules_free(struct rvu *rvu, u16 pcifunc) 4095 + { 4096 + struct npc_mcam_free_entry_req free_req = { 0 }; 4097 + unsigned long index; 4098 + struct msg_rsp rsp; 4099 + u16 ptr[4]; 4100 + int rc, i; 4101 + void *map; 4102 + 4103 + if (!npc_priv.init_done) 4104 + return; 4105 + 4106 + if (!npc_is_cgx_or_lbk(rvu, pcifunc)) { 4107 + dev_dbg(rvu->dev, 4108 + "%s: dft rule allocation is only for cgx mapped device, pcifunc=%#x\n", 4109 + __func__, pcifunc); 4110 + return; 4111 + } 4112 + 4113 + rc = npc_cn20k_dft_rules_idx_get(rvu, pcifunc, &ptr[0], &ptr[1], 4114 + &ptr[2], &ptr[3]); 4115 + if (rc) 4116 + return; 4117 + 4118 + /* LBK */ 4119 + if (is_lbk_vf(rvu, pcifunc)) { 4120 + index = NPC_DFT_RULE_ID_MK(pcifunc, NPC_DFT_RULE_PROMISC_ID); 4121 + map = xa_erase(&npc_priv.xa_pf2dfl_rmap, index); 4122 + if (!map) 4123 + dev_dbg(rvu->dev, 4124 + "%s: Err from delete %s mcam idx from xarray (pcifunc=%#x\n", 4125 + __func__, 4126 + npc_dft_rule_name[NPC_DFT_RULE_PROMISC_ID], 4127 + pcifunc); 4128 + 4129 + goto free_rules; 4130 + } 4131 + 4132 + /* VF */ 4133 + if (is_vf(pcifunc)) { 4134 + index = NPC_DFT_RULE_ID_MK(pcifunc, NPC_DFT_RULE_UCAST_ID); 4135 + map = xa_erase(&npc_priv.xa_pf2dfl_rmap, index); 4136 + if (!map) 4137 + dev_dbg(rvu->dev, 4138 + "%s: Err from delete %s mcam idx from xarray (pcifunc=%#x\n", 4139 + __func__, 4140 + npc_dft_rule_name[NPC_DFT_RULE_UCAST_ID], 4141 + pcifunc); 4142 + 4143 + goto free_rules; 4144 + } 4145 + 4146 + /* PF */ 4147 + for (i = NPC_DFT_RULE_START_ID; i < NPC_DFT_RULE_MAX_ID; i++) { 4148 + index = NPC_DFT_RULE_ID_MK(pcifunc, i); 4149 + map = xa_erase(&npc_priv.xa_pf2dfl_rmap, index); 4150 + if (!map) 4151 + dev_dbg(rvu->dev, 4152 + "%s: Err from delete %s mcam idx from xarray (pcifunc=%#x\n", 4153 + __func__, npc_dft_rule_name[i], 4154 + pcifunc); 4155 + } 4156 + 4157 + free_rules: 4158 + 4159 + free_req.hdr.pcifunc = pcifunc; 4160 + free_req.all = 1; 4161 + rc = rvu_mbox_handler_npc_mcam_free_entry(rvu, &free_req, &rsp); 4162 + if (rc) 4163 + dev_err(rvu->dev, 4164 + "%s: Error deleting default entries (pcifunc=%#x\n", 4165 + __func__, pcifunc); 4166 + } 4167 + 4168 + int npc_cn20k_dft_rules_alloc(struct rvu *rvu, u16 pcifunc) 4169 + { 4170 + struct npc_mcam_free_entry_req free_req = { 0 }; 4171 + u16 mcam_idx[4] = { 0 }, pf_ucast, pf_pcifunc; 4172 + struct npc_mcam_alloc_entry_req req = { 0 }; 4173 + struct npc_mcam_alloc_entry_rsp rsp = { 0 }; 4174 + int ret, eidx, i, k, pf, cnt; 4175 + struct rvu_pfvf *pfvf; 4176 + unsigned long index; 4177 + struct msg_rsp free_rsp; 4178 + u16 b, m, p, u; 4179 + 4180 + if (!npc_priv.init_done) 4181 + return 0; 4182 + 4183 + if (!npc_is_cgx_or_lbk(rvu, pcifunc)) { 4184 + dev_dbg(rvu->dev, 4185 + "%s: dft rule allocation is only for cgx mapped device, pcifunc=%#x\n", 4186 + __func__, pcifunc); 4187 + return 0; 4188 + } 4189 + 4190 + /* Check if default rules are already alloced for this pcifunc */ 4191 + ret = npc_cn20k_dft_rules_idx_get(rvu, pcifunc, &b, &m, &p, &u); 4192 + if (!ret) { 4193 + dev_dbg(rvu->dev, 4194 + "%s: default rules are already installed (pcifunc=%#x)\n", 4195 + __func__, pcifunc); 4196 + dev_dbg(rvu->dev, 4197 + "%s: bcast(%u) mcast(%u) promisc(%u) ucast(%u)\n", 4198 + __func__, b, m, p, u); 4199 + return 0; 4200 + } 4201 + 4202 + /* Set ref index as lowest priority index */ 4203 + eidx = 2 * npc_priv.bank_depth - 1; 4204 + 4205 + /* Install only UCAST for VF */ 4206 + cnt = is_vf(pcifunc) ? 1 : ARRAY_SIZE(mcam_idx); 4207 + 4208 + /* For VF pcifunc, allocate default mcam indexes by taking 4209 + * ref as PF's ucast index. 4210 + */ 4211 + if (is_vf(pcifunc)) { 4212 + pf = rvu_get_pf(rvu->pdev, pcifunc); 4213 + pf_pcifunc = pf << RVU_CN20K_PFVF_PF_SHIFT; 4214 + 4215 + /* Get PF's ucast entry index */ 4216 + ret = npc_cn20k_dft_rules_idx_get(rvu, pf_pcifunc, NULL, 4217 + NULL, NULL, &pf_ucast); 4218 + 4219 + /* There is no PF rules installed; and VF installation comes 4220 + * first. PF may come later. 4221 + * TODO: Install PF rules before installing VF rules. 4222 + */ 4223 + 4224 + /* Set PF's ucast as ref entry */ 4225 + if (!ret) 4226 + eidx = pf_ucast; 4227 + } 4228 + 4229 + pfvf = rvu_get_pfvf(rvu, pcifunc); 4230 + pfvf->hw_prio = NPC_DFT_RULE_PRIO; 4231 + 4232 + req.contig = false; 4233 + req.ref_prio = NPC_MCAM_HIGHER_PRIO; 4234 + req.ref_entry = eidx; 4235 + req.kw_type = NPC_MCAM_KEY_X2; 4236 + req.count = cnt; 4237 + req.hdr.pcifunc = pcifunc; 4238 + 4239 + ret = rvu_mbox_handler_npc_mcam_alloc_entry(rvu, &req, &rsp); 4240 + 4241 + /* successfully allocated index */ 4242 + if (!ret) { 4243 + /* Copy indexes to local array */ 4244 + for (i = 0; i < cnt; i++) 4245 + mcam_idx[i] = rsp.entry_list[i]; 4246 + 4247 + goto chk_sanity; 4248 + } 4249 + 4250 + /* If there is no slots available and request is for PF, 4251 + * return error. 4252 + */ 4253 + if (!is_vf(pcifunc)) { 4254 + dev_err(rvu->dev, 4255 + "%s: Default index allocation failed for pcifunc=%#x\n", 4256 + __func__, pcifunc); 4257 + return ret; 4258 + } 4259 + 4260 + /* We could not find an index with higher priority index for VF. 4261 + * Find rule with lower priority index and set hardware priority 4262 + * as NPC_DFT_RULE_PRIO - 1 (higher hw priority) 4263 + */ 4264 + req.contig = false; 4265 + req.kw_type = NPC_MCAM_KEY_X2; 4266 + req.count = cnt; 4267 + req.hdr.pcifunc = pcifunc; 4268 + req.ref_prio = NPC_MCAM_LOWER_PRIO; 4269 + req.ref_entry = eidx + 1; 4270 + ret = rvu_mbox_handler_npc_mcam_alloc_entry(rvu, &req, &rsp); 4271 + if (ret) { 4272 + dev_err(rvu->dev, 4273 + "%s: Default index allocation failed for pcifunc=%#x\n", 4274 + __func__, pcifunc); 4275 + return ret; 4276 + } 4277 + 4278 + /* Copy indexes to local array */ 4279 + for (i = 0; i < cnt; i++) 4280 + mcam_idx[i] = rsp.entry_list[i]; 4281 + 4282 + pfvf->hw_prio = NPC_DFT_RULE_PRIO - 1; 4283 + 4284 + chk_sanity: 4285 + /* LBK */ 4286 + if (is_lbk_vf(rvu, pcifunc)) { 4287 + index = NPC_DFT_RULE_ID_MK(pcifunc, NPC_DFT_RULE_PROMISC_ID); 4288 + ret = xa_insert(&npc_priv.xa_pf2dfl_rmap, index, 4289 + xa_mk_value(mcam_idx[0]), GFP_KERNEL); 4290 + if (ret) { 4291 + dev_err(rvu->dev, 4292 + "%s: Err to insert %s mcam idx to xarray pcifunc=%#x\n", 4293 + __func__, 4294 + npc_dft_rule_name[NPC_DFT_RULE_PROMISC_ID], 4295 + pcifunc); 4296 + goto err; 4297 + } 4298 + 4299 + goto done; 4300 + } 4301 + 4302 + /* VF */ 4303 + if (is_vf(pcifunc)) { 4304 + index = NPC_DFT_RULE_ID_MK(pcifunc, NPC_DFT_RULE_UCAST_ID); 4305 + ret = xa_insert(&npc_priv.xa_pf2dfl_rmap, index, 4306 + xa_mk_value(mcam_idx[0]), GFP_KERNEL); 4307 + if (ret) { 4308 + dev_err(rvu->dev, 4309 + "%s: Err to insert %s mcam idx to xarray pcifunc=%#x\n", 4310 + __func__, 4311 + npc_dft_rule_name[NPC_DFT_RULE_UCAST_ID], 4312 + pcifunc); 4313 + goto err; 4314 + } 4315 + 4316 + goto done; 4317 + } 4318 + 4319 + /* PF */ 4320 + for (i = NPC_DFT_RULE_START_ID, k = 0; i < NPC_DFT_RULE_MAX_ID && 4321 + k < cnt; i++, k++) { 4322 + index = NPC_DFT_RULE_ID_MK(pcifunc, i); 4323 + ret = xa_insert(&npc_priv.xa_pf2dfl_rmap, index, 4324 + xa_mk_value(mcam_idx[k]), GFP_KERNEL); 4325 + if (ret) { 4326 + dev_err(rvu->dev, 4327 + "%s: Err to insert %s mcam idx to xarray pcifunc=%#x\n", 4328 + __func__, npc_dft_rule_name[i], 4329 + pcifunc); 4330 + for (int p = NPC_DFT_RULE_START_ID; p < i; p++) { 4331 + index = NPC_DFT_RULE_ID_MK(pcifunc, p); 4332 + xa_erase(&npc_priv.xa_pf2dfl_rmap, index); 4333 + } 4334 + goto err; 4335 + } 4336 + } 4337 + 4338 + done: 4339 + return 0; 4340 + 4341 + err: 4342 + free_req.hdr.pcifunc = pcifunc; 4343 + free_req.all = 1; 4344 + ret = rvu_mbox_handler_npc_mcam_free_entry(rvu, &free_req, &free_rsp); 4345 + if (ret) 4346 + dev_err(rvu->dev, 4347 + "%s: Error deleting default entries (pcifunc=%#x\n", 4348 + __func__, pcifunc); 4349 + 4350 + return -EFAULT; 4351 + } 4352 + 4353 + static int npc_priv_init(struct rvu *rvu) 4354 + { 4355 + struct npc_mcam *mcam = &rvu->hw->mcam; 4356 + int blkaddr, num_banks, bank_depth; 4357 + int num_subbanks, subbank_depth; 4358 + u64 npc_const1, npc_const2 = 0; 4359 + struct npc_subbank *sb; 4360 + u64 cfg; 4361 + int i; 4362 + 4363 + blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); 4364 + if (blkaddr < 0) { 4365 + dev_err(rvu->dev, "%s: NPC block not implemented\n", 4366 + __func__); 4367 + return -ENODEV; 4368 + } 4369 + 4370 + npc_const1 = rvu_read64(rvu, blkaddr, NPC_AF_CONST1); 4371 + if (npc_const1 & BIT_ULL(63)) 4372 + npc_const2 = rvu_read64(rvu, blkaddr, NPC_AF_CONST2); 4373 + 4374 + num_banks = mcam->banks; 4375 + bank_depth = mcam->banksize; 4376 + 4377 + num_subbanks = FIELD_GET(GENMASK_ULL(39, 32), npc_const2); 4378 + if (!num_subbanks) { 4379 + dev_err(rvu->dev, "Number of subbanks is zero\n"); 4380 + return -EFAULT; 4381 + } 4382 + 4383 + if (num_subbanks & (num_subbanks - 1)) { 4384 + dev_err(rvu->dev, 4385 + "subbanks cnt(%u) should be a power of 2\n", 4386 + num_subbanks); 4387 + return -EINVAL; 4388 + } 4389 + 4390 + npc_priv.num_subbanks = num_subbanks; 4391 + 4392 + subbank_depth = bank_depth / num_subbanks; 4393 + 4394 + npc_priv.bank_depth = bank_depth; 4395 + npc_priv.subbank_depth = subbank_depth; 4396 + 4397 + /* Get kex configured key size */ 4398 + cfg = rvu_read64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(0)); 4399 + npc_priv.kw = FIELD_GET(GENMASK_ULL(34, 32), cfg); 4400 + 4401 + dev_info(rvu->dev, 4402 + "banks=%u depth=%u, subbanks=%u depth=%u, key type=%s\n", 4403 + num_banks, bank_depth, num_subbanks, subbank_depth, 4404 + npc_kw_name[npc_priv.kw]); 4405 + 4406 + npc_priv.sb = kcalloc(num_subbanks, sizeof(struct npc_subbank), 4407 + GFP_KERNEL); 4408 + if (!npc_priv.sb) 4409 + return -ENOMEM; 4410 + 4411 + xa_init_flags(&npc_priv.xa_sb_used, XA_FLAGS_ALLOC); 4412 + xa_init_flags(&npc_priv.xa_sb_free, XA_FLAGS_ALLOC); 4413 + xa_init_flags(&npc_priv.xa_idx2pf_map, XA_FLAGS_ALLOC); 4414 + xa_init_flags(&npc_priv.xa_pf_map, XA_FLAGS_ALLOC); 4415 + xa_init_flags(&npc_priv.xa_pf2dfl_rmap, XA_FLAGS_ALLOC); 4416 + xa_init_flags(&npc_priv.xa_idx2vidx_map, XA_FLAGS_ALLOC); 4417 + xa_init_flags(&npc_priv.xa_vidx2idx_map, XA_FLAGS_ALLOC); 4418 + 4419 + if (npc_create_srch_order(num_subbanks)) 4420 + goto fail1; 4421 + 4422 + npc_populate_restricted_idxs(num_subbanks); 4423 + 4424 + /* Initialize subbanks */ 4425 + for (i = 0, sb = npc_priv.sb; i < num_subbanks; i++, sb++) 4426 + npc_subbank_init(rvu, sb, i); 4427 + 4428 + /* Get number of pcifuncs in the system */ 4429 + npc_priv.pf_cnt = npc_pcifunc_map_create(rvu); 4430 + npc_priv.xa_pf2idx_map = kcalloc(npc_priv.pf_cnt, 4431 + sizeof(struct xarray), 4432 + GFP_KERNEL); 4433 + if (!npc_priv.xa_pf2idx_map) 4434 + goto fail2; 4435 + 4436 + for (i = 0; i < npc_priv.pf_cnt; i++) 4437 + xa_init_flags(&npc_priv.xa_pf2idx_map[i], XA_FLAGS_ALLOC); 4438 + 4439 + INIT_LIST_HEAD(&npc_priv.defrag_lh); 4440 + mutex_init(&npc_priv.lock); 4441 + 4442 + return 0; 4443 + 4444 + fail2: 4445 + kfree(subbank_srch_order); 4446 + subbank_srch_order = NULL; 4447 + 4448 + fail1: 4449 + xa_destroy(&npc_priv.xa_sb_used); 4450 + xa_destroy(&npc_priv.xa_sb_free); 4451 + xa_destroy(&npc_priv.xa_idx2pf_map); 4452 + xa_destroy(&npc_priv.xa_pf_map); 4453 + xa_destroy(&npc_priv.xa_pf2dfl_rmap); 4454 + xa_destroy(&npc_priv.xa_idx2vidx_map); 4455 + xa_destroy(&npc_priv.xa_vidx2idx_map); 4456 + kfree(npc_priv.sb); 4457 + npc_priv.sb = NULL; 4458 + return -ENOMEM; 4459 + } 4460 + 4461 + void npc_cn20k_deinit(struct rvu *rvu) 4462 + { 4463 + int i; 4464 + 4465 + xa_destroy(&npc_priv.xa_sb_used); 4466 + xa_destroy(&npc_priv.xa_sb_free); 4467 + xa_destroy(&npc_priv.xa_idx2pf_map); 4468 + xa_destroy(&npc_priv.xa_pf_map); 4469 + xa_destroy(&npc_priv.xa_pf2dfl_rmap); 4470 + xa_destroy(&npc_priv.xa_idx2vidx_map); 4471 + xa_destroy(&npc_priv.xa_vidx2idx_map); 4472 + 4473 + for (i = 0; i < npc_priv.pf_cnt; i++) 4474 + xa_destroy(&npc_priv.xa_pf2idx_map[i]); 4475 + 4476 + kfree(npc_priv.xa_pf2idx_map); 4477 + /* No need to destroy mutex lock as it is 4478 + * part of subbank structure 4479 + */ 4480 + kfree(npc_priv.sb); 4481 + kfree(subbank_srch_order); 4482 + } 4483 + 4484 + static int npc_setup_mcam_section(struct rvu *rvu, int key_type) 4485 + { 4486 + int blkaddr, sec; 4487 + 4488 + blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); 4489 + if (blkaddr < 0) { 4490 + dev_err(rvu->dev, "%s: NPC block not implemented\n", __func__); 4491 + return -ENODEV; 4492 + } 4493 + 4494 + for (sec = 0; sec < npc_priv.num_subbanks; sec++) 4495 + rvu_write64(rvu, blkaddr, 4496 + NPC_AF_MCAM_SECTIONX_CFG_EXT(sec), key_type); 4497 + 4498 + return 0; 4499 + } 4500 + 4501 + int npc_cn20k_init(struct rvu *rvu) 4502 + { 4503 + int err; 4504 + 4505 + err = npc_priv_init(rvu); 4506 + if (err) { 4507 + dev_err(rvu->dev, "%s: Error to init\n", 4508 + __func__); 4509 + return err; 4510 + } 4511 + 4512 + err = npc_setup_mcam_section(rvu, NPC_MCAM_KEY_X2); 4513 + if (err) { 4514 + dev_err(rvu->dev, "%s: mcam section configuration failure\n", 4515 + __func__); 4516 + return err; 4517 + } 4518 + 4519 + npc_priv.init_done = true; 4520 + 4521 + return 0; 4522 + }
+340
drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Marvell RVU Admin Function driver 3 + * 4 + * Copyright (C) 2026 Marvell. 5 + * 6 + */ 7 + 8 + #ifndef NPC_CN20K_H 9 + #define NPC_CN20K_H 10 + 11 + #define MKEX_CN20K_SIGN 0x19bbfdbd160 12 + 13 + #define MAX_NUM_BANKS 2 14 + #define MAX_NUM_SUB_BANKS 32 15 + #define MAX_SUBBANK_DEPTH 256 16 + 17 + /* strtoull of "mkexprof" with base:36 */ 18 + #define MKEX_END_SIGN 0xdeadbeef 19 + 20 + #define NPC_CN20K_BYTESM GENMASK_ULL(18, 16) 21 + #define NPC_CN20K_PARSE_NIBBLE GENMASK_ULL(22, 0) 22 + #define NPC_CN20K_TOTAL_NIBBLE 23 23 + 24 + #define CN20K_SET_EXTR_LT(intf, extr, ltype, cfg) \ 25 + rvu_write64(rvu, BLKADDR_NPC, \ 26 + NPC_AF_INTFX_EXTRACTORX_LTX_CFG(intf, extr, ltype), cfg) 27 + 28 + #define CN20K_GET_KEX_CFG(intf) \ 29 + rvu_read64(rvu, BLKADDR_NPC, NPC_AF_INTFX_KEX_CFG(intf)) 30 + 31 + #define CN20K_GET_EXTR_LID(intf, extr) \ 32 + rvu_read64(rvu, BLKADDR_NPC, \ 33 + NPC_AF_INTFX_EXTRACTORX_CFG(intf, extr)) 34 + 35 + #define CN20K_SET_EXTR_LT(intf, extr, ltype, cfg) \ 36 + rvu_write64(rvu, BLKADDR_NPC, \ 37 + NPC_AF_INTFX_EXTRACTORX_LTX_CFG(intf, extr, ltype), cfg) 38 + 39 + #define CN20K_GET_EXTR_LT(intf, extr, ltype) \ 40 + rvu_read64(rvu, BLKADDR_NPC, \ 41 + NPC_AF_INTFX_EXTRACTORX_LTX_CFG(intf, extr, ltype)) 42 + 43 + /* NPC_PARSE_KEX_S nibble definitions for each field */ 44 + #define NPC_CN20K_PARSE_NIBBLE_CHAN GENMASK_ULL(2, 0) 45 + #define NPC_CN20K_PARSE_NIBBLE_ERRLEV BIT_ULL(3) 46 + #define NPC_CN20K_PARSE_NIBBLE_ERRCODE GENMASK_ULL(5, 4) 47 + #define NPC_CN20K_PARSE_NIBBLE_L2L3_BCAST BIT_ULL(6) 48 + #define NPC_CN20K_PARSE_NIBBLE_LA_FLAGS BIT_ULL(7) 49 + #define NPC_CN20K_PARSE_NIBBLE_LA_LTYPE BIT_ULL(8) 50 + #define NPC_CN20K_PARSE_NIBBLE_LB_FLAGS BIT_ULL(9) 51 + #define NPC_CN20K_PARSE_NIBBLE_LB_LTYPE BIT_ULL(10) 52 + #define NPC_CN20K_PARSE_NIBBLE_LC_FLAGS BIT_ULL(11) 53 + #define NPC_CN20K_PARSE_NIBBLE_LC_LTYPE BIT_ULL(12) 54 + #define NPC_CN20K_PARSE_NIBBLE_LD_FLAGS BIT_ULL(13) 55 + #define NPC_CN20K_PARSE_NIBBLE_LD_LTYPE BIT_ULL(14) 56 + #define NPC_CN20K_PARSE_NIBBLE_LE_FLAGS BIT_ULL(15) 57 + #define NPC_CN20K_PARSE_NIBBLE_LE_LTYPE BIT_ULL(16) 58 + #define NPC_CN20K_PARSE_NIBBLE_LF_FLAGS BIT_ULL(17) 59 + #define NPC_CN20K_PARSE_NIBBLE_LF_LTYPE BIT_ULL(18) 60 + #define NPC_CN20K_PARSE_NIBBLE_LG_FLAGS BIT_ULL(19) 61 + #define NPC_CN20K_PARSE_NIBBLE_LG_LTYPE BIT_ULL(20) 62 + #define NPC_CN20K_PARSE_NIBBLE_LH_FLAGS BIT_ULL(21) 63 + #define NPC_CN20K_PARSE_NIBBLE_LH_LTYPE BIT_ULL(22) 64 + 65 + /* Rx parse key extract nibble enable */ 66 + #define NPC_CN20K_PARSE_NIBBLE_INTF_RX (NPC_CN20K_PARSE_NIBBLE_CHAN | \ 67 + NPC_CN20K_PARSE_NIBBLE_L2L3_BCAST | \ 68 + NPC_CN20K_PARSE_NIBBLE_LA_LTYPE | \ 69 + NPC_CN20K_PARSE_NIBBLE_LB_LTYPE | \ 70 + NPC_CN20K_PARSE_NIBBLE_LC_FLAGS | \ 71 + NPC_CN20K_PARSE_NIBBLE_LC_LTYPE | \ 72 + NPC_CN20K_PARSE_NIBBLE_LD_LTYPE | \ 73 + NPC_CN20K_PARSE_NIBBLE_LE_LTYPE) 74 + 75 + /* Tx parse key extract nibble enable */ 76 + #define NPC_CN20K_PARSE_NIBBLE_INTF_TX (NPC_CN20K_PARSE_NIBBLE_LA_LTYPE | \ 77 + NPC_CN20K_PARSE_NIBBLE_LB_LTYPE | \ 78 + NPC_CN20K_PARSE_NIBBLE_LC_LTYPE | \ 79 + NPC_CN20K_PARSE_NIBBLE_LD_LTYPE | \ 80 + NPC_CN20K_PARSE_NIBBLE_LE_LTYPE) 81 + 82 + /** 83 + * enum npc_subbank_flag - NPC subbank status 84 + * 85 + * subbank flag indicates whether the subbank is free 86 + * or used. 87 + * 88 + * @NPC_SUBBANK_FLAG_UNINIT: Subbank is not initialized. 89 + * @NPC_SUBBANK_FLAG_FREE: Subbank is free. 90 + * @NPC_SUBBANK_FLAG_USED: Subbank is used. 91 + */ 92 + enum npc_subbank_flag { 93 + NPC_SUBBANK_FLAG_UNINIT, 94 + NPC_SUBBANK_FLAG_FREE = BIT(0), 95 + NPC_SUBBANK_FLAG_USED = BIT(1), 96 + }; 97 + 98 + /** 99 + * enum npc_dft_rule_id - Default rule type 100 + * 101 + * Mcam default rule type. 102 + * 103 + * @NPC_DFT_RULE_START_ID: Not used 104 + * @NPC_DFT_RULE_PROMISC_ID: promiscuous rule 105 + * @NPC_DFT_RULE_MCAST_ID: multicast rule 106 + * @NPC_DFT_RULE_BCAST_ID: broadcast rule 107 + * @NPC_DFT_RULE_UCAST_ID: unicast rule 108 + * @NPC_DFT_RULE_MAX_ID: Maximum index. 109 + */ 110 + enum npc_dft_rule_id { 111 + NPC_DFT_RULE_START_ID = 1, 112 + NPC_DFT_RULE_PROMISC_ID = NPC_DFT_RULE_START_ID, 113 + NPC_DFT_RULE_MCAST_ID, 114 + NPC_DFT_RULE_BCAST_ID, 115 + NPC_DFT_RULE_UCAST_ID, 116 + NPC_DFT_RULE_MAX_ID, 117 + }; 118 + 119 + /** 120 + * struct npc_subbank - Subbank fields. 121 + * @b0b: Subbanks bottom index for bank0 122 + * @b1b: Subbanks bottom index for bank1 123 + * @b0t: Subbanks top index for bank0 124 + * @b1t: Subbanks top index for bank1 125 + * @flags: Subbank flags 126 + * @lock: Mutex lock for flags and rsrc mofiication 127 + * @b0map: Bitmap map for bank0 indexes 128 + * @b1map: Bitmap map for bank1 indexes 129 + * @idx: Subbank index 130 + * @arr_idx: Index to the free array or used array 131 + * @free_cnt: Number of free slots in the subbank. 132 + * @key_type: X4 or X2 subbank. 133 + * 134 + * MCAM resource is divided horizontally into multiple subbanks and 135 + * Resource allocation from each subbank is managed by this data 136 + * structure. 137 + */ 138 + struct npc_subbank { 139 + u16 b0t, b0b, b1t, b1b; 140 + enum npc_subbank_flag flags; 141 + struct mutex lock; /* Protect subbank resources */ 142 + DECLARE_BITMAP(b0map, MAX_SUBBANK_DEPTH); 143 + DECLARE_BITMAP(b1map, MAX_SUBBANK_DEPTH); 144 + u16 idx; 145 + u16 arr_idx; 146 + u16 free_cnt; 147 + u8 key_type; 148 + }; 149 + 150 + /** 151 + * struct npc_defrag_show_node - Defragmentation show node 152 + * @old_midx: Old mcam index. 153 + * @new_midx: New mcam index. 154 + * @vidx: Virtual index 155 + * @list: Linked list of these nodes 156 + * 157 + * This structure holds information on last defragmentation 158 + * executed on mcam resource. 159 + */ 160 + struct npc_defrag_show_node { 161 + u16 old_midx; 162 + u16 new_midx; 163 + u16 vidx; 164 + struct list_head list; 165 + }; 166 + 167 + /** 168 + * struct npc_priv_t - NPC private structure. 169 + * @bank_depth: Total entries in each bank. 170 + * @num_banks: Number of banks. 171 + * @num_subbanks: Number of subbanks. 172 + * @subbank_depth: Depth of subbank. 173 + * @kw: Kex configured key type. 174 + * @sb: Subbank array. 175 + * @xa_sb_used: Array of used subbanks. 176 + * @xa_sb_free: Array of free subbanks. 177 + * @xa_pf2idx_map: PF to mcam index map. 178 + * @xa_idx2pf_map: Mcam index to PF map. 179 + * @xa_pf_map: Pcifunc to index map. 180 + * @pf_cnt: Number of PFs. 181 + * @init_done: Indicates MCAM initialization is done. 182 + * @xa_pf2dfl_rmap: PF to default rule index map. 183 + * @xa_idx2vidx_map: Mcam index to virtual index map. 184 + * @xa_vidx2idx_map: virtual index to mcam index map. 185 + * @defrag_lh: Defrag list head. 186 + * @lock: Lock for defrag list 187 + * 188 + * This structure is populated during probing time by reading 189 + * HW csr registers. 190 + */ 191 + struct npc_priv_t { 192 + int bank_depth; 193 + const int num_banks; 194 + int num_subbanks; 195 + int subbank_depth; 196 + u8 kw; 197 + struct npc_subbank *sb; 198 + struct xarray xa_sb_used; 199 + struct xarray xa_sb_free; 200 + struct xarray *xa_pf2idx_map; 201 + struct xarray xa_idx2pf_map; 202 + struct xarray xa_pf_map; 203 + struct xarray xa_pf2dfl_rmap; 204 + struct xarray xa_idx2vidx_map; 205 + struct xarray xa_vidx2idx_map; 206 + struct list_head defrag_lh; 207 + struct mutex lock; /* protect defrag nodes */ 208 + int pf_cnt; 209 + bool init_done; 210 + }; 211 + 212 + struct npc_kpm_action0 { 213 + #if defined(__BIG_ENDIAN_BITFIELD) 214 + u64 rsvd_63_57 : 7; 215 + u64 byp_count : 3; 216 + u64 capture_ena : 1; 217 + u64 parse_done : 1; 218 + u64 next_state : 8; 219 + u64 rsvd_43 : 1; 220 + u64 capture_lid : 3; 221 + u64 capture_ltype : 4; 222 + u64 rsvd_32_35 : 4; 223 + u64 capture_flags : 4; 224 + u64 ptr_advance : 8; 225 + u64 var_len_offset : 8; 226 + u64 var_len_mask : 8; 227 + u64 var_len_right : 1; 228 + u64 var_len_shift : 3; 229 + #else 230 + u64 var_len_shift : 3; 231 + u64 var_len_right : 1; 232 + u64 var_len_mask : 8; 233 + u64 var_len_offset : 8; 234 + u64 ptr_advance : 8; 235 + u64 capture_flags : 4; 236 + u64 rsvd_32_35 : 4; 237 + u64 capture_ltype : 4; 238 + u64 capture_lid : 3; 239 + u64 rsvd_43 : 1; 240 + u64 next_state : 8; 241 + u64 parse_done : 1; 242 + u64 capture_ena : 1; 243 + u64 byp_count : 3; 244 + u64 rsvd_63_57 : 7; 245 + #endif 246 + }; 247 + 248 + struct npc_mcam_kex_extr { 249 + /* MKEX Profle Header */ 250 + u64 mkex_sign; /* "mcam-kex-profile" (8 bytes/ASCII characters) */ 251 + u8 name[MKEX_NAME_LEN]; /* MKEX Profile name */ 252 + u64 cpu_model; /* Format as profiled by CPU hardware */ 253 + u64 kpu_version; /* KPU firmware/profile version */ 254 + u64 reserved; /* Reserved for extension */ 255 + 256 + /* MKEX Profle Data */ 257 + u64 keyx_cfg[NPC_MAX_INTF]; /* NPC_AF_INTF(0..1)_KEX_CFG */ 258 + #define NPC_MAX_EXTRACTOR 24 259 + /* MKEX Extractor data */ 260 + u64 intf_extr_lid[NPC_MAX_INTF][NPC_MAX_EXTRACTOR]; 261 + /* KEX configuration per extractor */ 262 + u64 intf_extr_lt[NPC_MAX_INTF][NPC_MAX_EXTRACTOR][NPC_MAX_LT]; 263 + } __packed; 264 + 265 + struct npc_cn20k_kpu_profile_fwdata { 266 + #define KPU_SIGN 0x00666f727075706b 267 + #define KPU_NAME_LEN 32 268 + /* Maximum number of custom KPU entries supported by 269 + * the built-in profile. 270 + */ 271 + #define KPU_CN20K_MAX_CST_ENT 6 272 + /* KPU Profle Header */ 273 + __le64 signature; /* "kpuprof\0" (8 bytes/ASCII characters) */ 274 + u8 name[KPU_NAME_LEN]; /* KPU Profile name */ 275 + __le64 version; /* KPU profile version */ 276 + u8 kpus; 277 + u8 reserved[7]; 278 + 279 + /* Default MKEX profile to be used with this KPU profile. May be 280 + * overridden with mkex_profile module parameter. 281 + * Format is same as for the MKEX profile to streamline processing. 282 + */ 283 + struct npc_mcam_kex_extr mkex; 284 + /* LTYPE values for specific HW offloaded protocols. */ 285 + struct npc_lt_def_cfg lt_def; 286 + /* Dynamically sized data: 287 + * Custom KPU CAM and ACTION configuration entries. 288 + * struct npc_kpu_fwdata kpu[kpus]; 289 + */ 290 + u8 data[]; 291 + } __packed; 292 + 293 + struct rvu; 294 + 295 + struct npc_priv_t *npc_priv_get(void); 296 + int npc_cn20k_init(struct rvu *rvu); 297 + void npc_cn20k_deinit(struct rvu *rvu); 298 + 299 + void npc_cn20k_subbank_calc_free(struct rvu *rvu, int *x2_free, 300 + int *x4_free, int *sb_free); 301 + 302 + int npc_cn20k_ref_idx_alloc(struct rvu *rvu, int pcifunc, int key_type, 303 + int prio, u16 *mcam_idx, int ref, int limit, 304 + bool contig, int count, bool virt); 305 + int npc_cn20k_idx_free(struct rvu *rvu, u16 *mcam_idx, int count); 306 + void npc_cn20k_parser_profile_init(struct rvu *rvu, int blkaddr); 307 + struct npc_mcam_kex_extr *npc_mkex_extr_default_get(void); 308 + void npc_cn20k_load_mkex_profile(struct rvu *rvu, int blkaddr, 309 + const char *mkex_profile); 310 + int npc_cn20k_apply_custom_kpu(struct rvu *rvu, 311 + struct npc_kpu_profile_adapter *profile); 312 + 313 + void 314 + npc_cn20k_update_action_entries_n_flags(struct rvu *rvu, 315 + struct npc_kpu_profile_adapter *pfl); 316 + 317 + int npc_cn20k_dft_rules_alloc(struct rvu *rvu, u16 pcifunc); 318 + void npc_cn20k_dft_rules_free(struct rvu *rvu, u16 pcifunc); 319 + 320 + int npc_cn20k_dft_rules_idx_get(struct rvu *rvu, u16 pcifunc, u16 *bcast, 321 + u16 *mcast, u16 *promisc, u16 *ucast); 322 + 323 + void npc_cn20k_config_mcam_entry(struct rvu *rvu, int blkaddr, int index, 324 + u8 intf, struct cn20k_mcam_entry *entry, 325 + bool enable, u8 hw_prio, u8 req_kw_type); 326 + void npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkaddr, 327 + int index, bool enable); 328 + void npc_cn20k_copy_mcam_entry(struct rvu *rvu, int blkaddr, 329 + u16 src, u16 dest); 330 + void npc_cn20k_read_mcam_entry(struct rvu *rvu, int blkaddr, u16 index, 331 + struct cn20k_mcam_entry *entry, u8 *intf, 332 + u8 *ena, u8 *hw_prio); 333 + void npc_cn20k_clear_mcam_entry(struct rvu *rvu, int blkaddr, 334 + int bank, int index); 335 + int npc_mcam_idx_2_key_type(struct rvu *rvu, u16 mcam_idx, u8 *key_type); 336 + u16 npc_cn20k_vidx2idx(u16 index); 337 + u16 npc_cn20k_idx2vidx(u16 idx); 338 + int npc_cn20k_defrag(struct rvu *rvu); 339 + 340 + #endif /* NPC_CN20K_H */
+65
drivers/net/ethernet/marvell/octeontx2/af/cn20k/reg.h
··· 78 78 #define RVU_MBOX_VF_INT_ENA_W1C (0x38) 79 79 80 80 #define RVU_MBOX_VF_VFAF_TRIGX(a) (0x2000 | (a) << 3) 81 + 82 + #define NIX_GINT_INT (0x200) 83 + #define NIX_GINT_INT_W1S (0x208) 84 + 85 + #define ALTAF_FLR BIT_ULL(0) 86 + #define ALTAF_RDY BIT_ULL(1) 87 + 88 + /* NPC registers */ 89 + #define NPC_AF_INTFX_EXTRACTORX_CFG(a, b) \ 90 + (0x20c000ull | (a) << 16 | (b) << 8) 91 + #define NPC_AF_INTFX_EXTRACTORX_LTX_CFG(a, b, c) \ 92 + (0x204000ull | (a) << 16 | (b) << 8 | (c) << 3) 93 + #define NPC_AF_KPMX_ENTRYX_CAMX(a, b, c) \ 94 + (0x20000ull | (a) << 12 | (b) << 3 | (c) << 16) 95 + #define NPC_AF_KPMX_ENTRYX_ACTION0(a, b) \ 96 + (0x40000ull | (a) << 12 | (b) << 3) 97 + #define NPC_AF_KPMX_ENTRYX_ACTION1(a, b) \ 98 + (0x50000ull | (a) << 12 | (b) << 3) 99 + #define NPC_AF_KPMX_ENTRY_DISX(a, b) (0x60000ull | (a) << 12 | (b) << 3) 100 + #define NPC_AF_KPM_PASS2_CFG 0x10210 101 + #define NPC_AF_KPMX_PASS2_OFFSET(a) (0x60040ull | (a) << 12) 102 + #define NPC_AF_MCAM_SECTIONX_CFG_EXT(a) (0xf000000ull | (a) << 3) 103 + 104 + #define NPC_AF_CN20K_MCAMEX_BANKX_CAMX_INTF_EXT(a, b, c) ({ \ 105 + u64 offset; \ 106 + offset = (0x8000000ull | (a) << 4 | (b) << 20 | (c) << 3); \ 107 + offset; }) 108 + 109 + #define NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W0_EXT(a, b, c) ({ \ 110 + u64 offset; \ 111 + offset = (0x9000000ull | (a) << 4 | (b) << 20 | (c) << 3); \ 112 + offset; }) 113 + 114 + #define NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W1_EXT(a, b, c) ({ \ 115 + u64 offset; \ 116 + offset = (0x9400000ull | (a) << 4 | (b) << 20 | (c) << 3); \ 117 + offset; }) 118 + 119 + #define NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W2_EXT(a, b, c) ({ \ 120 + u64 offset; \ 121 + offset = (0x9800000ull | (a) << 4 | (b) << 20 | (c) << 3); \ 122 + offset; }) 123 + 124 + #define NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W3_EXT(a, b, c) ({ \ 125 + u64 offset; \ 126 + offset = (0x9c00000ull | (a) << 4 | (b) << 20 | (c) << 3); \ 127 + offset; }) 128 + 129 + #define NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(a, b) ({ \ 130 + u64 offset; \ 131 + offset = (0xa000000ull | (a) << 4 | (b) << 20); \ 132 + offset; }) 133 + 134 + #define NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(a, b, c) ({ \ 135 + u64 offset; \ 136 + offset = (0xc000000ull | (a) << 4 | (b) << 20 | (c) << 22); \ 137 + offset; }) 138 + 139 + #define NPC_AF_INTFX_MISS_ACTX(a, b) (0xf003000 | (a) << 6 | (b) << 4) 140 + 141 + #define NPC_AF_CN20K_MCAMEX_BANKX_STAT_EXT(a, b) ({ \ 142 + u64 offset; \ 143 + offset = (0xb000000ull | (a) << 4 | (b) << 20); \ 144 + offset; }) 145 + 81 146 #endif /* RVU_MBOX_REG_H */
-4
drivers/net/ethernet/marvell/octeontx2/af/common.h
··· 177 177 #define NIX_TX_ACTIONOP_MCAST (0x3ull) 178 178 #define NIX_TX_ACTIONOP_DROP_VIOL (0x5ull) 179 179 180 - #define NPC_MCAM_KEY_X1 0 181 - #define NPC_MCAM_KEY_X2 1 182 - #define NPC_MCAM_KEY_X4 2 183 - 184 180 #define NIX_INTFX_RX(a) (0x0ull | (a) << 1) 185 181 #define NIX_INTFX_TX(a) (0x1ull | (a) << 1) 186 182
+167 -5
drivers/net/ethernet/marvell/octeontx2/af/mbox.h
··· 53 53 #define MBOX_DIR_VFPF_UP 7 /* VF replies to PF */ 54 54 55 55 enum { 56 + NPC_MCAM_KEY_X1 = 0, 57 + NPC_MCAM_KEY_DYN = NPC_MCAM_KEY_X1, 58 + NPC_MCAM_KEY_X2, 59 + NPC_MCAM_KEY_X4, 60 + NPC_MCAM_KEY_MAX, 61 + }; 62 + 63 + enum { 56 64 TYPE_AFVF, 57 65 TYPE_AFPF, 58 66 }; ··· 283 275 M(NPC_GET_FIELD_STATUS, 0x6014, npc_get_field_status, \ 284 276 npc_get_field_status_req, \ 285 277 npc_get_field_status_rsp) \ 278 + M(NPC_CN20K_MCAM_GET_FREE_COUNT, 0x6015, npc_cn20k_get_fcnt, \ 279 + msg_req, npc_cn20k_get_fcnt_rsp) \ 280 + M(NPC_CN20K_GET_KEX_CFG, 0x6016, npc_cn20k_get_kex_cfg, \ 281 + msg_req, npc_cn20k_get_kex_cfg_rsp) \ 282 + M(NPC_CN20K_MCAM_WRITE_ENTRY, 0x6017, npc_cn20k_mcam_write_entry, \ 283 + npc_cn20k_mcam_write_entry_req, msg_rsp) \ 284 + M(NPC_CN20K_MCAM_ALLOC_AND_WRITE_ENTRY, 0x6018, \ 285 + npc_cn20k_mcam_alloc_and_write_entry, \ 286 + npc_cn20k_mcam_alloc_and_write_entry_req, \ 287 + npc_mcam_alloc_and_write_entry_rsp) \ 288 + M(NPC_CN20K_MCAM_READ_ENTRY, 0x6019, npc_cn20k_mcam_read_entry, \ 289 + npc_mcam_read_entry_req, \ 290 + npc_cn20k_mcam_read_entry_rsp) \ 291 + M(NPC_CN20K_MCAM_READ_BASE_RULE, 0x601a, npc_cn20k_read_base_steer_rule, \ 292 + msg_req, npc_cn20k_mcam_read_base_rule_rsp) \ 293 + M(NPC_MCAM_DEFRAG, 0x601b, npc_defrag, \ 294 + msg_req, \ 295 + msg_rsp) \ 296 + M(NPC_MCAM_GET_NUM_KWS, 0x601c, npc_get_num_kws, \ 297 + npc_get_num_kws_req, \ 298 + npc_get_num_kws_rsp) \ 299 + M(NPC_MCAM_GET_DFT_RL_IDXS, 0x601d, npc_get_dft_rl_idxs, \ 300 + msg_req, \ 301 + npc_get_dft_rl_idxs_rsp)\ 302 + M(NPC_MCAM_GET_NPC_PFL_INFO, 0x601e, npc_get_pfl_info, \ 303 + msg_req, \ 304 + npc_get_pfl_info_rsp) \ 286 305 /* NIX mbox IDs (range 0x8000 - 0xFFFF) */ \ 287 306 M(NIX_LF_ALLOC, 0x8000, nix_lf_alloc, \ 288 307 nix_lf_alloc_req, nix_lf_alloc_rsp) \ ··· 1562 1527 #define NPC_MCAM_ANY_PRIO 0 1563 1528 #define NPC_MCAM_LOWER_PRIO 1 1564 1529 #define NPC_MCAM_HIGHER_PRIO 2 1565 - u8 priority; /* Lower or higher w.r.t ref_entry */ 1530 + u8 ref_prio; /* Lower or higher w.r.t ref_entry */ 1566 1531 u16 ref_entry; 1567 1532 u16 count; /* Number of entries requested */ 1533 + u8 kw_type; /* entry key type, valid for cn20k */ 1534 + u8 virt; /* Request virtual index */ 1568 1535 }; 1569 1536 1570 1537 struct npc_mcam_alloc_entry_rsp { ··· 1585 1548 u8 all; /* If all entries allocated to this PFVF to be freed */ 1586 1549 }; 1587 1550 1551 + struct mcam_entry_mdata { 1552 + u64 *kw; 1553 + u64 *kw_mask; 1554 + u64 *action; 1555 + u64 *vtag_action; 1556 + u8 max_kw; 1557 + }; 1558 + 1559 + enum npc_kws_in_key_sz { 1560 + NPC_KWS_IN_KEY_SZ_7 = 7, 1561 + NPC_KWS_IN_KEY_SZ_8 = 8, 1562 + NPC_KWS_IN_KEY_SZ_MAX, 1563 + }; 1564 + 1588 1565 struct mcam_entry { 1589 - #define NPC_MAX_KWS_IN_KEY 7 /* Number of keywords in max keywidth */ 1590 - u64 kw[NPC_MAX_KWS_IN_KEY]; 1591 - u64 kw_mask[NPC_MAX_KWS_IN_KEY]; 1566 + u64 kw[NPC_KWS_IN_KEY_SZ_7]; 1567 + u64 kw_mask[NPC_KWS_IN_KEY_SZ_7]; 1592 1568 u64 action; 1593 1569 u64 vtag_action; 1570 + }; 1571 + 1572 + struct cn20k_mcam_entry { 1573 + u64 kw[NPC_KWS_IN_KEY_SZ_8]; 1574 + u64 kw_mask[NPC_KWS_IN_KEY_SZ_8]; 1575 + u64 action; 1576 + u64 vtag_action; 1577 + u64 action2; 1578 + }; 1579 + 1580 + struct npc_cn20k_mcam_write_entry_req { 1581 + struct mbox_msghdr hdr; 1582 + struct cn20k_mcam_entry entry_data; 1583 + u16 entry; /* MCAM entry to write this match key */ 1584 + u16 cntr; /* Counter for this MCAM entry */ 1585 + u8 intf; /* Rx or Tx interface */ 1586 + u8 enable_entry;/* Enable this MCAM entry ? */ 1587 + u8 hw_prio; /* hardware priority, valid for cn20k */ 1588 + u8 req_kw_type; /* Type of kw which should be written */ 1589 + u64 reserved; /* reserved for future use */ 1594 1590 }; 1595 1591 1596 1592 struct npc_mcam_write_entry_req { ··· 1634 1564 u8 intf; /* Rx or Tx interface */ 1635 1565 u8 enable_entry;/* Enable this MCAM entry ? */ 1636 1566 u8 set_cntr; /* Set counter for this entry ? */ 1567 + u8 hw_prio; /* hardware priority, valid for cn20k */ 1568 + u64 reserved; /* reserved for future use */ 1637 1569 }; 1638 1570 1639 1571 /* Enable/Disable a given entry */ ··· 1694 1622 struct mbox_msghdr hdr; 1695 1623 struct mcam_entry entry_data; 1696 1624 u16 ref_entry; 1697 - u8 priority; /* Lower or higher w.r.t ref_entry */ 1625 + u8 ref_prio; /* Lower or higher w.r.t ref_entry */ 1698 1626 u8 intf; /* Rx or Tx interface */ 1699 1627 u8 enable_entry;/* Enable this MCAM entry ? */ 1700 1628 u8 alloc_cntr; /* Allocate counter and map ? */ 1629 + }; 1630 + 1631 + struct npc_cn20k_mcam_alloc_and_write_entry_req { 1632 + struct mbox_msghdr hdr; 1633 + struct cn20k_mcam_entry entry_data; 1634 + u16 ref_entry; 1635 + u8 ref_prio; /* Lower or higher w.r.t ref_entry */ 1636 + u8 intf; /* Rx or Tx interface */ 1637 + u8 enable_entry;/* Enable this MCAM entry ? */ 1638 + u8 hw_prio; /* hardware priority, valid for cn20k */ 1639 + u8 virt; /* Allocate virtual index */ 1640 + u8 req_kw_type; /* Key type to be written */ 1641 + u16 reserved[4]; /* reserved for future use */ 1642 + }; 1643 + 1644 + struct npc_cn20k_mcam_read_entry_rsp { 1645 + struct mbox_msghdr hdr; 1646 + struct cn20k_mcam_entry entry_data; 1647 + u8 intf; 1648 + u8 enable; 1649 + u8 hw_prio; /* valid for cn20k */ 1650 + }; 1651 + 1652 + struct npc_cn20k_mcam_read_base_rule_rsp { 1653 + struct mbox_msghdr hdr; 1654 + struct cn20k_mcam_entry entry; 1701 1655 }; 1702 1656 1703 1657 struct npc_mcam_alloc_and_write_entry_rsp { ··· 1747 1649 u64 intf_lid_lt_ld[NPC_MAX_INTF][NPC_MAX_LID][NPC_MAX_LT][NPC_MAX_LD]; 1748 1650 /* NPC_AF_INTF(0..1)_LDATA(0..1)_FLAGS(0..15)_CFG */ 1749 1651 u64 intf_ld_flags[NPC_MAX_INTF][NPC_MAX_LD][NPC_MAX_LFL]; 1652 + #define MKEX_NAME_LEN 128 1653 + u8 mkex_pfl_name[MKEX_NAME_LEN]; 1654 + }; 1655 + 1656 + struct npc_cn20k_get_kex_cfg_rsp { 1657 + struct mbox_msghdr hdr; 1658 + u64 rx_keyx_cfg; /* NPC_AF_INTF(0)_KEX_CFG */ 1659 + u64 tx_keyx_cfg; /* NPC_AF_INTF(1)_KEX_CFG */ 1660 + #define NPC_MAX_EXTRACTOR 24 1661 + /* MKEX Extractor data */ 1662 + u64 intf_extr_lid[NPC_MAX_INTF][NPC_MAX_EXTRACTOR]; 1663 + /* KEX configuration per extractor */ 1664 + u64 intf_extr_lt[NPC_MAX_INTF][NPC_MAX_EXTRACTOR][NPC_MAX_LT]; 1750 1665 #define MKEX_NAME_LEN 128 1751 1666 u8 mkex_pfl_name[MKEX_NAME_LEN]; 1752 1667 }; ··· 1876 1765 u8 vtag1_op; 1877 1766 /* old counter value */ 1878 1767 u16 cntr_val; 1768 + u8 hw_prio; 1769 + u8 req_kw_type; /* Key type to be written */ 1770 + u8 alloc_entry; /* only for cn20k */ 1771 + /* For now use any priority, once AF driver is changed to 1772 + * allocate least priority entry instead of mid zone then make 1773 + * NPC_MCAM_LEAST_PRIO as 3 1774 + */ 1775 + #define NPC_MCAM_LEAST_PRIO NPC_MCAM_ANY_PRIO 1776 + u16 ref_prio; 1777 + u16 ref_entry; 1879 1778 }; 1880 1779 1881 1780 struct npc_install_flow_rsp { 1882 1781 struct mbox_msghdr hdr; 1883 1782 int counter; /* negative if no counter else counter number */ 1783 + u16 entry; 1784 + u8 kw_type; 1785 + }; 1786 + 1787 + struct npc_get_num_kws_req { 1788 + struct mbox_msghdr hdr; 1789 + struct npc_install_flow_req fl; 1790 + u32 rsvd[4]; 1791 + }; 1792 + 1793 + struct npc_get_num_kws_rsp { 1794 + struct mbox_msghdr hdr; 1795 + int kws; 1796 + u32 rsvd[4]; 1797 + }; 1798 + 1799 + struct npc_get_dft_rl_idxs_rsp { 1800 + struct mbox_msghdr hdr; 1801 + u16 bcast; 1802 + u16 mcast; 1803 + u16 promisc; 1804 + u16 ucast; 1805 + u16 vf_ucast; 1806 + u16 rsvd[7]; 1807 + }; 1808 + 1809 + struct npc_get_pfl_info_rsp { 1810 + struct mbox_msghdr hdr; 1811 + u16 x4_slots; 1812 + u8 kw_type; 1813 + u8 rsvd1[3]; 1814 + u32 rsvd2[4]; 1884 1815 }; 1885 1816 1886 1817 struct npc_delete_flow_req { ··· 1948 1795 struct mcam_entry entry_data; 1949 1796 u8 intf; 1950 1797 u8 enable; 1798 + u8 hw_prio; /* valid for cn20k */ 1799 + }; 1800 + 1801 + /* Available entries to use */ 1802 + struct npc_cn20k_get_fcnt_rsp { 1803 + struct mbox_msghdr hdr; 1804 + int free_x2; 1805 + int free_x4; 1806 + int free_subbanks; 1951 1807 }; 1952 1808 1953 1809 struct npc_mcam_read_base_rule_rsp {
+2
drivers/net/ethernet/marvell/octeontx2/af/npc.h
··· 429 429 430 430 /* NPC_AF_INTFX_KEX_CFG field masks */ 431 431 #define NPC_PARSE_NIBBLE GENMASK_ULL(30, 0) 432 + #define NPC_TOTAL_NIBBLE 31 432 433 433 434 /* NPC_PARSE_KEX_S nibble definitions for each field */ 434 435 #define NPC_PARSE_NIBBLE_CHAN GENMASK_ULL(2, 0) ··· 644 643 u16 chan; 645 644 u16 chan_mask; 646 645 u8 lxmb; 646 + u8 hw_prio; 647 647 }; 648 648 649 649 #endif /* NPC_H */
+48 -36
drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h
··· 321 321 NPC_F_LB_L_FDSA, 322 322 }; 323 323 324 + enum npc_cn20k_kpu_lc_uflag { 325 + NPC_CN20K_F_LC_U_MPLS_IN_IP = 0x20, 326 + NPC_CN20K_F_LC_U_IP6_TUN_IP6 = 0x40, 327 + NPC_CN20K_F_LC_U_IP6_MPLS_IN_IP = 0x80, 328 + }; 329 + 330 + enum npc_cn20k_kpu_lc_lflag { 331 + NPC_CN20K_F_LC_L_IP_FRAG = 2, 332 + NPC_CN20K_F_LC_L_IP6_FRAG, 333 + NPC_CN20K_F_LC_L_6TO4, 334 + }; 335 + 324 336 enum npc_kpu_lc_uflag { 325 337 NPC_F_LC_U_UNK_PROTO = 0x10, 326 338 NPC_F_LC_U_IP_FRAG = 0x20, ··· 501 489 0, 0, 0, 0, \ 502 490 } 503 491 504 - static struct npc_kpu_profile_action ikpu_action_entries[] = { 492 + static struct npc_kpu_profile_action ikpu_action_entries[] __maybe_unused = { 505 493 { 506 494 NPC_ERRLEV_RE, NPC_EC_NOERR, 507 495 12, 16, 20, 0, 0, ··· 1080 1068 }, 1081 1069 }; 1082 1070 1083 - static struct npc_kpu_profile_cam kpu1_cam_entries[] = { 1071 + static struct npc_kpu_profile_cam kpu1_cam_entries[] __maybe_unused = { 1084 1072 NPC_KPU_NOP_CAM, 1085 1073 NPC_KPU_NOP_CAM, 1086 1074 NPC_KPU_NOP_CAM, ··· 1890 1878 }, 1891 1879 }; 1892 1880 1893 - static struct npc_kpu_profile_cam kpu2_cam_entries[] = { 1881 + static struct npc_kpu_profile_cam kpu2_cam_entries[] __maybe_unused = { 1894 1882 NPC_KPU_NOP_CAM, 1895 1883 NPC_KPU_NOP_CAM, 1896 1884 NPC_KPU_NOP_CAM, ··· 2835 2823 }, 2836 2824 }; 2837 2825 2838 - static struct npc_kpu_profile_cam kpu3_cam_entries[] = { 2826 + static struct npc_kpu_profile_cam kpu3_cam_entries[] __maybe_unused = { 2839 2827 NPC_KPU_NOP_CAM, 2840 2828 NPC_KPU_NOP_CAM, 2841 2829 NPC_KPU_NOP_CAM, ··· 3816 3804 }, 3817 3805 }; 3818 3806 3819 - static struct npc_kpu_profile_cam kpu4_cam_entries[] = { 3807 + static struct npc_kpu_profile_cam kpu4_cam_entries[] __maybe_unused = { 3820 3808 NPC_KPU_NOP_CAM, 3821 3809 NPC_KPU_NOP_CAM, 3822 3810 NPC_KPU_NOP_CAM, ··· 4131 4119 }, 4132 4120 }; 4133 4121 4134 - static struct npc_kpu_profile_cam kpu5_cam_entries[] = { 4122 + static struct npc_kpu_profile_cam kpu5_cam_entries[] __maybe_unused = { 4135 4123 NPC_KPU_NOP_CAM, 4136 4124 NPC_KPU_NOP_CAM, 4137 4125 NPC_KPU_NOP_CAM, ··· 5184 5172 }, 5185 5173 }; 5186 5174 5187 - static struct npc_kpu_profile_cam kpu6_cam_entries[] = { 5175 + static struct npc_kpu_profile_cam kpu6_cam_entries[] __maybe_unused = { 5188 5176 NPC_KPU_NOP_CAM, 5189 5177 NPC_KPU_NOP_CAM, 5190 5178 NPC_KPU_NOP_CAM, ··· 5913 5901 }, 5914 5902 }; 5915 5903 5916 - static struct npc_kpu_profile_cam kpu7_cam_entries[] = { 5904 + static struct npc_kpu_profile_cam kpu7_cam_entries[] __maybe_unused = { 5917 5905 NPC_KPU_NOP_CAM, 5918 5906 NPC_KPU_NOP_CAM, 5919 5907 NPC_KPU_NOP_CAM, ··· 6264 6252 }, 6265 6253 }; 6266 6254 6267 - static struct npc_kpu_profile_cam kpu8_cam_entries[] = { 6255 + static struct npc_kpu_profile_cam kpu8_cam_entries[] __maybe_unused = { 6268 6256 NPC_KPU_NOP_CAM, 6269 6257 NPC_KPU_NOP_CAM, 6270 6258 NPC_KPU_NOP_CAM, ··· 7101 7089 }, 7102 7090 }; 7103 7091 7104 - static struct npc_kpu_profile_cam kpu9_cam_entries[] = { 7092 + static struct npc_kpu_profile_cam kpu9_cam_entries[] __maybe_unused = { 7105 7093 NPC_KPU_NOP_CAM, 7106 7094 NPC_KPU_NOP_CAM, 7107 7095 NPC_KPU_NOP_CAM, ··· 7587 7575 }, 7588 7576 }; 7589 7577 7590 - static struct npc_kpu_profile_cam kpu10_cam_entries[] = { 7578 + static struct npc_kpu_profile_cam kpu10_cam_entries[] __maybe_unused = { 7591 7579 NPC_KPU_NOP_CAM, 7592 7580 NPC_KPU_NOP_CAM, 7593 7581 NPC_KPU_NOP_CAM, ··· 7758 7746 }, 7759 7747 }; 7760 7748 7761 - static struct npc_kpu_profile_cam kpu11_cam_entries[] = { 7749 + static struct npc_kpu_profile_cam kpu11_cam_entries[] __maybe_unused = { 7762 7750 NPC_KPU_NOP_CAM, 7763 7751 NPC_KPU_NOP_CAM, 7764 7752 NPC_KPU_NOP_CAM, ··· 8073 8061 }, 8074 8062 }; 8075 8063 8076 - static struct npc_kpu_profile_cam kpu12_cam_entries[] = { 8064 + static struct npc_kpu_profile_cam kpu12_cam_entries[] __maybe_unused = { 8077 8065 NPC_KPU_NOP_CAM, 8078 8066 NPC_KPU_NOP_CAM, 8079 8067 NPC_KPU_NOP_CAM, ··· 8334 8322 }, 8335 8323 }; 8336 8324 8337 - static struct npc_kpu_profile_cam kpu13_cam_entries[] = { 8325 + static struct npc_kpu_profile_cam kpu13_cam_entries[] __maybe_unused = { 8338 8326 NPC_KPU_NOP_CAM, 8339 8327 NPC_KPU_NOP_CAM, 8340 8328 NPC_KPU_NOP_CAM, ··· 8352 8340 }, 8353 8341 }; 8354 8342 8355 - static struct npc_kpu_profile_cam kpu14_cam_entries[] = { 8343 + static struct npc_kpu_profile_cam kpu14_cam_entries[] __maybe_unused = { 8356 8344 NPC_KPU_NOP_CAM, 8357 8345 NPC_KPU_NOP_CAM, 8358 8346 NPC_KPU_NOP_CAM, ··· 8370 8358 }, 8371 8359 }; 8372 8360 8373 - static struct npc_kpu_profile_cam kpu15_cam_entries[] = { 8361 + static struct npc_kpu_profile_cam kpu15_cam_entries[] __maybe_unused = { 8374 8362 NPC_KPU_NOP_CAM, 8375 8363 NPC_KPU_NOP_CAM, 8376 8364 NPC_KPU_NOP_CAM, ··· 8577 8565 }, 8578 8566 }; 8579 8567 8580 - static struct npc_kpu_profile_cam kpu16_cam_entries[] = { 8568 + static struct npc_kpu_profile_cam kpu16_cam_entries[] __maybe_unused = { 8581 8569 NPC_KPU_NOP_CAM, 8582 8570 NPC_KPU_NOP_CAM, 8583 8571 NPC_KPU_NOP_CAM, ··· 8640 8628 }, 8641 8629 }; 8642 8630 8643 - static struct npc_kpu_profile_action kpu1_action_entries[] = { 8631 + static struct npc_kpu_profile_action kpu1_action_entries[] __maybe_unused = { 8644 8632 NPC_KPU_NOP_ACTION, 8645 8633 NPC_KPU_NOP_ACTION, 8646 8634 NPC_KPU_NOP_ACTION, ··· 9380 9368 }, 9381 9369 }; 9382 9370 9383 - static struct npc_kpu_profile_action kpu2_action_entries[] = { 9371 + static struct npc_kpu_profile_action kpu2_action_entries[] __maybe_unused = { 9384 9372 NPC_KPU_NOP_ACTION, 9385 9373 NPC_KPU_NOP_ACTION, 9386 9374 NPC_KPU_NOP_ACTION, ··· 10221 10209 }, 10222 10210 }; 10223 10211 10224 - static struct npc_kpu_profile_action kpu3_action_entries[] = { 10212 + static struct npc_kpu_profile_action kpu3_action_entries[] __maybe_unused = { 10225 10213 NPC_KPU_NOP_ACTION, 10226 10214 NPC_KPU_NOP_ACTION, 10227 10215 NPC_KPU_NOP_ACTION, ··· 11094 11082 }, 11095 11083 }; 11096 11084 11097 - static struct npc_kpu_profile_action kpu4_action_entries[] = { 11085 + static struct npc_kpu_profile_action kpu4_action_entries[] __maybe_unused = { 11098 11086 NPC_KPU_NOP_ACTION, 11099 11087 NPC_KPU_NOP_ACTION, 11100 11088 NPC_KPU_NOP_ACTION, ··· 11375 11363 }, 11376 11364 }; 11377 11365 11378 - static struct npc_kpu_profile_action kpu5_action_entries[] = { 11366 + static struct npc_kpu_profile_action kpu5_action_entries[] __maybe_unused = { 11379 11367 NPC_KPU_NOP_ACTION, 11380 11368 NPC_KPU_NOP_ACTION, 11381 11369 NPC_KPU_NOP_ACTION, ··· 12312 12300 }, 12313 12301 }; 12314 12302 12315 - static struct npc_kpu_profile_action kpu6_action_entries[] = { 12303 + static struct npc_kpu_profile_action kpu6_action_entries[] __maybe_unused = { 12316 12304 NPC_KPU_NOP_ACTION, 12317 12305 NPC_KPU_NOP_ACTION, 12318 12306 NPC_KPU_NOP_ACTION, ··· 12961 12949 }, 12962 12950 }; 12963 12951 12964 - static struct npc_kpu_profile_action kpu7_action_entries[] = { 12952 + static struct npc_kpu_profile_action kpu7_action_entries[] __maybe_unused = { 12965 12953 NPC_KPU_NOP_ACTION, 12966 12954 NPC_KPU_NOP_ACTION, 12967 12955 NPC_KPU_NOP_ACTION, ··· 13274 13262 }, 13275 13263 }; 13276 13264 13277 - static struct npc_kpu_profile_action kpu8_action_entries[] = { 13265 + static struct npc_kpu_profile_action kpu8_action_entries[] __maybe_unused = { 13278 13266 NPC_KPU_NOP_ACTION, 13279 13267 NPC_KPU_NOP_ACTION, 13280 13268 NPC_KPU_NOP_ACTION, ··· 14019 14007 }, 14020 14008 }; 14021 14009 14022 - static struct npc_kpu_profile_action kpu9_action_entries[] = { 14010 + static struct npc_kpu_profile_action kpu9_action_entries[] __maybe_unused = { 14023 14011 NPC_KPU_NOP_ACTION, 14024 14012 NPC_KPU_NOP_ACTION, 14025 14013 NPC_KPU_NOP_ACTION, ··· 14452 14440 }, 14453 14441 }; 14454 14442 14455 - static struct npc_kpu_profile_action kpu10_action_entries[] = { 14443 + static struct npc_kpu_profile_action kpu10_action_entries[] __maybe_unused = { 14456 14444 NPC_KPU_NOP_ACTION, 14457 14445 NPC_KPU_NOP_ACTION, 14458 14446 NPC_KPU_NOP_ACTION, ··· 14605 14593 }, 14606 14594 }; 14607 14595 14608 - static struct npc_kpu_profile_action kpu11_action_entries[] = { 14596 + static struct npc_kpu_profile_action kpu11_action_entries[] __maybe_unused = { 14609 14597 NPC_KPU_NOP_ACTION, 14610 14598 NPC_KPU_NOP_ACTION, 14611 14599 NPC_KPU_NOP_ACTION, ··· 14886 14874 }, 14887 14875 }; 14888 14876 14889 - static struct npc_kpu_profile_action kpu12_action_entries[] = { 14877 + static struct npc_kpu_profile_action kpu12_action_entries[] __maybe_unused = { 14890 14878 NPC_KPU_NOP_ACTION, 14891 14879 NPC_KPU_NOP_ACTION, 14892 14880 NPC_KPU_NOP_ACTION, ··· 15119 15107 }, 15120 15108 }; 15121 15109 15122 - static struct npc_kpu_profile_action kpu13_action_entries[] = { 15110 + static struct npc_kpu_profile_action kpu13_action_entries[] __maybe_unused = { 15123 15111 NPC_KPU_NOP_ACTION, 15124 15112 NPC_KPU_NOP_ACTION, 15125 15113 NPC_KPU_NOP_ACTION, ··· 15136 15124 }, 15137 15125 }; 15138 15126 15139 - static struct npc_kpu_profile_action kpu14_action_entries[] = { 15127 + static struct npc_kpu_profile_action kpu14_action_entries[] __maybe_unused = { 15140 15128 NPC_KPU_NOP_ACTION, 15141 15129 NPC_KPU_NOP_ACTION, 15142 15130 NPC_KPU_NOP_ACTION, ··· 15153 15141 }, 15154 15142 }; 15155 15143 15156 - static struct npc_kpu_profile_action kpu15_action_entries[] = { 15144 + static struct npc_kpu_profile_action kpu15_action_entries[] __maybe_unused = { 15157 15145 NPC_KPU_NOP_ACTION, 15158 15146 NPC_KPU_NOP_ACTION, 15159 15147 NPC_KPU_NOP_ACTION, ··· 15338 15326 }, 15339 15327 }; 15340 15328 15341 - static struct npc_kpu_profile_action kpu16_action_entries[] = { 15329 + static struct npc_kpu_profile_action kpu16_action_entries[] __maybe_unused = { 15342 15330 NPC_KPU_NOP_ACTION, 15343 15331 NPC_KPU_NOP_ACTION, 15344 15332 NPC_KPU_NOP_ACTION, ··· 15395 15383 }, 15396 15384 }; 15397 15385 15398 - static struct npc_kpu_profile npc_kpu_profiles[] = { 15386 + static struct npc_kpu_profile npc_kpu_profiles[] __maybe_unused = { 15399 15387 { 15400 15388 ARRAY_SIZE(kpu1_cam_entries), 15401 15389 ARRAY_SIZE(kpu1_action_entries), ··· 15494 15482 }, 15495 15483 }; 15496 15484 15497 - static struct npc_lt_def_cfg npc_lt_defaults = { 15485 + static struct npc_lt_def_cfg npc_lt_defaults __maybe_unused = { 15498 15486 .rx_ol2 = { 15499 15487 .lid = NPC_LID_LA, 15500 15488 .ltype_match = NPC_LT_LA_ETHER, ··· 15616 15604 }, 15617 15605 }; 15618 15606 15619 - static struct npc_mcam_kex npc_mkex_default = { 15607 + static struct npc_mcam_kex npc_mkex_default __maybe_unused = { 15620 15608 .mkex_sign = MKEX_SIGN, 15621 15609 .name = "default", 15622 15610 .kpu_version = NPC_KPU_PROFILE_VER,
+100 -14
drivers/net/ethernet/marvell/octeontx2/af/rvu.c
··· 22 22 #include "rvu_npc_hash.h" 23 23 #include "cn20k/reg.h" 24 24 #include "cn20k/api.h" 25 + #include "cn20k/npc.h" 25 26 26 27 #define DRV_NAME "rvu_af" 27 28 #define DRV_STRING "Marvell OcteonTX2 RVU Admin Function Driver" ··· 600 599 601 600 static int rvu_setup_msix_resources(struct rvu *rvu) 602 601 { 602 + struct altaf_intr_notify *altaf_intr_data; 603 603 struct rvu_hwinfo *hw = rvu->hw; 604 604 int pf, vf, numvfs, hwvf, err; 605 605 int nvecs, offset, max_msix; ··· 707 705 rvu->msix_base_iova = iova; 708 706 rvu->msixtr_base_phy = phy_addr; 709 707 708 + if (is_rvu_otx2(rvu) || is_cn20k(rvu->pdev)) 709 + return 0; 710 + 711 + if (!rvu->fwdata) 712 + goto fail; 713 + 714 + altaf_intr_data = &rvu->fwdata->altaf_intr_info; 715 + if (altaf_intr_data->gint_paddr) { 716 + iova = dma_map_resource(rvu->dev, altaf_intr_data->gint_paddr, 717 + PCI_MSIX_ENTRY_SIZE, 718 + DMA_BIDIRECTIONAL, 0); 719 + 720 + if (dma_mapping_error(rvu->dev, iova)) 721 + goto fail; 722 + 723 + altaf_intr_data->gint_iova_addr = iova; 724 + } 725 + 710 726 return 0; 727 + 728 + fail: 729 + dma_unmap_resource(rvu->dev, phy_addr, max_msix * PCI_MSIX_ENTRY_SIZE, 730 + DMA_BIDIRECTIONAL, 0); 731 + return -EFAULT; 711 732 } 712 733 713 734 static void rvu_reset_msix(struct rvu *rvu) ··· 1421 1396 if (blkaddr < 0) 1422 1397 return; 1423 1398 1424 - 1425 1399 block = &hw->block[blkaddr]; 1426 1400 1427 1401 num_lfs = rvu_get_rsrc_mapcount(pfvf, block->addr); ··· 1491 1467 else if ((blkid == BLKADDR_CPT1) && !detach->cptlfs) 1492 1468 continue; 1493 1469 } 1470 + 1471 + if (detach_all || 1472 + (detach && (blkid == BLKADDR_NIX0 || 1473 + blkid == BLKADDR_NIX1) && 1474 + detach->nixlf)) 1475 + npc_cn20k_dft_rules_free(rvu, pcifunc); 1476 + 1494 1477 rvu_detach_block(rvu, pcifunc, block->type); 1495 1478 } 1496 1479 ··· 1781 1750 err = rvu_attach_block(rvu, pcifunc, BLKTYPE_NIX, 1, attach); 1782 1751 if (err) 1783 1752 goto fail2; 1753 + 1754 + if (is_cn20k(rvu->pdev)) { 1755 + err = npc_cn20k_dft_rules_alloc(rvu, pcifunc); 1756 + if (err) 1757 + goto fail3; 1758 + } 1784 1759 } 1785 1760 1786 1761 if (attach->sso) { ··· 1800 1763 err = rvu_attach_block(rvu, pcifunc, BLKTYPE_SSO, 1801 1764 attach->sso, attach); 1802 1765 if (err) 1803 - goto fail3; 1766 + goto fail4; 1804 1767 } 1805 1768 1806 1769 if (attach->ssow) { ··· 1809 1772 err = rvu_attach_block(rvu, pcifunc, BLKTYPE_SSOW, 1810 1773 attach->ssow, attach); 1811 1774 if (err) 1812 - goto fail4; 1775 + goto fail5; 1813 1776 } 1814 1777 1815 1778 if (attach->timlfs) { ··· 1818 1781 err = rvu_attach_block(rvu, pcifunc, BLKTYPE_TIM, 1819 1782 attach->timlfs, attach); 1820 1783 if (err) 1821 - goto fail5; 1784 + goto fail6; 1822 1785 } 1823 1786 1824 1787 if (attach->cptlfs) { ··· 1828 1791 err = rvu_attach_block(rvu, pcifunc, BLKTYPE_CPT, 1829 1792 attach->cptlfs, attach); 1830 1793 if (err) 1831 - goto fail6; 1794 + goto fail7; 1832 1795 } 1833 1796 1834 1797 mutex_unlock(&rvu->rsrc_lock); 1835 1798 return 0; 1836 1799 1837 - fail6: 1800 + fail7: 1838 1801 if (attach->timlfs) 1839 1802 rvu_detach_block(rvu, pcifunc, BLKTYPE_TIM); 1840 1803 1841 - fail5: 1804 + fail6: 1842 1805 if (attach->ssow) 1843 1806 rvu_detach_block(rvu, pcifunc, BLKTYPE_SSOW); 1844 1807 1845 - fail4: 1808 + fail5: 1846 1809 if (attach->sso) 1847 1810 rvu_detach_block(rvu, pcifunc, BLKTYPE_SSO); 1811 + 1812 + fail4: 1813 + if (is_cn20k(rvu->pdev)) 1814 + npc_cn20k_dft_rules_free(rvu, pcifunc); 1848 1815 1849 1816 fail3: 1850 1817 if (attach->nixlf) ··· 2226 2185 return 0; 2227 2186 } 2228 2187 2188 + static void rvu_notify_altaf(struct rvu *rvu, u16 pcifunc, u64 op) 2189 + { 2190 + int pf, vf; 2191 + 2192 + if (!rvu->fwdata) 2193 + return; 2194 + 2195 + if (op == ALTAF_FLR) { 2196 + pf = rvu_get_pf(rvu->pdev, pcifunc); 2197 + set_bit(pf, rvu->fwdata->altaf_intr_info.flr_pf_bmap); 2198 + if (pcifunc & RVU_PFVF_FUNC_MASK) { 2199 + vf = pcifunc & RVU_PFVF_FUNC_MASK; 2200 + if (vf >= 128) { 2201 + WARN(1, 2202 + "flr_vf_bmap size is 128 bits, vf=%u\n", 2203 + vf); 2204 + return; 2205 + } 2206 + 2207 + set_bit(vf, rvu->fwdata->altaf_intr_info.flr_vf_bmap); 2208 + } 2209 + } 2210 + 2211 + rvu_write64(rvu, BLKADDR_NIX0, AF_BAR2_ALIASX(0, NIX_GINT_INT_W1S), op); 2212 + usleep_range(5000, 6000); 2213 + } 2214 + 2229 2215 static int rvu_process_mbox_msg(struct otx2_mbox *mbox, int devid, 2230 2216 struct mbox_msghdr *req) 2231 2217 { ··· 2336 2268 2337 2269 offset = mbox->rx_start + ALIGN(sizeof(*req_hdr), MBOX_MSG_ALIGN); 2338 2270 2339 - if (req_hdr->sig && !(is_rvu_otx2(rvu) || is_cn20k(rvu->pdev))) { 2271 + if (req_hdr->sig && rvu->altaf_ready && 2272 + !(is_rvu_otx2(rvu) || is_cn20k(rvu->pdev))) { 2340 2273 req_hdr->opt_msg = mw->mbox_wrk[devid].num_msgs; 2341 2274 rvu_write64(rvu, BLKADDR_NIX0, RVU_AF_BAR2_SEL, 2342 2275 RVU_AF_BAR2_PFID); ··· 2846 2777 block = &rvu->hw->block[blkaddr]; 2847 2778 num_lfs = rvu_get_rsrc_mapcount(rvu_get_pfvf(rvu, pcifunc), 2848 2779 block->addr); 2780 + 2781 + if (block->addr == BLKADDR_TIM && rvu->altaf_ready) { 2782 + rvu_notify_altaf(rvu, pcifunc, ALTAF_FLR); 2783 + return; 2784 + } 2785 + 2786 + if ((block->addr == BLKADDR_SSO || block->addr == BLKADDR_SSOW) && 2787 + rvu->altaf_ready) 2788 + return; 2789 + 2849 2790 if (!num_lfs) 2850 2791 return; 2851 2792 for (slot = 0; slot < num_lfs; slot++) { ··· 3139 3060 3140 3061 static int rvu_register_interrupts(struct rvu *rvu) 3141 3062 { 3142 - int ret, offset, pf_vec_start; 3063 + int i, ret, offset, pf_vec_start; 3143 3064 3144 3065 rvu->num_vec = pci_msix_vec_count(rvu->pdev); 3145 3066 3146 - rvu->irq_name = devm_kmalloc_array(rvu->dev, rvu->num_vec, 3147 - NAME_SIZE, GFP_KERNEL); 3067 + rvu->irq_name = devm_kcalloc(rvu->dev, rvu->num_vec, 3068 + NAME_SIZE, GFP_KERNEL); 3148 3069 if (!rvu->irq_name) 3149 3070 return -ENOMEM; 3150 3071 ··· 3330 3251 if (ret) 3331 3252 goto fail; 3332 3253 3254 + for (i = 0; i < rvu->num_vec; i++) { 3255 + if (strstr(&rvu->irq_name[i * NAME_SIZE], "Mbox") || 3256 + strstr(&rvu->irq_name[i * NAME_SIZE], "FLR")) 3257 + irq_set_affinity(pci_irq_vector(rvu->pdev, i), 3258 + cpumask_of(0)); 3259 + } 3260 + 3333 3261 return 0; 3334 3262 3335 3263 fail: ··· 3365 3279 cfg | BIT_ULL(22)); 3366 3280 } 3367 3281 3368 - rvu->flr_wq = alloc_ordered_workqueue("rvu_afpf_flr", 3369 - WQ_HIGHPRI | WQ_MEM_RECLAIM); 3282 + rvu->flr_wq = alloc_workqueue("rvu_afpf_flr", 3283 + WQ_HIGHPRI | WQ_MEM_RECLAIM, 0); 3370 3284 if (!rvu->flr_wq) 3371 3285 return -ENOMEM; 3372 3286
+13 -5
drivers/net/ethernet/marvell/octeontx2/af/rvu.h
··· 197 197 /* Masks where all set bits indicate position 198 198 * of a field in the key 199 199 */ 200 - u64 kw_mask[NPC_MAX_KWS_IN_KEY]; 200 + u64 kw_mask[NPC_KWS_IN_KEY_SZ_MAX]; 201 201 /* Number of words in the key a field spans. If a field is 202 202 * of 16 bytes and key offset is 4 then the field will use 203 203 * 4 bytes in KW0, 8 bytes in KW1 and 4 bytes in KW2 and ··· 308 308 u64 lmt_map_ent_w1; /* Preseving the word1 of lmtst map table entry*/ 309 309 unsigned long flags; 310 310 struct sdp_node_info *sdp_info; 311 + u8 hw_prio; /* Hw priority of default rules */ 311 312 }; 312 313 313 314 enum rvu_pfvf_flags { ··· 448 447 u8 sdp_links; 449 448 u8 cpt_links; /* Number of CPT links */ 450 449 u8 npc_kpus; /* No of parser units */ 450 + u8 npc_kpms; /* Number of enhanced parser units */ 451 + u8 npc_kex_extr; /* Number of LDATA extractors per KEX */ 451 452 u8 npc_pkinds; /* No of port kinds */ 452 453 u8 npc_intfs; /* No of interfaces */ 453 - u8 npc_kpu_entries; /* No of KPU entries */ 454 + u16 npc_kpu_entries; /* No of KPU entries */ 454 455 u16 npc_counters; /* No of match stats counters */ 455 456 u32 lbk_bufsize; /* FIFO size supported by LBK */ 456 457 bool npc_ext_set; /* Extended register set */ ··· 555 552 const struct npc_lt_def_cfg *lt_def; 556 553 const struct npc_kpu_profile_action *ikpu; /* array[pkinds] */ 557 554 const struct npc_kpu_profile *kpu; /* array[kpus] */ 558 - struct npc_mcam_kex *mkex; 555 + union npc_mcam_key_prfl { 556 + struct npc_mcam_kex *mkex; 557 + /* used for cn9k and cn10k */ 558 + struct npc_mcam_kex_extr *mkex_extr; /* used for cn20k */ 559 + } mcam_kex_prfl; 559 560 struct npc_mcam_kex_hash *mkex_hash; 560 561 bool custom; 561 562 size_t pkinds; ··· 1124 1117 void rvu_mac_reset(struct rvu *rvu, u16 pcifunc); 1125 1118 u32 rvu_cgx_get_lmac_fifolen(struct rvu *rvu, int cgx, int lmac); 1126 1119 void cgx_start_linkup(struct rvu *rvu); 1127 - int npc_get_nixlf_mcam_index(struct npc_mcam *mcam, u16 pcifunc, int nixlf, 1128 - int type); 1120 + int npc_get_nixlf_mcam_index(struct npc_mcam *mcam, 1121 + u16 pcifunc, int nixlf, int type); 1129 1122 bool is_mcam_entry_enabled(struct rvu *rvu, struct npc_mcam *mcam, int blkaddr, 1130 1123 int index); 1131 1124 int rvu_npc_init(struct rvu *rvu); ··· 1191 1184 int rvu_rep_install_mcam_rules(struct rvu *rvu); 1192 1185 void rvu_rep_update_rules(struct rvu *rvu, u16 pcifunc, bool ena); 1193 1186 int rvu_rep_notify_pfvf_state(struct rvu *rvu, u16 pcifunc, bool enable); 1187 + int npc_mcam_verify_entry(struct npc_mcam *mcam, u16 pcifunc, int entry); 1194 1188 #endif /* RVU_H */
+58 -18
drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
··· 21 21 #include "rvu_npc_hash.h" 22 22 #include "mcs.h" 23 23 24 + #include "cn20k/reg.h" 24 25 #include "cn20k/debugfs.h" 26 + #include "cn20k/npc.h" 25 27 26 28 #define DEBUGFS_DIR_NAME "octeontx2" 27 29 ··· 3198 3196 static int rvu_dbg_npc_mcam_info_display(struct seq_file *filp, void *unsued) 3199 3197 { 3200 3198 struct rvu *rvu = filp->private; 3199 + int x4_free, x2_free, sb_free; 3201 3200 int pf, vf, numvfs, blkaddr; 3201 + struct npc_priv_t *npc_priv; 3202 3202 struct npc_mcam *mcam; 3203 3203 u16 pcifunc, counters; 3204 3204 u64 cfg; ··· 3214 3210 3215 3211 seq_puts(filp, "\nNPC MCAM info:\n"); 3216 3212 /* MCAM keywidth on receive and transmit sides */ 3217 - cfg = rvu_read64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(NIX_INTF_RX)); 3218 - cfg = (cfg >> 32) & 0x07; 3219 - seq_printf(filp, "\t\t RX keywidth \t: %s\n", (cfg == NPC_MCAM_KEY_X1) ? 3220 - "112bits" : ((cfg == NPC_MCAM_KEY_X2) ? 3221 - "224bits" : "448bits")); 3222 - cfg = rvu_read64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(NIX_INTF_TX)); 3223 - cfg = (cfg >> 32) & 0x07; 3224 - seq_printf(filp, "\t\t TX keywidth \t: %s\n", (cfg == NPC_MCAM_KEY_X1) ? 3225 - "112bits" : ((cfg == NPC_MCAM_KEY_X2) ? 3226 - "224bits" : "448bits")); 3213 + if (is_cn20k(rvu->pdev)) { 3214 + npc_priv = npc_priv_get(); 3215 + seq_printf(filp, "\t\t RX keywidth \t: %s\n", 3216 + (npc_priv->kw == NPC_MCAM_KEY_X1) ? 3217 + "256bits" : "512bits"); 3218 + 3219 + npc_cn20k_subbank_calc_free(rvu, &x2_free, &x4_free, &sb_free); 3220 + seq_printf(filp, "\t\t free x4 slots\t: %d\n", x4_free); 3221 + 3222 + seq_printf(filp, "\t\t free x2 slots\t: %d\n", x2_free); 3223 + 3224 + seq_printf(filp, "\t\t free subbanks\t: %d\n", sb_free); 3225 + } else { 3226 + cfg = rvu_read64(rvu, blkaddr, 3227 + NPC_AF_INTFX_KEX_CFG(NIX_INTF_RX)); 3228 + cfg = (cfg >> 32) & 0x07; 3229 + seq_printf(filp, "\t\t RX keywidth \t: %s\n", 3230 + (cfg == NPC_MCAM_KEY_X1) ? 3231 + "112bits" : ((cfg == NPC_MCAM_KEY_X2) ? 3232 + "224bits" : "448bits")); 3233 + cfg = rvu_read64(rvu, blkaddr, 3234 + NPC_AF_INTFX_KEX_CFG(NIX_INTF_TX)); 3235 + cfg = (cfg >> 32) & 0x07; 3236 + seq_printf(filp, "\t\t TX keywidth \t: %s\n", 3237 + (cfg == NPC_MCAM_KEY_X1) ? 3238 + "112bits" : ((cfg == NPC_MCAM_KEY_X2) ? 3239 + "224bits" : "448bits")); 3240 + } 3227 3241 3228 3242 mutex_lock(&mcam->lock); 3229 3243 /* MCAM entries */ ··· 3528 3506 struct rvu_npc_mcam_rule *iter; 3529 3507 struct rvu *rvu = s->private; 3530 3508 struct npc_mcam *mcam; 3531 - int pf, vf = -1; 3509 + int pf, vf = -1, bank; 3510 + u16 target, index; 3532 3511 bool enabled; 3512 + u64 hits, off; 3533 3513 int blkaddr; 3534 - u16 target; 3535 - u64 hits; 3536 3514 3537 3515 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); 3538 3516 if (blkaddr < 0) ··· 3576 3554 3577 3555 enabled = is_mcam_entry_enabled(rvu, mcam, blkaddr, iter->entry); 3578 3556 seq_printf(s, "\tenabled: %s\n", enabled ? "yes" : "no"); 3557 + if (is_cn20k(rvu->pdev)) { 3558 + seq_printf(s, "\tpriority: %u\n", iter->hw_prio); 3559 + index = iter->entry & (mcam->banksize - 1); 3560 + bank = npc_get_bank(mcam, iter->entry); 3561 + off = NPC_AF_CN20K_MCAMEX_BANKX_STAT_EXT(index, bank); 3562 + hits = rvu_read64(rvu, blkaddr, off); 3563 + seq_printf(s, "\thits: %lld\n", hits); 3564 + continue; 3565 + } 3579 3566 3580 3567 if (!iter->has_cntr) 3581 3568 continue; ··· 3729 3698 struct npc_exact_table *table; 3730 3699 struct rvu *rvu = s->private; 3731 3700 struct npc_key_field *field; 3701 + u64 cfg, cam1, off; 3732 3702 u16 chan, pcifunc; 3733 3703 int blkaddr, i; 3734 - u64 cfg, cam1; 3735 3704 char *str; 3736 3705 3737 3706 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); ··· 3752 3721 chan = field->kw_mask[0] & cam1; 3753 3722 3754 3723 str = (cfg & 1) ? "enabled" : "disabled"; 3724 + if (is_cn20k(rvu->pdev)) { 3725 + off = NPC_AF_CN20K_MCAMEX_BANKX_STAT_EXT(i, 0); 3726 + seq_printf(s, "0x%x\t%d\t\t%llu\t0x%x\t%s\n", pcifunc, 3727 + i, rvu_read64(rvu, blkaddr, off), chan, str); 3728 + } else { 3729 + off = NPC_AF_MATCH_STATX(table->counter_idx[i]); 3730 + seq_printf(s, "0x%x\t%d\t\t%llu\t0x%x\t%s\n", pcifunc, 3731 + i, rvu_read64(rvu, blkaddr, off), 3732 + chan, str); 3733 + } 3755 3734 3756 - seq_printf(s, "0x%x\t%d\t\t%llu\t0x%x\t%s\n", pcifunc, i, 3757 - rvu_read64(rvu, blkaddr, 3758 - NPC_AF_MATCH_STATX(table->counter_idx[i])), 3759 - chan, str); 3760 3735 } 3761 3736 3762 3737 return 0; ··· 3781 3744 3782 3745 debugfs_create_file("rx_miss_act_stats", 0444, rvu->rvu_dbg.npc, rvu, 3783 3746 &rvu_dbg_npc_rx_miss_act_fops); 3747 + 3748 + if (is_cn20k(rvu->pdev)) 3749 + npc_cn20k_debugfs_init(rvu); 3784 3750 3785 3751 if (!rvu->hw->cap.npc_exact_match_enabled) 3786 3752 return;
+94 -1
drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c
··· 11 11 #include "rvu_reg.h" 12 12 #include "rvu_struct.h" 13 13 #include "rvu_npc_hash.h" 14 + #include "cn20k/npc.h" 14 15 15 16 #define DRV_NAME "octeontx2-af" 16 17 ··· 1257 1256 RVU_AF_DEVLINK_PARAM_ID_NPC_MCAM_ZONE_PERCENT, 1258 1257 RVU_AF_DEVLINK_PARAM_ID_NPC_EXACT_FEATURE_DISABLE, 1259 1258 RVU_AF_DEVLINK_PARAM_ID_NPC_DEF_RULE_CNTR_ENABLE, 1259 + RVU_AF_DEVLINK_PARAM_ID_NPC_DEFRAG, 1260 1260 RVU_AF_DEVLINK_PARAM_ID_NIX_MAXLF, 1261 1261 }; 1262 + 1263 + static int rvu_af_npc_defrag_feature_get(struct devlink *devlink, u32 id, 1264 + struct devlink_param_gset_ctx *ctx, 1265 + struct netlink_ext_ack *extack) 1266 + { 1267 + struct rvu_devlink *rvu_dl = devlink_priv(devlink); 1268 + struct rvu *rvu = rvu_dl->rvu; 1269 + bool enabled; 1270 + 1271 + enabled = is_cn20k(rvu->pdev); 1272 + 1273 + snprintf(ctx->val.vstr, sizeof(ctx->val.vstr), "%s", 1274 + enabled ? "enabled" : "disabled"); 1275 + 1276 + return 0; 1277 + } 1278 + 1279 + static int rvu_af_npc_defrag(struct devlink *devlink, u32 id, 1280 + struct devlink_param_gset_ctx *ctx, 1281 + struct netlink_ext_ack *extack) 1282 + { 1283 + struct rvu_devlink *rvu_dl = devlink_priv(devlink); 1284 + struct rvu *rvu = rvu_dl->rvu; 1285 + 1286 + /* It is hard to roll back if defrag process fails. 1287 + * print a error message and return fault. 1288 + */ 1289 + if (npc_cn20k_defrag(rvu)) { 1290 + dev_err(rvu->dev, "Defrag process failed\n"); 1291 + return -EFAULT; 1292 + } 1293 + return 0; 1294 + } 1295 + 1296 + static int rvu_af_npc_defrag_feature_validate(struct devlink *devlink, u32 id, 1297 + union devlink_param_value val, 1298 + struct netlink_ext_ack *extack) 1299 + { 1300 + struct rvu_devlink *rvu_dl = devlink_priv(devlink); 1301 + struct rvu *rvu = rvu_dl->rvu; 1302 + u64 enable; 1303 + 1304 + if (kstrtoull(val.vstr, 10, &enable)) { 1305 + NL_SET_ERR_MSG_MOD(extack, 1306 + "Only 1 value is supported"); 1307 + return -EINVAL; 1308 + } 1309 + 1310 + if (enable != 1) { 1311 + NL_SET_ERR_MSG_MOD(extack, 1312 + "Only initiating defrag is supported"); 1313 + return -EINVAL; 1314 + } 1315 + 1316 + if (is_cn20k(rvu->pdev)) 1317 + return 0; 1318 + 1319 + NL_SET_ERR_MSG_MOD(extack, 1320 + "Can defrag NPC only in cn20k silicon"); 1321 + return -EFAULT; 1322 + } 1262 1323 1263 1324 static int rvu_af_npc_exact_feature_get(struct devlink *devlink, u32 id, 1264 1325 struct devlink_param_gset_ctx *ctx, ··· 1624 1561 .eswitch_mode_set = rvu_devlink_eswitch_mode_set, 1625 1562 }; 1626 1563 1564 + static const struct devlink_param rvu_af_dl_param_defrag[] = { 1565 + DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_NPC_DEFRAG, 1566 + "npc_defrag", DEVLINK_PARAM_TYPE_STRING, 1567 + BIT(DEVLINK_PARAM_CMODE_RUNTIME), 1568 + rvu_af_npc_defrag_feature_get, 1569 + rvu_af_npc_defrag, 1570 + rvu_af_npc_defrag_feature_validate), 1571 + }; 1572 + 1627 1573 int rvu_register_dl(struct rvu *rvu) 1628 1574 { 1629 1575 struct rvu_devlink *rvu_dl; ··· 1665 1593 goto err_dl_health; 1666 1594 } 1667 1595 1596 + if (is_cn20k(rvu->pdev)) { 1597 + err = devlink_params_register(dl, rvu_af_dl_param_defrag, 1598 + ARRAY_SIZE(rvu_af_dl_param_defrag)); 1599 + if (err) { 1600 + dev_err(rvu->dev, 1601 + "devlink defrag params register failed with error %d", 1602 + err); 1603 + goto err_dl_defrag; 1604 + } 1605 + } 1606 + 1668 1607 /* Register exact match devlink only for CN10K-B */ 1669 1608 if (!rvu_npc_exact_has_match_table(rvu)) 1670 1609 goto done; ··· 1684 1601 ARRAY_SIZE(rvu_af_dl_param_exact_match)); 1685 1602 if (err) { 1686 1603 dev_err(rvu->dev, 1687 - "devlink exact match params register failed with error %d", err); 1604 + "devlink exact match params register failed with error %d", 1605 + err); 1688 1606 goto err_dl_exact_match; 1689 1607 } 1690 1608 ··· 1694 1610 return 0; 1695 1611 1696 1612 err_dl_exact_match: 1613 + if (is_cn20k(rvu->pdev)) 1614 + devlink_params_unregister(dl, rvu_af_dl_param_defrag, 1615 + ARRAY_SIZE(rvu_af_dl_param_defrag)); 1616 + 1617 + err_dl_defrag: 1697 1618 devlink_params_unregister(dl, rvu_af_dl_params, ARRAY_SIZE(rvu_af_dl_params)); 1698 1619 1699 1620 err_dl_health: ··· 1715 1626 devlink_unregister(dl); 1716 1627 1717 1628 devlink_params_unregister(dl, rvu_af_dl_params, ARRAY_SIZE(rvu_af_dl_params)); 1629 + 1630 + if (is_cn20k(rvu->pdev)) 1631 + devlink_params_unregister(dl, rvu_af_dl_param_defrag, 1632 + ARRAY_SIZE(rvu_af_dl_param_defrag)); 1718 1633 1719 1634 /* Unregister exact match devlink only for CN10K-B */ 1720 1635 if (rvu_npc_exact_has_match_table(rvu))
-1
drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
··· 5289 5289 /* Disable the interface if it is in any multicast list */ 5290 5290 nix_mcast_update_mce_entry(rvu, pcifunc, 0); 5291 5291 5292 - 5293 5292 pfvf = rvu_get_pfvf(rvu, pcifunc); 5294 5293 clear_bit(NIXLF_INITIALIZED, &pfvf->flags); 5295 5294
+466 -134
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
··· 16 16 #include "cgx.h" 17 17 #include "npc_profile.h" 18 18 #include "rvu_npc_hash.h" 19 + #include "cn20k/npc.h" 20 + #include "rvu_npc.h" 21 + #include "cn20k/reg.h" 19 22 20 23 #define RSVD_MCAM_ENTRIES_PER_PF 3 /* Broadcast, Promisc and AllMulticast */ 21 24 #define RSVD_MCAM_ENTRIES_PER_NIXLF 1 /* Ucast for LFs */ ··· 152 149 { 153 150 struct rvu_hwinfo *hw = container_of(mcam, struct rvu_hwinfo, mcam); 154 151 struct rvu *rvu = hw->rvu; 155 - int pf = rvu_get_pf(rvu->pdev, pcifunc); 152 + u16 bcast, mcast, promisc, ucast; 156 153 int index; 154 + int rc; 155 + int pf; 156 + 157 + if (is_cn20k(rvu->pdev)) { 158 + rc = npc_cn20k_dft_rules_idx_get(rvu, pcifunc, &bcast, &mcast, 159 + &promisc, &ucast); 160 + if (rc) 161 + return -EFAULT; 162 + 163 + switch (type) { 164 + case NIXLF_BCAST_ENTRY: 165 + return bcast; 166 + case NIXLF_ALLMULTI_ENTRY: 167 + return mcast; 168 + case NIXLF_PROMISC_ENTRY: 169 + return promisc; 170 + case NIXLF_UCAST_ENTRY: 171 + return ucast; 172 + default: 173 + return -EINVAL; 174 + } 175 + } 157 176 158 177 /* Check if this is for a PF */ 178 + pf = rvu_get_pf(rvu->pdev, pcifunc); 159 179 if (pf && !(pcifunc & RVU_PFVF_FUNC_MASK)) { 160 180 /* Reserved entries exclude PF0 */ 161 181 pf--; ··· 199 173 200 174 int npc_get_bank(struct npc_mcam *mcam, int index) 201 175 { 176 + struct rvu_hwinfo *hw = container_of(mcam, struct rvu_hwinfo, mcam); 202 177 int bank = index / mcam->banksize; 178 + struct rvu *rvu = hw->rvu; 179 + 180 + if (is_cn20k(rvu->pdev)) 181 + return bank; 203 182 204 183 /* 0,1 & 2,3 banks are combined for this keysize */ 205 184 if (mcam->keysize == NPC_MCAM_KEY_X2) ··· 220 189 u64 cfg; 221 190 222 191 index &= (mcam->banksize - 1); 223 - cfg = rvu_read64(rvu, blkaddr, NPC_AF_MCAMEX_BANKX_CFG(index, bank)); 192 + if (is_cn20k(rvu->pdev)) 193 + cfg = rvu_read64(rvu, blkaddr, 194 + NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(index, 195 + bank)); 196 + else 197 + cfg = rvu_read64(rvu, blkaddr, 198 + NPC_AF_MCAMEX_BANKX_CFG(index, bank)); 199 + 224 200 return (cfg & 1); 225 201 } 226 202 ··· 236 198 { 237 199 int bank = npc_get_bank(mcam, index); 238 200 int actbank = bank; 201 + 202 + if (is_cn20k(rvu->pdev)) { 203 + if (index < 0 || index >= mcam->banksize * mcam->banks) 204 + return; 205 + 206 + return npc_cn20k_enable_mcam_entry(rvu, blkaddr, index, enable); 207 + } 239 208 240 209 index &= (mcam->banksize - 1); 241 210 for (; bank < (actbank + mcam->banks_per_entry); bank++) { ··· 412 367 int blkaddr, u16 pf_func) 413 368 { 414 369 int bank, nixlf, index; 370 + u64 reg; 415 371 416 372 /* get ucast entry rule entry index */ 417 373 if (nix_get_nixlf(rvu, pf_func, &nixlf, NULL)) { ··· 427 381 bank = npc_get_bank(mcam, index); 428 382 index &= (mcam->banksize - 1); 429 383 430 - return rvu_read64(rvu, blkaddr, 431 - NPC_AF_MCAMEX_BANKX_ACTION(index, bank)); 384 + if (is_cn20k(rvu->pdev)) 385 + reg = NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(index, bank, 0); 386 + else 387 + reg = NPC_AF_MCAMEX_BANKX_ACTION(index, bank); 388 + 389 + return rvu_read64(rvu, blkaddr, reg); 432 390 } 433 391 434 392 static void npc_fixup_vf_rule(struct rvu *rvu, struct npc_mcam *mcam, ··· 597 547 u64 cfg, sreg, dreg; 598 548 int bank, i; 599 549 550 + if (is_cn20k(rvu->pdev)) 551 + return npc_cn20k_copy_mcam_entry(rvu, blkaddr, src, dest); 552 + 600 553 src &= (mcam->banksize - 1); 601 554 dest &= (mcam->banksize - 1); 602 555 ··· 636 583 int blkaddr, int index) 637 584 { 638 585 int bank = npc_get_bank(mcam, index); 586 + u64 reg; 639 587 640 588 index &= (mcam->banksize - 1); 641 - return rvu_read64(rvu, blkaddr, 642 - NPC_AF_MCAMEX_BANKX_ACTION(index, bank)); 589 + 590 + if (is_cn20k(rvu->pdev)) 591 + reg = NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(index, bank, 0); 592 + else 593 + reg = NPC_AF_MCAMEX_BANKX_ACTION(index, bank); 594 + return rvu_read64(rvu, blkaddr, reg); 643 595 } 644 596 645 597 void npc_set_mcam_action(struct rvu *rvu, struct npc_mcam *mcam, 646 598 int blkaddr, int index, u64 cfg) 647 599 { 648 600 int bank = npc_get_bank(mcam, index); 601 + u64 reg; 649 602 650 603 index &= (mcam->banksize - 1); 651 - return rvu_write64(rvu, blkaddr, 652 - NPC_AF_MCAMEX_BANKX_ACTION(index, bank), cfg); 604 + 605 + if (is_cn20k(rvu->pdev)) 606 + reg = NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(index, bank, 0); 607 + else 608 + reg = NPC_AF_MCAMEX_BANKX_ACTION(index, bank); 609 + 610 + return rvu_write64(rvu, blkaddr, reg, cfg); 653 611 } 654 612 655 613 void rvu_npc_install_ucast_entry(struct rvu *rvu, u16 pcifunc, ··· 714 650 req.index = action.index; 715 651 req.match_id = action.match_id; 716 652 req.flow_key_alg = action.flow_key_alg; 653 + 654 + if (is_cn20k(rvu->pdev)) 655 + req.hw_prio = pfvf->hw_prio; 717 656 718 657 rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp); 719 658 } ··· 806 739 req.match_id = action.match_id; 807 740 req.flow_key_alg = flow_key_alg; 808 741 742 + if (is_cn20k(rvu->pdev)) 743 + req.hw_prio = pfvf->hw_prio; 744 + 809 745 rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp); 810 746 } 811 747 ··· 888 818 req.entry = index; 889 819 req.hdr.pcifunc = 0; /* AF is requester */ 890 820 req.vf = pcifunc; 821 + 822 + if (is_cn20k(rvu->pdev)) 823 + req.hw_prio = pfvf->hw_prio; 891 824 892 825 rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp); 893 826 } ··· 980 907 req.match_id = action.match_id; 981 908 req.flow_key_alg = flow_key_alg; 982 909 910 + if (is_cn20k(rvu->pdev)) 911 + req.hw_prio = pfvf->hw_prio; 912 + 983 913 rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp); 984 914 } 985 915 ··· 1016 940 1017 941 mutex_lock(&mcam->lock); 1018 942 for (index = 0; index < mcam->bmap_entries; index++) { 1019 - if (mcam->entry2target_pffunc[index] == pcifunc) { 1020 - update = true; 1021 - /* update not needed for the rules added via ntuple filters */ 1022 - list_for_each_entry(rule, &mcam->mcam_rules, list) { 1023 - if (rule->entry == index) 1024 - update = false; 1025 - } 1026 - if (!update) 1027 - continue; 1028 - bank = npc_get_bank(mcam, index); 1029 - actindex = index; 1030 - entry = index & (mcam->banksize - 1); 943 + if (mcam->entry2target_pffunc[index] != pcifunc) 944 + continue; 945 + update = true; 946 + /* update not needed for the rules added via ntuple filters */ 947 + list_for_each_entry(rule, &mcam->mcam_rules, list) { 948 + if (rule->entry == index) 949 + update = false; 950 + } 951 + if (!update) 952 + continue; 953 + bank = npc_get_bank(mcam, index); 954 + actindex = index; 955 + entry = index & (mcam->banksize - 1); 1031 956 1032 - /* read vf flow entry enable status */ 1033 - enable = is_mcam_entry_enabled(rvu, mcam, blkaddr, 1034 - actindex); 1035 - /* disable before mcam entry update */ 1036 - npc_enable_mcam_entry(rvu, mcam, blkaddr, actindex, 1037 - false); 1038 - /* update 'action' */ 957 + /* read vf flow entry enable status */ 958 + enable = is_mcam_entry_enabled(rvu, mcam, blkaddr, 959 + actindex); 960 + /* disable before mcam entry update */ 961 + npc_enable_mcam_entry(rvu, mcam, blkaddr, actindex, 962 + false); 963 + 964 + /* update 'action' */ 965 + if (is_cn20k(rvu->pdev)) 966 + rvu_write64(rvu, blkaddr, 967 + NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(entry, 968 + bank, 969 + 0), 970 + rx_action); 971 + else 1039 972 rvu_write64(rvu, blkaddr, 1040 973 NPC_AF_MCAMEX_BANKX_ACTION(entry, bank), 1041 974 rx_action); 1042 - if (enable) 1043 - npc_enable_mcam_entry(rvu, mcam, blkaddr, 1044 - actindex, true); 1045 - } 975 + 976 + if (enable) 977 + npc_enable_mcam_entry(rvu, mcam, blkaddr, 978 + actindex, true); 1046 979 } 1047 980 mutex_unlock(&mcam->lock); 1048 981 } ··· 1064 979 struct npc_mcam *mcam = &rvu->hw->mcam; 1065 980 struct rvu_hwinfo *hw = rvu->hw; 1066 981 int bank, op_rss; 982 + u64 reg; 1067 983 1068 984 if (!is_mcam_entry_enabled(rvu, mcam, blkaddr, mcam_index)) 1069 985 return; ··· 1074 988 bank = npc_get_bank(mcam, mcam_index); 1075 989 mcam_index &= (mcam->banksize - 1); 1076 990 991 + if (is_cn20k(rvu->pdev)) 992 + reg = NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(mcam_index, 993 + bank, 0); 994 + else 995 + reg = NPC_AF_MCAMEX_BANKX_ACTION(mcam_index, bank); 996 + 1077 997 /* If Rx action is MCAST update only RSS algorithm index */ 1078 998 if (!op_rss) { 1079 - *(u64 *)&action = rvu_read64(rvu, blkaddr, 1080 - NPC_AF_MCAMEX_BANKX_ACTION(mcam_index, bank)); 999 + *(u64 *)&action = rvu_read64(rvu, blkaddr, reg); 1081 1000 1082 1001 action.flow_key_alg = alg_idx; 1083 1002 } 1084 - rvu_write64(rvu, blkaddr, 1085 - NPC_AF_MCAMEX_BANKX_ACTION(mcam_index, bank), *(u64 *)&action); 1003 + rvu_write64(rvu, blkaddr, reg, *(u64 *)&action); 1086 1004 } 1087 1005 1088 1006 void rvu_npc_update_flowkey_alg_idx(struct rvu *rvu, u16 pcifunc, int nixlf, ··· 1096 1006 struct nix_rx_action action; 1097 1007 int blkaddr, index, bank; 1098 1008 struct rvu_pfvf *pfvf; 1009 + u64 reg; 1099 1010 1100 1011 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); 1101 1012 if (blkaddr < 0) ··· 1119 1028 bank = npc_get_bank(mcam, index); 1120 1029 index &= (mcam->banksize - 1); 1121 1030 1122 - *(u64 *)&action = rvu_read64(rvu, blkaddr, 1123 - NPC_AF_MCAMEX_BANKX_ACTION(index, bank)); 1031 + if (is_cn20k(rvu->pdev)) 1032 + reg = NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(index, bank, 0); 1033 + else 1034 + reg = NPC_AF_MCAMEX_BANKX_ACTION(index, bank); 1035 + 1036 + *(u64 *)&action = rvu_read64(rvu, blkaddr, reg); 1124 1037 /* Ignore if no action was set earlier */ 1125 1038 if (!*(u64 *)&action) 1126 1039 return; ··· 1134 1039 action.index = group; 1135 1040 action.flow_key_alg = alg_idx; 1136 1041 1137 - rvu_write64(rvu, blkaddr, 1138 - NPC_AF_MCAMEX_BANKX_ACTION(index, bank), *(u64 *)&action); 1042 + rvu_write64(rvu, blkaddr, reg, *(u64 *)&action); 1043 + /* update the VF flow rule action with the VF default entry action */ 1044 + if (mcam_index < 0) 1045 + npc_update_vf_flow_entry(rvu, mcam, blkaddr, pcifunc, 1046 + *(u64 *)&action); 1139 1047 1140 1048 /* update the action change in default rule */ 1141 1049 pfvf = rvu_get_pfvf(rvu, pcifunc); ··· 1436 1338 npc_program_mkex_hash(rvu, blkaddr); 1437 1339 } 1438 1340 1439 - static int npc_fwdb_prfl_img_map(struct rvu *rvu, void __iomem **prfl_img_addr, 1440 - u64 *size) 1341 + int npc_fwdb_prfl_img_map(struct rvu *rvu, void __iomem **prfl_img_addr, 1342 + u64 *size) 1441 1343 { 1442 1344 u64 prfl_addr, prfl_sz; 1443 1345 ··· 1493 1395 */ 1494 1396 if (!is_rvu_96xx_B0(rvu) || 1495 1397 mcam_kex->keyx_cfg[NIX_INTF_RX] == mcam_kex->keyx_cfg[NIX_INTF_TX]) 1496 - rvu->kpu.mkex = mcam_kex; 1398 + rvu->kpu.mcam_kex_prfl.mkex = mcam_kex; 1497 1399 goto program_mkex; 1498 1400 } 1499 1401 ··· 1503 1405 dev_warn(dev, "Failed to load requested profile: %s\n", mkex_profile); 1504 1406 1505 1407 program_mkex: 1506 - dev_info(rvu->dev, "Using %s mkex profile\n", rvu->kpu.mkex->name); 1408 + dev_info(rvu->dev, "Using %s mkex profile\n", 1409 + rvu->kpu.mcam_kex_prfl.mkex->name); 1507 1410 /* Program selected mkex profile */ 1508 - npc_program_mkex_profile(rvu, blkaddr, rvu->kpu.mkex); 1411 + npc_program_mkex_profile(rvu, blkaddr, rvu->kpu.mcam_kex_prfl.mkex); 1509 1412 if (mkex_prfl_addr) 1510 1413 iounmap(mkex_prfl_addr); 1511 1414 } 1512 1415 1513 - static void npc_config_kpuaction(struct rvu *rvu, int blkaddr, 1514 - const struct npc_kpu_profile_action *kpuaction, 1515 - int kpu, int entry, bool pkind) 1416 + void npc_config_kpuaction(struct rvu *rvu, int blkaddr, 1417 + const struct npc_kpu_profile_action *kpuaction, 1418 + int kpu, int entry, bool pkind) 1516 1419 { 1517 1420 struct npc_kpu_action0 action0 = {0}; 1518 1421 struct npc_kpu_action1 action1 = {0}; ··· 1576 1477 NPC_AF_KPUX_ENTRYX_CAMX(kpu, entry, 1), *(u64 *)&cam1); 1577 1478 } 1578 1479 1579 - static inline u64 enable_mask(int count) 1480 + u64 npc_enable_mask(int count) 1580 1481 { 1581 1482 return (((count) < 64) ? ~(BIT_ULL(count) - 1) : (0x00ULL)); 1582 1483 } ··· 1609 1510 1610 1511 /* Enable all programmed entries */ 1611 1512 num_entries = min_t(int, profile->action_entries, profile->cam_entries); 1612 - entry_mask = enable_mask(num_entries); 1513 + entry_mask = npc_enable_mask(num_entries); 1613 1514 /* Disable first KPU_MAX_CST_ENT entries for built-in profile */ 1614 1515 if (!rvu->kpu.custom) 1615 1516 entry_mask |= GENMASK_ULL(KPU_MAX_CST_ENT - 1, 0); ··· 1618 1519 if (num_entries > 64) { 1619 1520 rvu_write64(rvu, blkaddr, 1620 1521 NPC_AF_KPUX_ENTRY_DISX(kpu, 1), 1621 - enable_mask(num_entries - 64)); 1522 + npc_enable_mask(num_entries - 64)); 1622 1523 } 1623 1524 1624 1525 /* Enable this KPU */ 1625 1526 rvu_write64(rvu, blkaddr, NPC_AF_KPUX_CFG(kpu), 0x01); 1626 1527 } 1627 1528 1628 - static int npc_prepare_default_kpu(struct npc_kpu_profile_adapter *profile) 1529 + static void npc_prepare_default_kpu(struct rvu *rvu, 1530 + struct npc_kpu_profile_adapter *profile) 1629 1531 { 1630 1532 profile->custom = 0; 1631 1533 profile->name = def_pfl_name; ··· 1636 1536 profile->kpu = npc_kpu_profiles; 1637 1537 profile->kpus = ARRAY_SIZE(npc_kpu_profiles); 1638 1538 profile->lt_def = &npc_lt_defaults; 1639 - profile->mkex = &npc_mkex_default; 1640 1539 profile->mkex_hash = &npc_mkex_hash_default; 1641 1540 1642 - return 0; 1541 + if (!is_cn20k(rvu->pdev)) { 1542 + profile->mcam_kex_prfl.mkex = &npc_mkex_default; 1543 + return; 1544 + } 1545 + 1546 + profile->mcam_kex_prfl.mkex_extr = npc_mkex_extr_default_get(); 1547 + ikpu_action_entries[NPC_RX_CPT_HDR_PKIND].offset = 6; 1548 + ikpu_action_entries[NPC_RX_CPT_HDR_PKIND].mask = 0xe0; 1549 + ikpu_action_entries[NPC_RX_CPT_HDR_PKIND].shift = 0x5; 1550 + ikpu_action_entries[NPC_RX_CPT_HDR_PKIND].right = 0x1; 1551 + 1552 + npc_cn20k_update_action_entries_n_flags(rvu, profile); 1643 1553 } 1644 1554 1645 1555 static int npc_apply_custom_kpu(struct rvu *rvu, 1646 1556 struct npc_kpu_profile_adapter *profile) 1647 1557 { 1648 1558 size_t hdr_sz = sizeof(struct npc_kpu_profile_fwdata), offset = 0; 1649 - struct npc_kpu_profile_fwdata *fw = rvu->kpu_fwdata; 1650 1559 struct npc_kpu_profile_action *action; 1560 + struct npc_kpu_profile_fwdata *fw; 1651 1561 struct npc_kpu_profile_cam *cam; 1652 1562 struct npc_kpu_fwdata *fw_kpu; 1653 1563 int entries; 1654 1564 u16 kpu, entry; 1565 + 1566 + if (is_cn20k(rvu->pdev)) 1567 + return npc_cn20k_apply_custom_kpu(rvu, profile); 1568 + 1569 + fw = rvu->kpu_fwdata; 1655 1570 1656 1571 if (rvu->kpu_fwdata_sz < hdr_sz) { 1657 1572 dev_warn(rvu->dev, "Invalid KPU profile size\n"); ··· 1708 1593 profile->custom = 1; 1709 1594 profile->name = fw->name; 1710 1595 profile->version = le64_to_cpu(fw->version); 1711 - profile->mkex = &fw->mkex; 1596 + profile->mcam_kex_prfl.mkex = &fw->mkex; 1712 1597 profile->lt_def = &fw->lt_def; 1713 1598 1714 1599 for (kpu = 0; kpu < fw->kpus; kpu++) { ··· 1822 1707 return ret; 1823 1708 } 1824 1709 1825 - static void npc_load_kpu_profile(struct rvu *rvu) 1710 + void npc_load_kpu_profile(struct rvu *rvu) 1826 1711 { 1827 1712 struct npc_kpu_profile_adapter *profile = &rvu->kpu; 1828 1713 const char *kpu_profile = rvu->kpu_pfl_name; ··· 1833 1718 if (!strncmp(kpu_profile, def_pfl_name, KPU_NAME_LEN)) 1834 1719 goto revert_to_default; 1835 1720 /* First prepare default KPU, then we'll customize top entries. */ 1836 - npc_prepare_default_kpu(profile); 1721 + npc_prepare_default_kpu(rvu, profile); 1837 1722 1838 1723 /* Order of preceedence for load loading NPC profile (high to low) 1839 1724 * Firmware binary in filesystem. ··· 1896 1781 return; 1897 1782 1898 1783 revert_to_default: 1899 - npc_prepare_default_kpu(profile); 1784 + npc_prepare_default_kpu(rvu, profile); 1900 1785 } 1901 1786 1902 1787 static void npc_parser_profile_init(struct rvu *rvu, int blkaddr) ··· 1957 1842 int cntr; 1958 1843 u64 cfg; 1959 1844 1960 - /* Actual number of MCAM entries vary by entry size */ 1961 1845 cfg = (rvu_read64(rvu, blkaddr, 1962 1846 NPC_AF_INTFX_KEX_CFG(0)) >> 32) & 0x07; 1963 - mcam->total_entries = (mcam->banks / BIT_ULL(cfg)) * mcam->banksize; 1964 1847 mcam->keysize = cfg; 1965 1848 1966 1849 /* Number of banks combined per MCAM entry */ 1967 - if (cfg == NPC_MCAM_KEY_X4) 1968 - mcam->banks_per_entry = 4; 1969 - else if (cfg == NPC_MCAM_KEY_X2) 1970 - mcam->banks_per_entry = 2; 1971 - else 1972 - mcam->banks_per_entry = 1; 1850 + if (is_cn20k(rvu->pdev)) { 1851 + /* In cn20k, x2 entries is allowed for x4 profile. 1852 + * set total_entries as 8192 * 2 and key size as x2. 1853 + */ 1854 + mcam->total_entries = mcam->banks * mcam->banksize; 1855 + if (cfg == NPC_MCAM_KEY_X2) 1856 + mcam->banks_per_entry = 1; 1857 + else 1858 + mcam->banks_per_entry = 2; 1973 1859 1974 - /* Reserve one MCAM entry for each of the NIX LF to 1975 - * guarantee space to install default matching DMAC rule. 1976 - * Also reserve 2 MCAM entries for each PF for default 1977 - * channel based matching or 'bcast & promisc' matching to 1978 - * support BCAST and PROMISC modes of operation for PFs. 1979 - * PF0 is excluded. 1980 - */ 1981 - rsvd = (nixlf_count * RSVD_MCAM_ENTRIES_PER_NIXLF) + 1982 - ((rvu->hw->total_pfs - 1) * RSVD_MCAM_ENTRIES_PER_PF); 1983 - if (mcam->total_entries <= rsvd) { 1984 - dev_warn(rvu->dev, 1985 - "Insufficient NPC MCAM size %d for pkt I/O, exiting\n", 1986 - mcam->total_entries); 1987 - return -ENOMEM; 1860 + rsvd = 0; 1861 + } else { 1862 + mcam->total_entries = (mcam->banks / BIT_ULL(cfg)) * 1863 + mcam->banksize; 1864 + 1865 + if (cfg == NPC_MCAM_KEY_X4) 1866 + mcam->banks_per_entry = 4; 1867 + else if (cfg == NPC_MCAM_KEY_X2) 1868 + mcam->banks_per_entry = 2; 1869 + else 1870 + mcam->banks_per_entry = 1; 1871 + 1872 + /* Reserve one MCAM entry for each of the NIX LF to 1873 + * guarantee space to install default matching DMAC rule. 1874 + * Also reserve 2 MCAM entries for each PF for default 1875 + * channel based matching or 'bcast & promisc' matching to 1876 + * support BCAST and PROMISC modes of operation for PFs. 1877 + * PF0 is excluded. 1878 + */ 1879 + rsvd = (nixlf_count * RSVD_MCAM_ENTRIES_PER_NIXLF) + 1880 + ((rvu->hw->total_pfs - 1) * RSVD_MCAM_ENTRIES_PER_PF); 1881 + if (mcam->total_entries <= rsvd) { 1882 + dev_warn(rvu->dev, 1883 + "Insufficient NPC MCAM size %d for pkt I/O, exiting\n", 1884 + mcam->total_entries); 1885 + return -ENOMEM; 1886 + } 1988 1887 } 1989 1888 1990 1889 mcam->bmap_entries = mcam->total_entries - rsvd; 1991 - mcam->nixlf_offset = mcam->bmap_entries; 1992 - mcam->pf_offset = mcam->nixlf_offset + nixlf_count; 1890 + /* cn20k does not need offsets to alloc mcam entries */ 1891 + if (!is_cn20k(rvu->pdev)) { 1892 + mcam->nixlf_offset = mcam->bmap_entries; 1893 + mcam->pf_offset = mcam->nixlf_offset + nixlf_count; 1894 + } 1993 1895 1994 1896 /* Allocate bitmaps for managing MCAM entries */ 1995 1897 mcam->bmap = bitmap_zalloc(mcam->bmap_entries, GFP_KERNEL); ··· 2030 1898 * allocations and another 1/8th at the top for high priority 2031 1899 * allocations. 2032 1900 */ 2033 - mcam->lprio_count = mcam->bmap_entries / 8; 2034 - if (mcam->lprio_count > BITS_PER_LONG) 2035 - mcam->lprio_count = round_down(mcam->lprio_count, 2036 - BITS_PER_LONG); 2037 - mcam->lprio_start = mcam->bmap_entries - mcam->lprio_count; 2038 - mcam->hprio_count = mcam->lprio_count; 2039 - mcam->hprio_end = mcam->hprio_count; 1901 + if (!is_cn20k(rvu->pdev)) { 1902 + mcam->lprio_count = mcam->bmap_entries / 8; 1903 + if (mcam->lprio_count > BITS_PER_LONG) 1904 + mcam->lprio_count = round_down(mcam->lprio_count, 1905 + BITS_PER_LONG); 1906 + mcam->lprio_start = mcam->bmap_entries - mcam->lprio_count; 1907 + mcam->hprio_count = mcam->lprio_count; 1908 + mcam->hprio_end = mcam->hprio_count; 1909 + } 2040 1910 2041 1911 /* Allocate bitmap for managing MCAM counters and memory 2042 1912 * for saving counter to RVU PFFUNC allocation mapping. ··· 2118 1984 hw->npc_pkinds = (npc_const1 >> 12) & 0xFFULL; 2119 1985 hw->npc_kpu_entries = npc_const1 & 0xFFFULL; 2120 1986 hw->npc_kpus = (npc_const >> 8) & 0x1FULL; 1987 + /* For Cn20k silicon, check if enhanced parser 1988 + * is present, then set the NUM_KPMS = NUM_KPUS / 2 and 1989 + * number of LDATA extractors per KEX. 1990 + */ 1991 + if (is_cn20k(rvu->pdev)) { 1992 + if (!(npc_const1 & BIT_ULL(62))) { 1993 + WARN(1, "Enhanced parser is not supported\n"); 1994 + return; 1995 + } 1996 + hw->npc_kpms = hw->npc_kpus / 2; 1997 + hw->npc_kex_extr = (npc_const1 >> 36) & 0x3FULL; 1998 + } 1999 + 2121 2000 hw->npc_intfs = npc_const & 0xFULL; 2122 2001 hw->npc_counters = (npc_const >> 48) & 0xFFFFULL; 2123 2002 ··· 2161 2014 2162 2015 static void rvu_npc_setup_interfaces(struct rvu *rvu, int blkaddr) 2163 2016 { 2164 - struct npc_mcam_kex *mkex = rvu->kpu.mkex; 2017 + struct npc_mcam_kex_extr *mkex_extr = rvu->kpu.mcam_kex_prfl.mkex_extr; 2018 + struct npc_mcam_kex *mkex = rvu->kpu.mcam_kex_prfl.mkex; 2165 2019 struct npc_mcam *mcam = &rvu->hw->mcam; 2166 2020 struct rvu_hwinfo *hw = rvu->hw; 2167 2021 u64 nibble_ena, rx_kex, tx_kex; 2022 + u64 *keyx_cfg, reg; 2168 2023 u8 intf; 2169 2024 2170 - /* Reserve last counter for MCAM RX miss action which is set to 2171 - * drop packet. This way we will know how many pkts didn't match 2172 - * any MCAM entry. 2173 - */ 2174 - mcam->counters.max--; 2175 - mcam->rx_miss_act_cntr = mcam->counters.max; 2025 + if (is_cn20k(rvu->pdev)) { 2026 + keyx_cfg = mkex_extr->keyx_cfg; 2027 + } else { 2028 + keyx_cfg = mkex->keyx_cfg; 2029 + /* Reserve last counter for MCAM RX miss action which is set to 2030 + * drop packet. This way we will know how many pkts didn't 2031 + * match any MCAM entry. 2032 + */ 2033 + mcam->counters.max--; 2034 + mcam->rx_miss_act_cntr = mcam->counters.max; 2035 + } 2176 2036 2177 - rx_kex = mkex->keyx_cfg[NIX_INTF_RX]; 2178 - tx_kex = mkex->keyx_cfg[NIX_INTF_TX]; 2037 + rx_kex = keyx_cfg[NIX_INTF_RX]; 2038 + tx_kex = keyx_cfg[NIX_INTF_TX]; 2039 + 2179 2040 nibble_ena = FIELD_GET(NPC_PARSE_NIBBLE, rx_kex); 2180 2041 2181 2042 nibble_ena = rvu_npc_get_tx_nibble_cfg(rvu, nibble_ena); 2182 2043 if (nibble_ena) { 2183 2044 tx_kex &= ~NPC_PARSE_NIBBLE; 2184 2045 tx_kex |= FIELD_PREP(NPC_PARSE_NIBBLE, nibble_ena); 2185 - mkex->keyx_cfg[NIX_INTF_TX] = tx_kex; 2046 + keyx_cfg[NIX_INTF_TX] = tx_kex; 2186 2047 } 2187 2048 2188 2049 /* Configure RX interfaces */ ··· 2202 2047 rvu_write64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(intf), 2203 2048 rx_kex); 2204 2049 2050 + if (is_cn20k(rvu->pdev)) 2051 + reg = NPC_AF_INTFX_MISS_ACTX(intf, 0); 2052 + else 2053 + reg = NPC_AF_INTFX_MISS_ACT(intf); 2054 + 2205 2055 /* If MCAM lookup doesn't result in a match, drop the received 2206 2056 * packet. And map this action to a counter to count dropped 2207 2057 * packets. 2208 2058 */ 2209 - rvu_write64(rvu, blkaddr, 2210 - NPC_AF_INTFX_MISS_ACT(intf), NIX_RX_ACTIONOP_DROP); 2059 + rvu_write64(rvu, blkaddr, reg, NIX_RX_ACTIONOP_DROP); 2060 + 2061 + if (is_cn20k(rvu->pdev)) 2062 + continue; 2211 2063 2212 2064 /* NPC_AF_INTFX_MISS_STAT_ACT[14:12] - counter[11:9] 2213 2065 * NPC_AF_INTFX_MISS_STAT_ACT[8:0] - counter[8:0] ··· 2234 2072 rvu_write64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(intf), 2235 2073 tx_kex); 2236 2074 2075 + if (is_cn20k(rvu->pdev)) 2076 + reg = NPC_AF_INTFX_MISS_ACTX(intf, 0); 2077 + else 2078 + reg = NPC_AF_INTFX_MISS_ACT(intf); 2079 + 2237 2080 /* Set TX miss action to UCAST_DEFAULT i.e 2238 2081 * transmit the packet on NIX LF SQ's default channel. 2239 2082 */ 2240 - rvu_write64(rvu, blkaddr, 2241 - NPC_AF_INTFX_MISS_ACT(intf), 2242 - NIX_TX_ACTIONOP_UCAST_DEFAULT); 2083 + rvu_write64(rvu, blkaddr, reg, NIX_TX_ACTIONOP_UCAST_DEFAULT); 2243 2084 } 2244 2085 } 2245 2086 ··· 2283 2118 return -ENOMEM; 2284 2119 2285 2120 /* Configure KPU profile */ 2286 - npc_parser_profile_init(rvu, blkaddr); 2121 + if (is_cn20k(rvu->pdev)) 2122 + npc_cn20k_parser_profile_init(rvu, blkaddr); 2123 + else 2124 + npc_parser_profile_init(rvu, blkaddr); 2287 2125 2288 2126 /* Config Outer L2, IPv4's NPC layer info */ 2289 2127 rvu_write64(rvu, blkaddr, NPC_AF_PCK_DEF_OL2, ··· 2317 2149 2318 2150 npc_config_secret_key(rvu, blkaddr); 2319 2151 /* Configure MKEX profile */ 2320 - npc_load_mkex_profile(rvu, blkaddr, rvu->mkex_pfl_name); 2152 + if (is_cn20k(rvu->pdev)) 2153 + npc_cn20k_load_mkex_profile(rvu, blkaddr, rvu->mkex_pfl_name); 2154 + else 2155 + npc_load_mkex_profile(rvu, blkaddr, rvu->mkex_pfl_name); 2321 2156 2322 2157 err = npc_mcam_rsrcs_init(rvu, blkaddr); 2323 2158 if (err) ··· 2330 2159 if (err) { 2331 2160 dev_err(rvu->dev, 2332 2161 "Incorrect mkex profile loaded using default mkex\n"); 2333 - npc_load_mkex_profile(rvu, blkaddr, def_pfl_name); 2162 + if (is_cn20k(rvu->pdev)) 2163 + npc_cn20k_load_mkex_profile(rvu, blkaddr, def_pfl_name); 2164 + else 2165 + npc_load_mkex_profile(rvu, blkaddr, def_pfl_name); 2334 2166 } 2167 + 2168 + if (is_cn20k(rvu->pdev)) 2169 + return npc_cn20k_init(rvu); 2335 2170 2336 2171 return 0; 2337 2172 } ··· 2354 2177 else 2355 2178 kfree(rvu->kpu_fwdata); 2356 2179 mutex_destroy(&mcam->lock); 2180 + 2181 + if (is_cn20k(rvu->pdev)) 2182 + npc_cn20k_deinit(rvu); 2357 2183 } 2358 2184 2359 2185 void rvu_npc_get_mcam_entry_alloc_info(struct rvu *rvu, u16 pcifunc, ··· 2397 2217 } 2398 2218 } 2399 2219 2400 - static int npc_mcam_verify_entry(struct npc_mcam *mcam, 2401 - u16 pcifunc, int entry) 2220 + int npc_mcam_verify_entry(struct npc_mcam *mcam, 2221 + u16 pcifunc, int entry) 2402 2222 { 2403 2223 /* verify AF installed entries */ 2404 2224 if (is_pffunc_af(pcifunc)) ··· 2440 2260 /* Set mapping and increment counter's refcnt */ 2441 2261 mcam->entry2cntr_map[entry] = cntr; 2442 2262 mcam->cntr_refcnt[cntr]++; 2263 + 2264 + if (is_cn20k(rvu->pdev)) 2265 + return; 2266 + 2443 2267 /* Enable stats */ 2444 2268 rvu_write64(rvu, blkaddr, 2445 2269 NPC_AF_MCAMEX_BANKX_STAT_ACT(index, bank), ··· 2460 2276 /* Remove mapping and reduce counter's refcnt */ 2461 2277 mcam->entry2cntr_map[entry] = NPC_MCAM_INVALID_MAP; 2462 2278 mcam->cntr_refcnt[cntr]--; 2279 + 2280 + if (is_cn20k(rvu->pdev)) 2281 + return; 2282 + 2463 2283 /* Disable stats */ 2464 2284 rvu_write64(rvu, blkaddr, 2465 2285 NPC_AF_MCAMEX_BANKX_STAT_ACT(index, bank), 0x00); ··· 2473 2285 * reverse bitmap too. Should be called with 2474 2286 * 'mcam->lock' held. 2475 2287 */ 2476 - static void npc_mcam_set_bit(struct npc_mcam *mcam, u16 index) 2288 + void npc_mcam_set_bit(struct npc_mcam *mcam, u16 index) 2477 2289 { 2478 2290 u16 entry, rentry; 2479 2291 ··· 2489 2301 * reverse bitmap too. Should be called with 2490 2302 * 'mcam->lock' held. 2491 2303 */ 2492 - static void npc_mcam_clear_bit(struct npc_mcam *mcam, u16 index) 2304 + void npc_mcam_clear_bit(struct npc_mcam *mcam, u16 index) 2493 2305 { 2494 2306 u16 entry, rentry; 2495 2307 ··· 2505 2317 int blkaddr, u16 pcifunc) 2506 2318 { 2507 2319 u16 index, cntr; 2320 + int rc; 2508 2321 2509 2322 /* Scan all MCAM entries and free the ones mapped to 'pcifunc' */ 2510 2323 for (index = 0; index < mcam->bmap_entries; index++) { ··· 2523 2334 blkaddr, index, 2524 2335 cntr); 2525 2336 mcam->entry2target_pffunc[index] = 0x0; 2337 + if (is_cn20k(rvu->pdev)) { 2338 + rc = npc_cn20k_idx_free(rvu, &index, 1); 2339 + if (rc) 2340 + dev_err(rvu->dev, 2341 + "Failed to free mcam idx=%u pcifunc=%#x\n", 2342 + index, pcifunc); 2343 + } 2526 2344 } 2527 2345 } 2528 2346 } ··· 2619 2423 { 2620 2424 u16 fcnt; 2621 2425 2622 - if (req->priority == NPC_MCAM_HIGHER_PRIO) 2426 + if (req->ref_prio == NPC_MCAM_HIGHER_PRIO) 2623 2427 goto hprio; 2624 2428 2625 2429 /* For a low priority entry allocation ··· 2676 2480 struct npc_mcam_alloc_entry_req *req, 2677 2481 struct npc_mcam_alloc_entry_rsp *rsp) 2678 2482 { 2483 + struct rvu_hwinfo *hw = container_of(mcam, struct rvu_hwinfo, mcam); 2679 2484 u16 entry_list[NPC_MAX_NONCONTIG_ENTRIES]; 2680 2485 u16 fcnt, hp_fcnt, lp_fcnt; 2486 + struct rvu *rvu = hw->rvu; 2681 2487 u16 start, end, index; 2682 2488 int entry, next_start; 2683 2489 bool reverse = false; 2684 2490 unsigned long *bmap; 2491 + int ret, limit = 0; 2685 2492 u16 max_contig; 2686 2493 2494 + if (!is_cn20k(rvu->pdev)) 2495 + goto not_cn20k; 2496 + 2497 + /* Only x2 or x4 key types are accepted */ 2498 + if (req->kw_type != NPC_MCAM_KEY_X2 && req->kw_type != NPC_MCAM_KEY_X4) 2499 + return NPC_MCAM_INVALID_REQ; 2500 + 2501 + /* The below table is being followed during allocation, 2502 + * 2503 + * 1. ref_entry == 0 && prio == HIGH && count == 1 : user wants to 2504 + * allocate 0th index 2505 + * 2. ref_entry == 0 && prio == HIGH && count > 1 : Invalid request 2506 + * 3. ref_entry == 0 && prio == LOW && count >= 1 : limit = 0 2507 + * 4. ref_entry != 0 && prio == HIGH && count >= 1 : limit = 0 2508 + * 5. ref_entry != 0 && prio == LOW && count >=1 : limit = Max 2509 + * (X2 2*8192, X4 8192) 2510 + */ 2511 + if (req->ref_entry && req->ref_prio == NPC_MCAM_LOWER_PRIO) { 2512 + if (req->kw_type == NPC_MCAM_KEY_X2) 2513 + limit = 2 * mcam->bmap_entries; 2514 + else 2515 + limit = mcam->bmap_entries; 2516 + } 2517 + 2518 + ret = npc_cn20k_ref_idx_alloc(rvu, pcifunc, req->kw_type, 2519 + req->ref_prio, rsp->entry_list, 2520 + req->ref_entry, limit, 2521 + req->contig, req->count, !!req->virt); 2522 + 2523 + if (ret) { 2524 + rsp->count = 0; 2525 + return NPC_MCAM_ALLOC_FAILED; 2526 + } 2527 + 2528 + rsp->count = req->count; 2529 + if (req->contig) 2530 + rsp->entry = rsp->entry_list[0]; 2531 + 2532 + /* cn20k, entries allocation algorithm is different. 2533 + * This common API updates some bitmap on usage etc, which 2534 + * will be used by other functions. So update those for 2535 + * cn20k as well. 2536 + */ 2537 + 2538 + mutex_lock(&mcam->lock); 2539 + /* Mark the allocated entries as used and set nixlf mapping */ 2540 + for (entry = 0; entry < rsp->count; entry++) { 2541 + index = npc_cn20k_vidx2idx(rsp->entry_list[entry]); 2542 + npc_mcam_set_bit(mcam, index); 2543 + mcam->entry2pfvf_map[index] = pcifunc; 2544 + mcam->entry2cntr_map[index] = NPC_MCAM_INVALID_MAP; 2545 + } 2546 + 2547 + /* cn20k, free count is provided thru different mbox message. 2548 + * one counter to indicate free x2 slots and free x4 slots 2549 + * does not provide any useful information to the user. 2550 + */ 2551 + rsp->free_count = -1; 2552 + mutex_unlock(&mcam->lock); 2553 + 2554 + return 0; 2555 + 2556 + not_cn20k: 2687 2557 mutex_lock(&mcam->lock); 2688 2558 2689 2559 /* Check if there are any free entries */ ··· 2785 2523 goto lprio_alloc; 2786 2524 2787 2525 /* Get the search range for priority allocation request */ 2788 - if (req->priority) { 2526 + if (req->ref_prio) { 2789 2527 npc_get_mcam_search_range_priority(mcam, req, 2790 2528 &start, &end, &reverse); 2791 2529 goto alloc; ··· 2826 2564 * and not in mid zone. 2827 2565 */ 2828 2566 if (!(pcifunc & RVU_PFVF_FUNC_MASK) && 2829 - req->priority == NPC_MCAM_HIGHER_PRIO) 2567 + req->ref_prio == NPC_MCAM_HIGHER_PRIO) 2830 2568 end = req->ref_entry; 2831 2569 2832 2570 if (!(pcifunc & RVU_PFVF_FUNC_MASK) && 2833 - req->priority == NPC_MCAM_LOWER_PRIO) 2571 + req->ref_prio == NPC_MCAM_LOWER_PRIO) 2834 2572 start = req->ref_entry; 2835 2573 } 2836 2574 ··· 2879 2617 /* If allocating requested no of entries is unsucessful, 2880 2618 * expand the search range to full bitmap length and retry. 2881 2619 */ 2882 - if (!req->priority && (rsp->count < req->count) && 2620 + if (!req->ref_prio && rsp->count < req->count && 2883 2621 ((end - start) != mcam->bmap_entries)) { 2884 2622 reverse = true; 2885 2623 start = 0; ··· 2890 2628 /* For priority entry allocation requests, if allocation is 2891 2629 * failed then expand search to max possible range and retry. 2892 2630 */ 2893 - if (req->priority && rsp->count < req->count) { 2894 - if (req->priority == NPC_MCAM_LOWER_PRIO && 2631 + if (req->ref_prio && rsp->count < req->count) { 2632 + if (req->ref_prio == NPC_MCAM_LOWER_PRIO && 2895 2633 (start != (req->ref_entry + 1))) { 2896 2634 start = req->ref_entry + 1; 2897 2635 end = mcam->bmap_entries; 2898 2636 reverse = false; 2899 2637 goto alloc; 2900 - } else if ((req->priority == NPC_MCAM_HIGHER_PRIO) && 2638 + } else if ((req->ref_prio == NPC_MCAM_HIGHER_PRIO) && 2901 2639 ((end - start) != req->ref_entry)) { 2902 2640 start = 0; 2903 2641 end = req->ref_entry; ··· 2950 2688 struct npc_install_flow_rsp rsp; 2951 2689 struct rvu_npc_mcam_rule *rule; 2952 2690 int blkaddr; 2691 + 2692 + /* Counter is set for each rule by default */ 2693 + if (is_cn20k(rvu->pdev)) 2694 + return -EINVAL; 2953 2695 2954 2696 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); 2955 2697 if (blkaddr < 0) ··· 3015 2749 /* ref_entry can't be '0' if requested priority is high. 3016 2750 * Can't be last entry if requested priority is low. 3017 2751 */ 3018 - if ((!req->ref_entry && req->priority == NPC_MCAM_HIGHER_PRIO) || 3019 - ((req->ref_entry == mcam->bmap_entries) && 3020 - req->priority == NPC_MCAM_LOWER_PRIO)) 2752 + if ((!req->ref_entry && req->ref_prio == NPC_MCAM_HIGHER_PRIO) || 2753 + (req->ref_entry == mcam->bmap_entries && 2754 + req->ref_prio == NPC_MCAM_LOWER_PRIO)) 3021 2755 return NPC_MCAM_INVALID_REQ; 3022 2756 3023 2757 /* Since list of allocated indices needs to be sent to requester, ··· 3046 2780 int blkaddr, rc = 0; 3047 2781 u16 cntr; 3048 2782 2783 + req->entry = npc_cn20k_vidx2idx(req->entry); 2784 + 3049 2785 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); 3050 2786 if (blkaddr < 0) 3051 2787 return NPC_MCAM_INVALID_REQ; ··· 3075 2807 if (cntr != NPC_MCAM_INVALID_MAP) 3076 2808 npc_unmap_mcam_entry_and_cntr(rvu, mcam, blkaddr, 3077 2809 req->entry, cntr); 2810 + 2811 + if (is_cn20k(rvu->pdev)) { 2812 + rc = npc_cn20k_idx_free(rvu, &req->entry, 1); 2813 + if (rc) 2814 + dev_err(rvu->dev, 2815 + "Failed to free index=%u\n", 2816 + req->entry); 2817 + } 3078 2818 3079 2819 goto exit; 3080 2820 ··· 3137 2861 if (rc) 3138 2862 goto exit; 3139 2863 3140 - if (req->set_cntr && 3141 - npc_mcam_verify_counter(mcam, pcifunc, req->cntr)) { 3142 - rc = NPC_MCAM_INVALID_REQ; 3143 - goto exit; 2864 + if (!is_cn20k(rvu->pdev)) { 2865 + /* Verify counter in SoCs other than cn20k */ 2866 + if (req->set_cntr && 2867 + npc_mcam_verify_counter(mcam, pcifunc, req->cntr)) { 2868 + rc = NPC_MCAM_INVALID_REQ; 2869 + goto exit; 2870 + } 3144 2871 } 3145 2872 3146 2873 if (!is_npc_interface_valid(rvu, req->intf)) { ··· 3181 2902 u16 pcifunc = req->hdr.pcifunc; 3182 2903 int blkaddr, rc; 3183 2904 2905 + req->entry = npc_cn20k_vidx2idx(req->entry); 2906 + 3184 2907 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); 3185 2908 if (blkaddr < 0) 3186 2909 return NPC_MCAM_INVALID_REQ; ··· 3205 2924 struct npc_mcam *mcam = &rvu->hw->mcam; 3206 2925 u16 pcifunc = req->hdr.pcifunc; 3207 2926 int blkaddr, rc; 2927 + 2928 + req->entry = npc_cn20k_vidx2idx(req->entry); 3208 2929 3209 2930 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); 3210 2931 if (blkaddr < 0) ··· 3242 2959 3243 2960 mutex_lock(&mcam->lock); 3244 2961 for (index = 0; index < req->shift_count; index++) { 3245 - old_entry = req->curr_entry[index]; 3246 - new_entry = req->new_entry[index]; 2962 + old_entry = npc_cn20k_vidx2idx(req->curr_entry[index]); 2963 + new_entry = npc_cn20k_vidx2idx(req->new_entry[index]); 3247 2964 3248 2965 /* Check if both old and new entries are valid and 3249 2966 * does belong to this PFFUNC or not. ··· 3315 3032 if (!req->contig && req->count > NPC_MAX_NONCONTIG_COUNTERS) 3316 3033 return NPC_MCAM_INVALID_REQ; 3317 3034 3318 - 3319 3035 /* Check if unused counters are available or not */ 3320 3036 if (!rvu_rsrc_free_count(&mcam->counters)) { 3321 3037 return NPC_MCAM_ALLOC_FAILED; ··· 3358 3076 { 3359 3077 struct npc_mcam *mcam = &rvu->hw->mcam; 3360 3078 int err; 3079 + 3080 + /* Counter is not supported for CN20K */ 3081 + if (is_cn20k(rvu->pdev)) 3082 + return NPC_MCAM_INVALID_REQ; 3361 3083 3362 3084 mutex_lock(&mcam->lock); 3363 3085 ··· 3416 3130 { 3417 3131 struct npc_mcam *mcam = &rvu->hw->mcam; 3418 3132 int err; 3133 + 3134 + /* Counter is not supported for CN20K */ 3135 + if (is_cn20k(rvu->pdev)) 3136 + return NPC_MCAM_INVALID_REQ; 3419 3137 3420 3138 mutex_lock(&mcam->lock); 3421 3139 ··· 3479 3189 u16 index, entry = 0; 3480 3190 int blkaddr, rc; 3481 3191 3192 + /* Counter is not supported for CN20K */ 3193 + if (is_cn20k(rvu->pdev)) 3194 + return NPC_MCAM_INVALID_REQ; 3195 + 3482 3196 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); 3483 3197 if (blkaddr < 0) 3484 3198 return NPC_MCAM_INVALID_REQ; ··· 3527 3233 struct npc_mcam_oper_counter_req *req, struct msg_rsp *rsp) 3528 3234 { 3529 3235 struct npc_mcam *mcam = &rvu->hw->mcam; 3530 - int blkaddr, err; 3236 + int blkaddr, err, index, bank; 3531 3237 3532 3238 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); 3533 3239 if (blkaddr < 0) 3534 3240 return NPC_MCAM_INVALID_REQ; 3241 + 3242 + /* For cn20k, npc mcam index is passed as cntr, as each 3243 + * mcam entry has corresponding counter. 3244 + */ 3245 + if (is_cn20k(rvu->pdev)) { 3246 + index = req->cntr & (mcam->banksize - 1); 3247 + bank = npc_get_bank(mcam, req->cntr); 3248 + rvu_write64(rvu, blkaddr, 3249 + NPC_AF_CN20K_MCAMEX_BANKX_STAT_EXT(index, bank), 0); 3250 + return 0; 3251 + } 3535 3252 3536 3253 mutex_lock(&mcam->lock); 3537 3254 err = npc_mcam_verify_counter(mcam, req->hdr.pcifunc, req->cntr); ··· 3560 3255 struct npc_mcam_oper_counter_rsp *rsp) 3561 3256 { 3562 3257 struct npc_mcam *mcam = &rvu->hw->mcam; 3563 - int blkaddr, err; 3258 + int blkaddr, err, index, bank; 3259 + u64 regval; 3564 3260 3565 3261 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); 3566 3262 if (blkaddr < 0) 3567 3263 return NPC_MCAM_INVALID_REQ; 3264 + 3265 + /* In CN20K, mcam index is passed cntr. Each cn20k mcam entry 3266 + * has its own counter. No need to verify the counter index. 3267 + */ 3268 + if (is_cn20k(rvu->pdev)) { 3269 + index = req->cntr & (mcam->banksize - 1); 3270 + bank = npc_get_bank(mcam, req->cntr); 3271 + regval = rvu_read64(rvu, blkaddr, 3272 + NPC_AF_CN20K_MCAMEX_BANKX_STAT_EXT(index, 3273 + bank)); 3274 + rsp->stat = regval; 3275 + return 0; 3276 + } 3568 3277 3569 3278 mutex_lock(&mcam->lock); 3570 3279 err = npc_mcam_verify_counter(mcam, req->hdr.pcifunc, req->cntr); ··· 3617 3298 /* Try to allocate a MCAM entry */ 3618 3299 entry_req.hdr.pcifunc = req->hdr.pcifunc; 3619 3300 entry_req.contig = true; 3620 - entry_req.priority = req->priority; 3301 + entry_req.ref_prio = req->ref_prio; 3621 3302 entry_req.ref_entry = req->ref_entry; 3622 3303 entry_req.count = 1; 3623 3304 ··· 3874 3555 if (blkaddr < 0) 3875 3556 return NPC_MCAM_INVALID_REQ; 3876 3557 3877 - mutex_lock(&mcam->lock); 3558 + req->entry = npc_cn20k_vidx2idx(req->entry); 3878 3559 3879 3560 index = req->entry & (mcam->banksize - 1); 3880 3561 bank = npc_get_bank(mcam, req->entry); 3881 3562 3563 + mutex_lock(&mcam->lock); 3564 + 3565 + if (is_cn20k(rvu->pdev)) { 3566 + regval = rvu_read64(rvu, blkaddr, 3567 + NPC_AF_CN20K_MCAMEX_BANKX_STAT_EXT(index, 3568 + bank)); 3569 + rsp->stat_ena = 1; 3570 + rsp->stat = regval; 3571 + mutex_unlock(&mcam->lock); 3572 + return 0; 3573 + } 3574 + 3882 3575 /* read MCAM entry STAT_ACT register */ 3883 - regval = rvu_read64(rvu, blkaddr, NPC_AF_MCAMEX_BANKX_STAT_ACT(index, bank)); 3576 + regval = rvu_read64(rvu, blkaddr, NPC_AF_MCAMEX_BANKX_STAT_ACT(index, 3577 + bank)); 3884 3578 3885 3579 if (!(regval & rvu->hw->npc_stat_ena)) { 3886 3580 rsp->stat_ena = 0;
+21
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Marvell RVU Admin Function driver 3 + * 4 + * Copyright (C) 2026 Marvell. 5 + * 6 + */ 7 + 8 + #ifndef RVU_NPC_H 9 + #define RVU_NPC_H 10 + 11 + u64 npc_enable_mask(int count); 12 + void npc_load_kpu_profile(struct rvu *rvu); 13 + void npc_config_kpuaction(struct rvu *rvu, int blkaddr, 14 + const struct npc_kpu_profile_action *kpuaction, 15 + int kpu, int entry, bool pkind); 16 + int npc_fwdb_prfl_img_map(struct rvu *rvu, void __iomem **prfl_img_addr, 17 + u64 *size); 18 + 19 + void npc_mcam_clear_bit(struct npc_mcam *mcam, u16 index); 20 + void npc_mcam_set_bit(struct npc_mcam *mcam, u16 index); 21 + #endif /* RVU_NPC_H */
+561 -147
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
··· 12 12 #include "npc.h" 13 13 #include "rvu_npc_fs.h" 14 14 #include "rvu_npc_hash.h" 15 + #include "cn20k/reg.h" 16 + #include "cn20k/npc.h" 15 17 16 18 static const char * const npc_flow_names[] = { 17 19 [NPC_DMAC] = "dmac", ··· 83 81 /* Compute keyword masks and figure out the number of keywords a field 84 82 * spans in the key. 85 83 */ 86 - static void npc_set_kw_masks(struct npc_mcam *mcam, u8 type, 84 + static void npc_set_kw_masks(struct rvu *rvu, struct npc_mcam *mcam, u8 type, 87 85 u8 nr_bits, int start_kwi, int offset, u8 intf) 88 86 { 89 87 struct npc_key_field *field = &mcam->rx_key_fields[type]; 90 88 u8 bits_in_kw; 91 89 int max_kwi; 92 90 93 - if (mcam->banks_per_entry == 1) 94 - max_kwi = 1; /* NPC_MCAM_KEY_X1 */ 95 - else if (mcam->banks_per_entry == 2) 96 - max_kwi = 3; /* NPC_MCAM_KEY_X2 */ 97 - else 98 - max_kwi = 6; /* NPC_MCAM_KEY_X4 */ 91 + if (is_cn20k(rvu->pdev)) { 92 + if (mcam->banks_per_entry == 1) 93 + max_kwi = 3; /* NPC_MCAM_KEY_X2 */ 94 + else 95 + max_kwi = 7; /* NPC_MCAM_KEY_X4 */ 96 + } else { 97 + if (mcam->banks_per_entry == 1) 98 + max_kwi = 1; /* NPC_MCAM_KEY_X1 */ 99 + else if (mcam->banks_per_entry == 2) 100 + max_kwi = 3; /* NPC_MCAM_KEY_X2 */ 101 + else 102 + max_kwi = 6; /* NPC_MCAM_KEY_X4 */ 103 + } 99 104 100 105 if (is_npc_intf_tx(intf)) 101 106 field = &mcam->tx_key_fields[type]; ··· 164 155 sizeof(struct npc_layer_mdata)) == 0; 165 156 } 166 157 167 - static void npc_set_layer_mdata(struct npc_mcam *mcam, enum key_fields type, 158 + static void npc_set_layer_mdata(struct rvu *rvu, 159 + struct npc_mcam *mcam, enum key_fields type, 168 160 u64 cfg, u8 lid, u8 lt, u8 intf) 169 161 { 170 162 struct npc_key_field *input = &mcam->rx_key_fields[type]; ··· 175 165 176 166 input->layer_mdata.hdr = FIELD_GET(NPC_HDR_OFFSET, cfg); 177 167 input->layer_mdata.key = FIELD_GET(NPC_KEY_OFFSET, cfg); 178 - input->layer_mdata.len = FIELD_GET(NPC_BYTESM, cfg) + 1; 168 + if (is_cn20k(rvu->pdev)) 169 + input->layer_mdata.len = FIELD_GET(NPC_CN20K_BYTESM, cfg) + 1; 170 + else 171 + input->layer_mdata.len = FIELD_GET(NPC_BYTESM, cfg) + 1; 179 172 input->layer_mdata.ltype = lt; 180 173 input->layer_mdata.lid = lid; 181 174 } 182 175 183 176 static bool npc_check_overlap_fields(struct npc_key_field *input1, 184 - struct npc_key_field *input2) 177 + struct npc_key_field *input2, 178 + int max_kw) 185 179 { 186 180 int kwi; 187 181 ··· 196 182 input1->layer_mdata.ltype != input2->layer_mdata.ltype) 197 183 return false; 198 184 199 - for (kwi = 0; kwi < NPC_MAX_KWS_IN_KEY; kwi++) { 185 + for (kwi = 0; kwi < max_kw; kwi++) { 200 186 if (input1->kw_mask[kwi] & input2->kw_mask[kwi]) 201 187 return true; 202 188 } ··· 216 202 struct npc_key_field *dummy, *input; 217 203 int start_kwi, offset; 218 204 u8 nr_bits, lid, lt, ld; 205 + int extr, kws; 219 206 u64 cfg; 220 207 221 208 dummy = &mcam->rx_key_fields[NPC_UNKNOWN]; ··· 227 212 input = &mcam->tx_key_fields[type]; 228 213 } 229 214 215 + kws = NPC_KWS_IN_KEY_SZ_7; 216 + 217 + if (is_cn20k(rvu->pdev)) 218 + goto skip_cn10k_config; 219 + 230 220 for (lid = start_lid; lid < NPC_MAX_LID; lid++) { 231 221 for (lt = 0; lt < NPC_MAX_LT; lt++) { 232 222 for (ld = 0; ld < NPC_MAX_LD; ld++) { ··· 241 221 if (!FIELD_GET(NPC_LDATA_EN, cfg)) 242 222 continue; 243 223 memset(dummy, 0, sizeof(struct npc_key_field)); 244 - npc_set_layer_mdata(mcam, NPC_UNKNOWN, cfg, 245 - lid, lt, intf); 224 + npc_set_layer_mdata(rvu, mcam, NPC_UNKNOWN, 225 + cfg, lid, lt, intf); 246 226 /* exclude input */ 247 227 if (npc_is_same(input, dummy)) 248 228 continue; ··· 250 230 offset = (dummy->layer_mdata.key * 8) % 64; 251 231 nr_bits = dummy->layer_mdata.len * 8; 252 232 /* form KW masks */ 253 - npc_set_kw_masks(mcam, NPC_UNKNOWN, nr_bits, 254 - start_kwi, offset, intf); 233 + npc_set_kw_masks(rvu, mcam, NPC_UNKNOWN, 234 + nr_bits, start_kwi, 235 + offset, intf); 255 236 /* check any input field bits falls in any 256 237 * other field bits. 257 238 */ 258 - if (npc_check_overlap_fields(dummy, input)) 239 + if (npc_check_overlap_fields(dummy, input, kws)) 259 240 return true; 260 241 } 242 + } 243 + } 244 + return false; 245 + 246 + skip_cn10k_config: 247 + for (extr = 0 ; extr < rvu->hw->npc_kex_extr; extr++) { 248 + lid = CN20K_GET_EXTR_LID(intf, extr); 249 + if (lid < start_lid) 250 + continue; 251 + for (lt = 0; lt < NPC_MAX_LT; lt++) { 252 + cfg = CN20K_GET_EXTR_LT(intf, extr, lt); 253 + if (!FIELD_GET(NPC_LDATA_EN, cfg)) 254 + continue; 255 + 256 + memset(dummy, 0, sizeof(struct npc_key_field)); 257 + npc_set_layer_mdata(rvu, mcam, NPC_UNKNOWN, cfg, 258 + lid, lt, intf); 259 + /* exclude input */ 260 + if (npc_is_same(input, dummy)) 261 + continue; 262 + start_kwi = dummy->layer_mdata.key / 8; 263 + offset = (dummy->layer_mdata.key * 8) % 64; 264 + nr_bits = dummy->layer_mdata.len * 8; 265 + /* form KW masks */ 266 + npc_set_kw_masks(rvu, mcam, NPC_UNKNOWN, nr_bits, 267 + start_kwi, offset, intf); 268 + /* check any input field bits falls in any other 269 + * field bits 270 + */ 271 + if (npc_check_overlap_fields(dummy, input, 272 + NPC_KWS_IN_KEY_SZ_8)) 273 + return true; 261 274 } 262 275 } 263 276 ··· 306 253 return true; 307 254 } 308 255 309 - static void npc_scan_exact_result(struct npc_mcam *mcam, u8 bit_number, 256 + static void npc_scan_exact_result(struct rvu *rvu, 257 + struct npc_mcam *mcam, u8 bit_number, 310 258 u8 key_nibble, u8 intf) 311 259 { 312 260 u8 offset = (key_nibble * 4) % 64; /* offset within key word */ ··· 323 269 default: 324 270 return; 325 271 } 326 - npc_set_kw_masks(mcam, type, nr_bits, kwi, offset, intf); 272 + npc_set_kw_masks(rvu, mcam, type, nr_bits, kwi, offset, intf); 327 273 } 328 274 329 - static void npc_scan_parse_result(struct npc_mcam *mcam, u8 bit_number, 275 + static void npc_cn20k_scan_parse_result(struct rvu *rvu, struct npc_mcam *mcam, 276 + u8 bit_number, u8 key_nibble, u8 intf) 277 + { 278 + u8 offset = (key_nibble * 4) % 64; /* offset within key word */ 279 + u8 kwi = (key_nibble * 4) / 64; /* which word in key */ 280 + u8 nr_bits = 4; /* bits in a nibble */ 281 + u8 type; 282 + 283 + switch (bit_number) { 284 + case 0 ... 2: 285 + type = NPC_CHAN; 286 + break; 287 + case 3: 288 + type = NPC_ERRLEV; 289 + break; 290 + case 4 ... 5: 291 + type = NPC_ERRCODE; 292 + break; 293 + case 6: 294 + type = NPC_LXMB; 295 + break; 296 + case 8: 297 + type = NPC_LA; 298 + break; 299 + case 10: 300 + type = NPC_LB; 301 + break; 302 + case 12: 303 + type = NPC_LC; 304 + break; 305 + case 14: 306 + type = NPC_LD; 307 + break; 308 + case 16: 309 + type = NPC_LE; 310 + break; 311 + case 18: 312 + type = NPC_LF; 313 + break; 314 + case 20: 315 + type = NPC_LG; 316 + break; 317 + case 22: 318 + type = NPC_LH; 319 + break; 320 + default: 321 + return; 322 + } 323 + 324 + npc_set_kw_masks(rvu, mcam, type, nr_bits, kwi, offset, intf); 325 + } 326 + 327 + static void npc_scan_parse_result(struct rvu *rvu, 328 + struct npc_mcam *mcam, u8 bit_number, 330 329 u8 key_nibble, u8 intf) 331 330 { 332 331 u8 offset = (key_nibble * 4) % 64; /* offset within key word */ 333 332 u8 kwi = (key_nibble * 4) / 64; /* which word in key */ 334 333 u8 nr_bits = 4; /* bits in a nibble */ 335 334 u8 type; 335 + 336 + if (is_cn20k(rvu->pdev)) { 337 + npc_cn20k_scan_parse_result(rvu, mcam, bit_number, 338 + key_nibble, intf); 339 + return; 340 + } 336 341 337 342 switch (bit_number) { 338 343 case 0 ... 2: ··· 435 322 return; 436 323 } 437 324 438 - npc_set_kw_masks(mcam, type, nr_bits, kwi, offset, intf); 325 + npc_set_kw_masks(rvu, mcam, type, nr_bits, kwi, offset, intf); 439 326 } 440 327 441 328 static void npc_handle_multi_layer_fields(struct rvu *rvu, int blkaddr, u8 intf) ··· 456 343 /* Inner VLAN TCI for double tagged frames */ 457 344 struct npc_key_field *vlan_tag3; 458 345 u64 *features; 346 + int i, max_kw; 459 347 u8 start_lid; 460 - int i; 348 + 349 + if (is_cn20k(rvu->pdev)) 350 + max_kw = NPC_KWS_IN_KEY_SZ_8; 351 + else 352 + max_kw = NPC_KWS_IN_KEY_SZ_7; 461 353 462 354 key_fields = mcam->rx_key_fields; 463 355 features = &mcam->rx_features; ··· 500 382 501 383 /* if key profile programmed extracts Ethertype from multiple layers */ 502 384 if (etype_ether->nr_kws && etype_tag1->nr_kws) { 503 - for (i = 0; i < NPC_MAX_KWS_IN_KEY; i++) { 385 + for (i = 0; i < max_kw; i++) { 504 386 if (etype_ether->kw_mask[i] != etype_tag1->kw_mask[i]) { 505 387 dev_err(rvu->dev, "mkex: Etype pos is different for untagged and tagged pkts.\n"); 506 388 goto vlan_tci; ··· 509 391 key_fields[NPC_ETYPE] = *etype_tag1; 510 392 } 511 393 if (etype_ether->nr_kws && etype_tag2->nr_kws) { 512 - for (i = 0; i < NPC_MAX_KWS_IN_KEY; i++) { 394 + for (i = 0; i < max_kw; i++) { 513 395 if (etype_ether->kw_mask[i] != etype_tag2->kw_mask[i]) { 514 396 dev_err(rvu->dev, "mkex: Etype pos is different for untagged and double tagged pkts.\n"); 515 397 goto vlan_tci; ··· 518 400 key_fields[NPC_ETYPE] = *etype_tag2; 519 401 } 520 402 if (etype_tag1->nr_kws && etype_tag2->nr_kws) { 521 - for (i = 0; i < NPC_MAX_KWS_IN_KEY; i++) { 403 + for (i = 0; i < max_kw; i++) { 522 404 if (etype_tag1->kw_mask[i] != etype_tag2->kw_mask[i]) { 523 405 dev_err(rvu->dev, "mkex: Etype pos is different for tagged and double tagged pkts.\n"); 524 406 goto vlan_tci; ··· 549 431 550 432 /* if key profile extracts outer vlan tci from multiple layers */ 551 433 if (vlan_tag1->nr_kws && vlan_tag2->nr_kws) { 552 - for (i = 0; i < NPC_MAX_KWS_IN_KEY; i++) { 434 + for (i = 0; i < max_kw; i++) { 553 435 if (vlan_tag1->kw_mask[i] != vlan_tag2->kw_mask[i]) { 554 436 dev_err(rvu->dev, "mkex: Out vlan tci pos is different for tagged and double tagged pkts.\n"); 555 437 goto done; ··· 584 466 /* starting KW index and starting bit position */ 585 467 int start_kwi, offset; 586 468 587 - nr_bytes = FIELD_GET(NPC_BYTESM, cfg) + 1; 469 + if (is_cn20k(rvu->pdev)) 470 + nr_bytes = FIELD_GET(NPC_CN20K_BYTESM, cfg) + 1; 471 + else 472 + nr_bytes = FIELD_GET(NPC_BYTESM, cfg) + 1; 473 + 588 474 hdr = FIELD_GET(NPC_HDR_OFFSET, cfg); 589 475 key = FIELD_GET(NPC_KEY_OFFSET, cfg); 590 476 ··· 611 489 if ((hstart) >= hdr && \ 612 490 ((hstart) + (hlen)) <= (hdr + nr_bytes)) { \ 613 491 bit_offset = (hdr + nr_bytes - (hstart) - (hlen)) * 8; \ 614 - npc_set_layer_mdata(mcam, (name), cfg, lid, lt, intf); \ 492 + npc_set_layer_mdata(rvu, mcam, (name), cfg, lid, lt, \ 493 + intf); \ 615 494 offset += bit_offset; \ 616 495 start_kwi += offset / 64; \ 617 496 offset %= 64; \ 618 - npc_set_kw_masks(mcam, (name), (hlen) * 8, \ 497 + npc_set_kw_masks(rvu, mcam, (name), (hlen) * 8, \ 619 498 start_kwi, offset, intf); \ 620 499 } \ 621 500 } \ ··· 759 636 u8 lid, lt, ld, bitnr; 760 637 u64 cfg, masked_cfg; 761 638 u8 key_nibble = 0; 639 + int extr; 762 640 763 641 /* Scan and note how parse result is going to be in key. 764 642 * A bit set in PARSE_NIBBLE_ENA corresponds to a nibble from ··· 767 643 * will be concatenated in key. 768 644 */ 769 645 cfg = rvu_read64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(intf)); 770 - masked_cfg = cfg & NPC_PARSE_NIBBLE; 771 - for_each_set_bit(bitnr, (unsigned long *)&masked_cfg, 31) { 772 - npc_scan_parse_result(mcam, bitnr, key_nibble, intf); 773 - key_nibble++; 646 + if (is_cn20k(rvu->pdev)) { 647 + masked_cfg = cfg & NPC_CN20K_PARSE_NIBBLE; 648 + for_each_set_bit(bitnr, (unsigned long *)&masked_cfg, 649 + NPC_CN20K_TOTAL_NIBBLE) { 650 + npc_scan_parse_result(rvu, mcam, bitnr, 651 + key_nibble, intf); 652 + key_nibble++; 653 + } 654 + } else { 655 + masked_cfg = cfg & NPC_PARSE_NIBBLE; 656 + for_each_set_bit(bitnr, (unsigned long *)&masked_cfg, 657 + NPC_TOTAL_NIBBLE) { 658 + npc_scan_parse_result(rvu, mcam, bitnr, 659 + key_nibble, intf); 660 + key_nibble++; 661 + } 774 662 } 775 663 776 664 /* Ignore exact match bits for mcam entries except the first rule ··· 792 656 masked_cfg = cfg & NPC_EXACT_NIBBLE; 793 657 bitnr = NPC_EXACT_NIBBLE_START; 794 658 for_each_set_bit_from(bitnr, (unsigned long *)&masked_cfg, NPC_EXACT_NIBBLE_END + 1) { 795 - npc_scan_exact_result(mcam, bitnr, key_nibble, intf); 659 + npc_scan_exact_result(rvu, mcam, bitnr, key_nibble, intf); 796 660 key_nibble++; 797 661 } 662 + 663 + if (is_cn20k(rvu->pdev)) 664 + goto skip_cn10k_config; 798 665 799 666 /* Scan and note how layer data is going to be in key */ 800 667 for (lid = 0; lid < NPC_MAX_LID; lid++) { ··· 814 675 } 815 676 } 816 677 678 + return 0; 679 + 680 + skip_cn10k_config: 681 + for (extr = 0 ; extr < rvu->hw->npc_kex_extr; extr++) { 682 + lid = CN20K_GET_EXTR_LID(intf, extr); 683 + for (lt = 0; lt < NPC_MAX_LT; lt++) { 684 + cfg = CN20K_GET_EXTR_LT(intf, extr, lt); 685 + if (!FIELD_GET(NPC_LDATA_EN, cfg)) 686 + continue; 687 + npc_scan_ldata(rvu, blkaddr, lid, lt, cfg, 688 + intf); 689 + } 690 + } 817 691 return 0; 818 692 } 819 693 ··· 903 751 * dont care. 904 752 */ 905 753 void npc_update_entry(struct rvu *rvu, enum key_fields type, 906 - struct mcam_entry *entry, u64 val_lo, 754 + struct mcam_entry_mdata *mdata, u64 val_lo, 907 755 u64 val_hi, u64 mask_lo, u64 mask_hi, u8 intf) 908 756 { 757 + u64 kw_mask[NPC_KWS_IN_KEY_SZ_MAX] = { 0 }; 758 + u64 kw[NPC_KWS_IN_KEY_SZ_MAX] = { 0 }; 909 759 struct npc_mcam *mcam = &rvu->hw->mcam; 910 - struct mcam_entry dummy = { {0} }; 911 760 struct npc_key_field *field; 912 761 u64 kw1, kw2, kw3; 762 + u64 *val, *mask; 763 + int i, max_kw; 913 764 u8 shift; 914 - int i; 915 765 916 766 field = &mcam->rx_key_fields[type]; 917 767 if (is_npc_intf_tx(intf)) ··· 922 768 if (!field->nr_kws) 923 769 return; 924 770 925 - for (i = 0; i < NPC_MAX_KWS_IN_KEY; i++) { 771 + if (is_cn20k(rvu->pdev)) 772 + max_kw = NPC_KWS_IN_KEY_SZ_8; 773 + else 774 + max_kw = NPC_KWS_IN_KEY_SZ_7; 775 + 776 + for (i = 0; i < max_kw; i++) { 926 777 if (!field->kw_mask[i]) 927 778 continue; 928 779 /* place key value in kw[x] */ 929 780 shift = __ffs64(field->kw_mask[i]); 930 781 /* update entry value */ 931 782 kw1 = (val_lo << shift) & field->kw_mask[i]; 932 - dummy.kw[i] = kw1; 783 + kw[i] = kw1; 933 784 /* update entry mask */ 934 785 kw1 = (mask_lo << shift) & field->kw_mask[i]; 935 - dummy.kw_mask[i] = kw1; 786 + kw_mask[i] = kw1; 936 787 937 788 if (field->nr_kws == 1) 938 789 break; ··· 947 788 kw2 = shift ? val_lo >> (64 - shift) : 0; 948 789 kw2 |= (val_hi << shift); 949 790 kw2 &= field->kw_mask[i + 1]; 950 - dummy.kw[i + 1] = kw2; 791 + kw[i + 1] = kw2; 951 792 /* update entry mask */ 952 793 kw2 = shift ? mask_lo >> (64 - shift) : 0; 953 794 kw2 |= (mask_hi << shift); 954 795 kw2 &= field->kw_mask[i + 1]; 955 - dummy.kw_mask[i + 1] = kw2; 796 + kw_mask[i + 1] = kw2; 956 797 break; 957 798 } 958 799 /* place remaining bits of key value in kw[x + 1], kw[x + 2] */ ··· 963 804 kw2 &= field->kw_mask[i + 1]; 964 805 kw3 = shift ? val_hi >> (64 - shift) : 0; 965 806 kw3 &= field->kw_mask[i + 2]; 966 - dummy.kw[i + 1] = kw2; 967 - dummy.kw[i + 2] = kw3; 807 + kw[i + 1] = kw2; 808 + kw[i + 2] = kw3; 968 809 /* update entry mask */ 969 810 kw2 = shift ? mask_lo >> (64 - shift) : 0; 970 811 kw2 |= (mask_hi << shift); 971 812 kw2 &= field->kw_mask[i + 1]; 972 813 kw3 = shift ? mask_hi >> (64 - shift) : 0; 973 814 kw3 &= field->kw_mask[i + 2]; 974 - dummy.kw_mask[i + 1] = kw2; 975 - dummy.kw_mask[i + 2] = kw3; 815 + kw_mask[i + 1] = kw2; 816 + kw_mask[i + 2] = kw3; 976 817 break; 977 818 } 978 819 } 979 820 /* dummy is ready with values and masks for given key 980 821 * field now clear and update input entry with those 981 822 */ 982 - for (i = 0; i < NPC_MAX_KWS_IN_KEY; i++) { 823 + 824 + val = mdata->kw; 825 + mask = mdata->kw_mask; 826 + 827 + for (i = 0; i < max_kw; i++, val++, mask++) { 983 828 if (!field->kw_mask[i]) 984 829 continue; 985 - entry->kw[i] &= ~field->kw_mask[i]; 986 - entry->kw_mask[i] &= ~field->kw_mask[i]; 987 830 988 - entry->kw[i] |= dummy.kw[i]; 989 - entry->kw_mask[i] |= dummy.kw_mask[i]; 831 + *val &= ~field->kw_mask[i]; 832 + *mask &= ~field->kw_mask[i]; 833 + 834 + *val |= kw[i]; 835 + *mask |= kw_mask[i]; 990 836 } 991 837 } 992 838 993 - static void npc_update_ipv6_flow(struct rvu *rvu, struct mcam_entry *entry, 839 + static void npc_update_ipv6_flow(struct rvu *rvu, 840 + struct mcam_entry_mdata *mdata, 994 841 u64 features, struct flow_msg *pkt, 995 842 struct flow_msg *mask, 996 843 struct rvu_npc_mcam_rule *output, u8 intf) ··· 1022 857 val_hi = (u64)src_ip[0] << 32 | src_ip[1]; 1023 858 val_lo = (u64)src_ip[2] << 32 | src_ip[3]; 1024 859 1025 - npc_update_entry(rvu, NPC_SIP_IPV6, entry, val_lo, val_hi, 860 + npc_update_entry(rvu, NPC_SIP_IPV6, mdata, val_lo, val_hi, 1026 861 mask_lo, mask_hi, intf); 1027 862 memcpy(opkt->ip6src, pkt->ip6src, sizeof(opkt->ip6src)); 1028 863 memcpy(omask->ip6src, mask->ip6src, sizeof(omask->ip6src)); ··· 1036 871 val_hi = (u64)dst_ip[0] << 32 | dst_ip[1]; 1037 872 val_lo = (u64)dst_ip[2] << 32 | dst_ip[3]; 1038 873 1039 - npc_update_entry(rvu, NPC_DIP_IPV6, entry, val_lo, val_hi, 874 + npc_update_entry(rvu, NPC_DIP_IPV6, mdata, val_lo, val_hi, 1040 875 mask_lo, mask_hi, intf); 1041 876 memcpy(opkt->ip6dst, pkt->ip6dst, sizeof(opkt->ip6dst)); 1042 877 memcpy(omask->ip6dst, mask->ip6dst, sizeof(omask->ip6dst)); 1043 878 } 1044 879 } 1045 880 1046 - static void npc_update_vlan_features(struct rvu *rvu, struct mcam_entry *entry, 881 + static void npc_update_vlan_features(struct rvu *rvu, 882 + struct mcam_entry_mdata *mdata, 1047 883 u64 features, u8 intf) 1048 884 { 1049 885 bool ctag = !!(features & BIT_ULL(NPC_VLAN_ETYPE_CTAG)); ··· 1053 887 1054 888 /* If only VLAN id is given then always match outer VLAN id */ 1055 889 if (vid && !ctag && !stag) { 1056 - npc_update_entry(rvu, NPC_LB, entry, 890 + npc_update_entry(rvu, NPC_LB, mdata, 1057 891 NPC_LT_LB_STAG_QINQ | NPC_LT_LB_CTAG, 0, 1058 892 NPC_LT_LB_STAG_QINQ & NPC_LT_LB_CTAG, 0, intf); 1059 893 return; 1060 894 } 1061 895 if (ctag) 1062 - npc_update_entry(rvu, NPC_LB, entry, NPC_LT_LB_CTAG, 0, 896 + npc_update_entry(rvu, NPC_LB, mdata, NPC_LT_LB_CTAG, 0, 1063 897 ~0ULL, 0, intf); 1064 898 if (stag) 1065 - npc_update_entry(rvu, NPC_LB, entry, NPC_LT_LB_STAG_QINQ, 0, 899 + npc_update_entry(rvu, NPC_LB, mdata, NPC_LT_LB_STAG_QINQ, 0, 1066 900 ~0ULL, 0, intf); 1067 901 } 1068 902 1069 - static void npc_update_flow(struct rvu *rvu, struct mcam_entry *entry, 1070 - u64 features, struct flow_msg *pkt, 1071 - struct flow_msg *mask, 1072 - struct rvu_npc_mcam_rule *output, u8 intf, 1073 - int blkaddr) 903 + void npc_update_flow(struct rvu *rvu, struct mcam_entry_mdata *mdata, 904 + u64 features, struct flow_msg *pkt, 905 + struct flow_msg *mask, 906 + struct rvu_npc_mcam_rule *output, u8 intf, 907 + int blkaddr) 1074 908 { 1075 909 u64 dmac_mask = ether_addr_to_u64(mask->dmac); 1076 910 u64 smac_mask = ether_addr_to_u64(mask->smac); ··· 1084 918 1085 919 /* For tcp/udp/sctp LTYPE should be present in entry */ 1086 920 if (features & BIT_ULL(NPC_IPPROTO_TCP)) 1087 - npc_update_entry(rvu, NPC_LD, entry, NPC_LT_LD_TCP, 921 + npc_update_entry(rvu, NPC_LD, mdata, NPC_LT_LD_TCP, 1088 922 0, ~0ULL, 0, intf); 1089 923 if (features & BIT_ULL(NPC_IPPROTO_UDP)) 1090 - npc_update_entry(rvu, NPC_LD, entry, NPC_LT_LD_UDP, 924 + npc_update_entry(rvu, NPC_LD, mdata, NPC_LT_LD_UDP, 1091 925 0, ~0ULL, 0, intf); 1092 926 if (features & BIT_ULL(NPC_IPPROTO_SCTP)) 1093 - npc_update_entry(rvu, NPC_LD, entry, NPC_LT_LD_SCTP, 927 + npc_update_entry(rvu, NPC_LD, mdata, NPC_LT_LD_SCTP, 1094 928 0, ~0ULL, 0, intf); 1095 929 if (features & BIT_ULL(NPC_IPPROTO_ICMP)) 1096 - npc_update_entry(rvu, NPC_LD, entry, NPC_LT_LD_ICMP, 930 + npc_update_entry(rvu, NPC_LD, mdata, NPC_LT_LD_ICMP, 1097 931 0, ~0ULL, 0, intf); 1098 932 if (features & BIT_ULL(NPC_IPPROTO_ICMP6)) 1099 - npc_update_entry(rvu, NPC_LD, entry, NPC_LT_LD_ICMP6, 933 + npc_update_entry(rvu, NPC_LD, mdata, NPC_LT_LD_ICMP6, 1100 934 0, ~0ULL, 0, intf); 1101 935 1102 936 /* For AH, LTYPE should be present in entry */ 1103 937 if (features & BIT_ULL(NPC_IPPROTO_AH)) 1104 - npc_update_entry(rvu, NPC_LD, entry, NPC_LT_LD_AH, 938 + npc_update_entry(rvu, NPC_LD, mdata, NPC_LT_LD_AH, 1105 939 0, ~0ULL, 0, intf); 1106 940 /* For ESP, LTYPE should be present in entry */ 1107 941 if (features & BIT_ULL(NPC_IPPROTO_ESP)) 1108 - npc_update_entry(rvu, NPC_LE, entry, NPC_LT_LE_ESP, 942 + npc_update_entry(rvu, NPC_LE, mdata, NPC_LT_LE_ESP, 1109 943 0, ~0ULL, 0, intf); 1110 944 1111 945 if (features & BIT_ULL(NPC_LXMB)) { 1112 946 output->lxmb = is_broadcast_ether_addr(pkt->dmac) ? 2 : 1; 1113 - npc_update_entry(rvu, NPC_LXMB, entry, output->lxmb, 0, 947 + npc_update_entry(rvu, NPC_LXMB, mdata, output->lxmb, 0, 1114 948 output->lxmb, 0, intf); 1115 949 } 1116 950 #define NPC_WRITE_FLOW(field, member, val_lo, val_hi, mask_lo, mask_hi) \ 1117 951 do { \ 1118 952 if (features & BIT_ULL((field))) { \ 1119 - npc_update_entry(rvu, (field), entry, (val_lo), (val_hi), \ 953 + npc_update_entry(rvu, (field), mdata, (val_lo), (val_hi), \ 1120 954 (mask_lo), (mask_hi), intf); \ 1121 955 memcpy(&opkt->member, &pkt->member, sizeof(pkt->member)); \ 1122 956 memcpy(&omask->member, &mask->member, sizeof(mask->member)); \ ··· 1204 1038 1205 1039 NPC_WRITE_FLOW(NPC_IPFRAG_IPV6, next_header, pkt->next_header, 0, 1206 1040 mask->next_header, 0); 1207 - npc_update_ipv6_flow(rvu, entry, features, pkt, mask, output, intf); 1208 - npc_update_vlan_features(rvu, entry, features, intf); 1041 + npc_update_ipv6_flow(rvu, mdata, features, pkt, mask, output, intf); 1042 + npc_update_vlan_features(rvu, mdata, features, intf); 1209 1043 1210 - npc_update_field_hash(rvu, intf, entry, blkaddr, features, 1044 + npc_update_field_hash(rvu, intf, mdata, blkaddr, features, 1211 1045 pkt, mask, opkt, omask); 1212 1046 } 1213 1047 ··· 1248 1082 struct rvu_npc_mcam_rule *rule) 1249 1083 { 1250 1084 struct npc_mcam *mcam = &rvu->hw->mcam; 1085 + 1086 + /* There is no counter allotted for cn20k */ 1087 + if (is_cn20k(rvu->pdev)) 1088 + return; 1251 1089 1252 1090 mutex_lock(&mcam->lock); 1253 1091 ··· 1299 1129 return 0; 1300 1130 } 1301 1131 1132 + void 1133 + npc_populate_mcam_mdata(struct rvu *rvu, 1134 + struct mcam_entry_mdata *mdata, 1135 + struct cn20k_mcam_entry *cn20k_entry, 1136 + struct mcam_entry *entry) 1137 + { 1138 + if (is_cn20k(rvu->pdev)) { 1139 + mdata->kw = cn20k_entry->kw; 1140 + mdata->kw_mask = cn20k_entry->kw_mask; 1141 + mdata->action = &cn20k_entry->action; 1142 + mdata->vtag_action = &cn20k_entry->vtag_action; 1143 + mdata->max_kw = NPC_KWS_IN_KEY_SZ_8; 1144 + return; 1145 + } 1146 + mdata->kw = entry->kw; 1147 + mdata->kw_mask = entry->kw_mask; 1148 + mdata->action = &entry->action; 1149 + mdata->vtag_action = &entry->vtag_action; 1150 + mdata->max_kw = NPC_KWS_IN_KEY_SZ_7; 1151 + } 1152 + 1302 1153 static int npc_update_rx_entry(struct rvu *rvu, struct rvu_pfvf *pfvf, 1303 - struct mcam_entry *entry, 1154 + struct mcam_entry_mdata *mdata, 1304 1155 struct npc_install_flow_req *req, 1305 1156 u16 target, bool pf_set_vfs_mac) 1306 1157 { ··· 1332 1141 if (rswitch->mode == DEVLINK_ESWITCH_MODE_SWITCHDEV && pf_set_vfs_mac) 1333 1142 req->chan_mask = 0x0; /* Do not care channel */ 1334 1143 1335 - npc_update_entry(rvu, NPC_CHAN, entry, req->channel, 0, req->chan_mask, 1144 + npc_update_entry(rvu, NPC_CHAN, mdata, req->channel, 0, req->chan_mask, 1336 1145 0, NIX_INTF_RX); 1337 1146 1338 1147 *(u64 *)&action = 0x00; ··· 1364 1173 action.match_id = req->match_id; 1365 1174 } 1366 1175 1367 - entry->action = *(u64 *)&action; 1176 + *mdata->action = *(u64 *)&action; 1368 1177 1369 1178 /* VTAG0 starts at 0th byte of LID_B. 1370 1179 * VTAG1 starts at 4th byte of LID_B. 1371 1180 */ 1372 - entry->vtag_action = FIELD_PREP(RX_VTAG0_VALID_BIT, req->vtag0_valid) | 1181 + *mdata->vtag_action = FIELD_PREP(RX_VTAG0_VALID_BIT, req->vtag0_valid) | 1373 1182 FIELD_PREP(RX_VTAG0_TYPE_MASK, req->vtag0_type) | 1374 1183 FIELD_PREP(RX_VTAG0_LID_MASK, NPC_LID_LB) | 1375 1184 FIELD_PREP(RX_VTAG0_RELPTR_MASK, 0) | ··· 1382 1191 } 1383 1192 1384 1193 static int npc_update_tx_entry(struct rvu *rvu, struct rvu_pfvf *pfvf, 1385 - struct mcam_entry *entry, 1194 + struct mcam_entry_mdata *mdata, 1386 1195 struct npc_install_flow_req *req, u16 target) 1387 1196 { 1388 1197 struct nix_tx_action action; ··· 1395 1204 if (is_pffunc_af(req->hdr.pcifunc)) 1396 1205 mask = 0; 1397 1206 1398 - npc_update_entry(rvu, NPC_PF_FUNC, entry, (__force u16)htons(target), 1207 + npc_update_entry(rvu, NPC_PF_FUNC, mdata, (__force u16)htons(target), 1399 1208 0, mask, 0, NIX_INTF_TX); 1400 1209 1401 1210 *(u64 *)&action = 0x00; ··· 1408 1217 1409 1218 action.match_id = req->match_id; 1410 1219 1411 - entry->action = *(u64 *)&action; 1220 + *mdata->action = *(u64 *)&action; 1412 1221 1413 1222 /* VTAG0 starts at 0th byte of LID_B. 1414 1223 * VTAG1 starts at 4th byte of LID_B. 1415 1224 */ 1416 - entry->vtag_action = FIELD_PREP(TX_VTAG0_DEF_MASK, req->vtag0_def) | 1225 + *mdata->vtag_action = FIELD_PREP(TX_VTAG0_DEF_MASK, req->vtag0_def) | 1417 1226 FIELD_PREP(TX_VTAG0_OP_MASK, req->vtag0_op) | 1418 1227 FIELD_PREP(TX_VTAG0_LID_MASK, NPC_LID_LA) | 1419 1228 FIELD_PREP(TX_VTAG0_RELPTR_MASK, 20) | ··· 1432 1241 bool pf_set_vfs_mac) 1433 1242 { 1434 1243 struct rvu_npc_mcam_rule *def_ucast_rule = pfvf->def_ucast_rule; 1244 + struct npc_cn20k_mcam_write_entry_req cn20k_wreq = { 0 }; 1435 1245 u64 features, installed_features, missing_features = 0; 1436 1246 struct npc_mcam_write_entry_req write_req = { 0 }; 1437 1247 struct npc_mcam *mcam = &rvu->hw->mcam; 1248 + struct cn20k_mcam_entry *cn20k_entry; 1249 + struct mcam_entry_mdata mdata = { }; 1438 1250 struct rvu_npc_mcam_rule dummy = { 0 }; 1439 1251 struct rvu_npc_mcam_rule *rule; 1440 1252 u16 owner = req->hdr.pcifunc; ··· 1449 1255 1450 1256 installed_features = req->features; 1451 1257 features = req->features; 1452 - entry = &write_req.entry_data; 1453 1258 entry_index = req->entry; 1454 1259 1455 - npc_update_flow(rvu, entry, features, &req->packet, &req->mask, &dummy, 1260 + cn20k_entry = &cn20k_wreq.entry_data; 1261 + entry = &write_req.entry_data; 1262 + 1263 + npc_populate_mcam_mdata(rvu, &mdata, cn20k_entry, entry); 1264 + 1265 + npc_update_flow(rvu, &mdata, features, &req->packet, &req->mask, &dummy, 1456 1266 req->intf, blkaddr); 1457 1267 1458 1268 if (is_npc_intf_rx(req->intf)) { 1459 - err = npc_update_rx_entry(rvu, pfvf, entry, req, target, pf_set_vfs_mac); 1269 + err = npc_update_rx_entry(rvu, pfvf, &mdata, req, target, 1270 + pf_set_vfs_mac); 1460 1271 if (err) 1461 1272 return err; 1462 1273 } else { 1463 - err = npc_update_tx_entry(rvu, pfvf, entry, req, target); 1274 + err = npc_update_tx_entry(rvu, pfvf, &mdata, req, target); 1464 1275 if (err) 1465 1276 return err; 1466 1277 } ··· 1485 1286 missing_features = (def_ucast_rule->features ^ features) & 1486 1287 def_ucast_rule->features; 1487 1288 if (missing_features) 1488 - npc_update_flow(rvu, entry, missing_features, 1289 + npc_update_flow(rvu, &mdata, missing_features, 1489 1290 &def_ucast_rule->packet, 1490 1291 &def_ucast_rule->mask, 1491 1292 &dummy, req->intf, ··· 1502 1303 new = true; 1503 1304 } 1504 1305 1505 - /* allocate new counter if rule has no counter */ 1506 - if (!req->default_rule && req->set_cntr && !rule->has_cntr) 1507 - rvu_mcam_add_counter_to_rule(rvu, owner, rule, rsp); 1306 + if (!is_cn20k(rvu->pdev)) { 1307 + write_req.hdr.pcifunc = owner; 1508 1308 1509 - /* if user wants to delete an existing counter for a rule then 1510 - * free the counter 1511 - */ 1512 - if (!req->set_cntr && rule->has_cntr) 1513 - rvu_mcam_remove_counter_from_rule(rvu, owner, rule); 1309 + /* allocate new counter if rule has no counter */ 1310 + if (!req->default_rule && req->set_cntr && !rule->has_cntr) 1311 + rvu_mcam_add_counter_to_rule(rvu, owner, rule, rsp); 1514 1312 1515 - write_req.hdr.pcifunc = owner; 1313 + /* if user wants to delete an existing counter for a rule then 1314 + * free the counter 1315 + */ 1316 + if (!req->set_cntr && rule->has_cntr) 1317 + rvu_mcam_remove_counter_from_rule(rvu, owner, rule); 1516 1318 1517 - /* AF owns the default rules so change the owner just to relax 1518 - * the checks in rvu_mbox_handler_npc_mcam_write_entry 1519 - */ 1520 - if (req->default_rule) 1521 - write_req.hdr.pcifunc = 0; 1319 + /* AF owns the default rules so change the owner just to relax 1320 + * the checks in rvu_mbox_handler_npc_mcam_write_entry 1321 + */ 1322 + if (req->default_rule) 1323 + write_req.hdr.pcifunc = 0; 1522 1324 1523 - write_req.entry = entry_index; 1524 - write_req.intf = req->intf; 1525 - write_req.enable_entry = (u8)enable; 1526 - /* if counter is available then clear and use it */ 1527 - if (req->set_cntr && rule->has_cntr) { 1528 - rvu_write64(rvu, blkaddr, NPC_AF_MATCH_STATX(rule->cntr), req->cntr_val); 1529 - write_req.set_cntr = 1; 1530 - write_req.cntr = rule->cntr; 1325 + write_req.entry = entry_index; 1326 + write_req.intf = req->intf; 1327 + write_req.enable_entry = (u8)enable; 1328 + /* if counter is available then clear and use it */ 1329 + if (req->set_cntr && rule->has_cntr) { 1330 + rvu_write64(rvu, blkaddr, 1331 + NPC_AF_MATCH_STATX(rule->cntr), 1332 + req->cntr_val); 1333 + write_req.set_cntr = 1; 1334 + write_req.cntr = rule->cntr; 1335 + } 1336 + goto update_rule; 1531 1337 } 1338 + 1339 + cn20k_wreq.hdr.pcifunc = owner; 1340 + 1341 + if (req->default_rule) 1342 + cn20k_wreq.hdr.pcifunc = 0; 1343 + 1344 + cn20k_wreq.entry = entry_index; 1345 + cn20k_wreq.intf = req->intf; 1346 + cn20k_wreq.enable_entry = (u8)enable; 1347 + cn20k_wreq.hw_prio = req->hw_prio; 1348 + cn20k_wreq.req_kw_type = req->req_kw_type; 1349 + 1350 + update_rule: 1532 1351 1533 1352 /* update rule */ 1534 1353 memcpy(&rule->packet, &dummy.packet, sizeof(rule->packet)); 1535 1354 memcpy(&rule->mask, &dummy.mask, sizeof(rule->mask)); 1536 1355 rule->entry = entry_index; 1537 - memcpy(&rule->rx_action, &entry->action, sizeof(struct nix_rx_action)); 1538 - if (is_npc_intf_tx(req->intf)) 1539 - memcpy(&rule->tx_action, &entry->action, 1540 - sizeof(struct nix_tx_action)); 1541 - rule->vtag_action = entry->vtag_action; 1356 + if (is_cn20k(rvu->pdev)) { 1357 + memcpy(&rule->rx_action, &cn20k_entry->action, 1358 + sizeof(struct nix_rx_action)); 1359 + if (is_npc_intf_tx(req->intf)) 1360 + memcpy(&rule->tx_action, &cn20k_entry->action, 1361 + sizeof(struct nix_tx_action)); 1362 + rule->vtag_action = cn20k_entry->vtag_action; 1363 + } else { 1364 + memcpy(&rule->rx_action, &entry->action, 1365 + sizeof(struct nix_rx_action)); 1366 + if (is_npc_intf_tx(req->intf)) 1367 + memcpy(&rule->tx_action, &entry->action, 1368 + sizeof(struct nix_tx_action)); 1369 + rule->vtag_action = entry->vtag_action; 1370 + } 1371 + 1542 1372 rule->features = installed_features; 1543 1373 rule->default_rule = req->default_rule; 1544 1374 rule->owner = owner; 1545 1375 rule->enable = enable; 1546 - rule->chan_mask = write_req.entry_data.kw_mask[0] & NPC_KEX_CHAN_MASK; 1547 - rule->chan = write_req.entry_data.kw[0] & NPC_KEX_CHAN_MASK; 1376 + 1377 + if (is_cn20k(rvu->pdev)) { 1378 + rule->chan_mask = cn20k_wreq.entry_data.kw_mask[0] & 1379 + NPC_KEX_CHAN_MASK; 1380 + rule->chan = cn20k_wreq.entry_data.kw[0] & 1381 + NPC_KEX_CHAN_MASK; 1382 + } else { 1383 + rule->chan_mask = write_req.entry_data.kw_mask[0] & 1384 + NPC_KEX_CHAN_MASK; 1385 + rule->chan = write_req.entry_data.kw[0] & NPC_KEX_CHAN_MASK; 1386 + } 1387 + 1548 1388 rule->chan &= rule->chan_mask; 1549 1389 rule->lxmb = dummy.lxmb; 1390 + rule->hw_prio = req->hw_prio; 1550 1391 if (is_npc_intf_tx(req->intf)) 1551 1392 rule->intf = pfvf->nix_tx_intf; 1552 1393 else ··· 1598 1359 pfvf->def_ucast_rule = rule; 1599 1360 1600 1361 /* write to mcam entry registers */ 1601 - err = rvu_mbox_handler_npc_mcam_write_entry(rvu, &write_req, 1602 - &write_rsp); 1362 + if (is_cn20k(rvu->pdev)) 1363 + err = rvu_mbox_handler_npc_cn20k_mcam_write_entry(rvu, 1364 + &cn20k_wreq, 1365 + &write_rsp); 1366 + else 1367 + err = rvu_mbox_handler_npc_mcam_write_entry(rvu, &write_req, 1368 + &write_rsp); 1369 + 1603 1370 if (err) { 1604 1371 rvu_mcam_remove_counter_from_rule(rvu, owner, rule); 1605 1372 if (new) { ··· 1638 1393 return 0; 1639 1394 } 1640 1395 1396 + static int 1397 + rvu_npc_free_entry_for_flow_install(struct rvu *rvu, u16 pcifunc, 1398 + bool free_entry, int mcam_idx) 1399 + { 1400 + struct npc_mcam_free_entry_req free_req = { 0 }; 1401 + struct msg_rsp rsp; 1402 + int rc; 1403 + 1404 + if (!free_entry) 1405 + return 0; 1406 + 1407 + free_req.hdr.pcifunc = pcifunc; 1408 + free_req.entry = mcam_idx; 1409 + rc = rvu_mbox_handler_npc_mcam_free_entry(rvu, &free_req, &rsp); 1410 + return rc; 1411 + } 1412 + 1413 + static int 1414 + rvu_npc_alloc_entry_for_flow_install(struct rvu *rvu, 1415 + struct npc_install_flow_req *fl_req, 1416 + u16 *mcam_idx, u8 *kw_type, 1417 + bool *allocated) 1418 + { 1419 + struct npc_mcam_alloc_entry_req entry_req; 1420 + struct npc_mcam_alloc_entry_rsp entry_rsp; 1421 + struct npc_get_num_kws_req kws_req; 1422 + struct npc_get_num_kws_rsp kws_rsp; 1423 + int off, kw_bits, rc; 1424 + u8 *src, *dst; 1425 + 1426 + if (!is_cn20k(rvu->pdev)) { 1427 + *kw_type = -1; 1428 + return 0; 1429 + } 1430 + 1431 + if (!fl_req->alloc_entry) { 1432 + *kw_type = -1; 1433 + return 0; 1434 + } 1435 + 1436 + off = offsetof(struct npc_install_flow_req, packet); 1437 + dst = (u8 *)&kws_req.fl + off; 1438 + src = (u8 *)fl_req + off; 1439 + memcpy(dst, src, sizeof(struct npc_install_flow_req) - off); 1440 + rc = rvu_mbox_handler_npc_get_num_kws(rvu, &kws_req, &kws_rsp); 1441 + if (rc) 1442 + return rc; 1443 + 1444 + kw_bits = kws_rsp.kws * 64; 1445 + 1446 + *kw_type = NPC_MCAM_KEY_X2; 1447 + if (kw_bits > 256) 1448 + *kw_type = NPC_MCAM_KEY_X4; 1449 + 1450 + memset(&entry_req, 0, sizeof(entry_req)); 1451 + memset(&entry_rsp, 0, sizeof(entry_rsp)); 1452 + 1453 + entry_req.hdr.pcifunc = fl_req->hdr.pcifunc; 1454 + entry_req.ref_prio = fl_req->ref_prio; 1455 + entry_req.ref_entry = fl_req->ref_entry; 1456 + entry_req.kw_type = *kw_type; 1457 + entry_req.count = 1; 1458 + rc = rvu_mbox_handler_npc_mcam_alloc_entry(rvu, 1459 + &entry_req, 1460 + &entry_rsp); 1461 + if (rc) 1462 + return rc; 1463 + 1464 + *mcam_idx = entry_rsp.entry_list[0]; 1465 + *allocated = true; 1466 + return 0; 1467 + } 1468 + 1641 1469 int rvu_mbox_handler_npc_install_flow(struct rvu *rvu, 1642 1470 struct npc_install_flow_req *req, 1643 1471 struct npc_install_flow_rsp *rsp) ··· 1721 1403 int blkaddr, nixlf, err; 1722 1404 struct rvu_pfvf *pfvf; 1723 1405 bool pf_set_vfs_mac = false; 1406 + bool allocated = false; 1724 1407 bool enable = true; 1408 + u8 kw_type; 1725 1409 u16 target; 1726 1410 1727 1411 blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); ··· 1734 1414 1735 1415 if (!is_npc_interface_valid(rvu, req->intf)) 1736 1416 return NPC_FLOW_INTF_INVALID; 1417 + 1418 + err = rvu_npc_alloc_entry_for_flow_install(rvu, req, &req->entry, 1419 + &kw_type, &allocated); 1420 + if (err) { 1421 + dev_err(rvu->dev, 1422 + "%s: Error to alloc mcam entry for pcifunc=%#x\n", 1423 + __func__, req->hdr.pcifunc); 1424 + return err; 1425 + } 1426 + 1427 + req->entry = npc_cn20k_vidx2idx(req->entry); 1737 1428 1738 1429 /* If DMAC is not extracted in MKEX, rules installed by AF 1739 1430 * can rely on L2MB bit set by hardware protocol checker for ··· 1759 1428 dev_warn(rvu->dev, 1760 1429 "%s: mkex profile does not support ucast flow\n", 1761 1430 __func__); 1431 + rvu_npc_free_entry_for_flow_install(rvu, 1432 + req->hdr.pcifunc, 1433 + allocated, 1434 + req->entry); 1762 1435 return NPC_FLOW_NOT_SUPPORTED; 1763 1436 } 1764 1437 ··· 1770 1435 dev_warn(rvu->dev, 1771 1436 "%s: mkex profile does not support bcast/mcast flow", 1772 1437 __func__); 1438 + rvu_npc_free_entry_for_flow_install(rvu, 1439 + req->hdr.pcifunc, 1440 + allocated, 1441 + req->entry); 1773 1442 return NPC_FLOW_NOT_SUPPORTED; 1774 1443 } 1775 1444 ··· 1783 1444 } 1784 1445 1785 1446 process_flow: 1786 - if (from_vf && req->default_rule) 1447 + if (from_vf && req->default_rule) { 1448 + rvu_npc_free_entry_for_flow_install(rvu, req->hdr.pcifunc, 1449 + allocated, req->entry); 1787 1450 return NPC_FLOW_VF_PERM_DENIED; 1451 + } 1788 1452 1789 1453 /* Each PF/VF info is maintained in struct rvu_pfvf. 1790 1454 * rvu_pfvf for the target PF/VF needs to be retrieved ··· 1815 1473 req->chan_mask = 0xFFF; 1816 1474 1817 1475 err = npc_check_unsupported_flows(rvu, req->features, req->intf); 1818 - if (err) 1476 + if (err) { 1477 + rvu_npc_free_entry_for_flow_install(rvu, req->hdr.pcifunc, 1478 + allocated, req->entry); 1819 1479 return NPC_FLOW_NOT_SUPPORTED; 1480 + } 1820 1481 1821 1482 pfvf = rvu_get_pfvf(rvu, target); 1822 1483 ··· 1838 1493 1839 1494 /* Proceed if NIXLF is attached or not for TX rules */ 1840 1495 err = nix_get_nixlf(rvu, target, &nixlf, NULL); 1841 - if (err && is_npc_intf_rx(req->intf) && !pf_set_vfs_mac) 1496 + if (err && is_npc_intf_rx(req->intf) && !pf_set_vfs_mac) { 1497 + rvu_npc_free_entry_for_flow_install(rvu, req->hdr.pcifunc, 1498 + allocated, req->entry); 1842 1499 return NPC_FLOW_NO_NIXLF; 1500 + } 1843 1501 1844 1502 /* don't enable rule when nixlf not attached or initialized */ 1845 1503 if (!(is_nixlf_attached(rvu, target) && ··· 1857 1509 enable = true; 1858 1510 1859 1511 /* Do not allow requests from uninitialized VFs */ 1860 - if (from_vf && !enable) 1512 + if (from_vf && !enable) { 1513 + rvu_npc_free_entry_for_flow_install(rvu, req->hdr.pcifunc, 1514 + allocated, req->entry); 1861 1515 return NPC_FLOW_VF_NOT_INIT; 1516 + } 1862 1517 1863 1518 /* PF sets VF mac & VF NIXLF is not attached, update the mac addr */ 1864 1519 if (pf_set_vfs_mac && !enable) { 1865 1520 ether_addr_copy(pfvf->default_mac, req->packet.dmac); 1866 1521 ether_addr_copy(pfvf->mac_addr, req->packet.dmac); 1867 1522 set_bit(PF_SET_VF_MAC, &pfvf->flags); 1523 + rvu_npc_free_entry_for_flow_install(rvu, req->hdr.pcifunc, 1524 + allocated, req->entry); 1868 1525 return 0; 1869 1526 } 1870 1527 1871 1528 mutex_lock(&rswitch->switch_lock); 1872 1529 err = npc_install_flow(rvu, blkaddr, target, nixlf, pfvf, 1873 1530 req, rsp, enable, pf_set_vfs_mac); 1531 + if (err) 1532 + rvu_npc_free_entry_for_flow_install(rvu, req->hdr.pcifunc, 1533 + allocated, req->entry); 1534 + 1535 + rsp->kw_type = kw_type; 1536 + rsp->entry = req->entry; 1874 1537 mutex_unlock(&rswitch->switch_lock); 1875 1538 1876 1539 return err; ··· 1917 1558 u16 pcifunc = req->hdr.pcifunc; 1918 1559 struct list_head del_list; 1919 1560 int blkaddr; 1561 + 1562 + req->entry = npc_cn20k_vidx2idx(req->entry); 1563 + req->start = npc_cn20k_vidx2idx(req->start); 1564 + req->end = npc_cn20k_vidx2idx(req->end); 1920 1565 1921 1566 INIT_LIST_HEAD(&del_list); 1922 1567 ··· 1964 1601 struct rvu_npc_mcam_rule *rule, 1965 1602 struct rvu_pfvf *pfvf) 1966 1603 { 1604 + struct npc_cn20k_mcam_write_entry_req cn20k_wreq = { 0 }; 1967 1605 struct npc_mcam_write_entry_req write_req = { 0 }; 1968 - struct mcam_entry *entry = &write_req.entry_data; 1606 + struct mcam_entry_mdata mdata = { }; 1969 1607 struct npc_mcam *mcam = &rvu->hw->mcam; 1608 + struct cn20k_mcam_entry *cn20k_entry; 1609 + struct mcam_entry *entry; 1610 + u8 intf, enable, hw_prio; 1970 1611 struct msg_rsp rsp; 1971 - u8 intf, enable; 1972 1612 int err; 1613 + 1614 + cn20k_entry = &cn20k_wreq.entry_data; 1615 + entry = &write_req.entry_data; 1616 + npc_populate_mcam_mdata(rvu, &mdata, cn20k_entry, entry); 1973 1617 1974 1618 ether_addr_copy(rule->packet.dmac, pfvf->mac_addr); 1975 1619 1976 - npc_read_mcam_entry(rvu, mcam, npcblkaddr, rule->entry, 1977 - entry, &intf, &enable); 1620 + if (is_cn20k(rvu->pdev)) 1621 + npc_cn20k_read_mcam_entry(rvu, npcblkaddr, rule->entry, 1622 + cn20k_entry, &intf, 1623 + &enable, &hw_prio); 1624 + else 1625 + npc_read_mcam_entry(rvu, mcam, npcblkaddr, rule->entry, 1626 + entry, &intf, &enable); 1978 1627 1979 - npc_update_entry(rvu, NPC_DMAC, entry, 1628 + npc_update_entry(rvu, NPC_DMAC, &mdata, 1980 1629 ether_addr_to_u64(pfvf->mac_addr), 0, 1981 1630 0xffffffffffffull, 0, intf); 1982 1631 1983 - write_req.hdr.pcifunc = rule->owner; 1984 - write_req.entry = rule->entry; 1985 - write_req.intf = pfvf->nix_rx_intf; 1986 - 1987 1632 mutex_unlock(&mcam->lock); 1988 - err = rvu_mbox_handler_npc_mcam_write_entry(rvu, &write_req, &rsp); 1633 + if (is_cn20k(rvu->pdev)) { 1634 + cn20k_wreq.hdr.pcifunc = rule->owner; 1635 + cn20k_wreq.entry = rule->entry; 1636 + cn20k_wreq.intf = pfvf->nix_rx_intf; 1637 + err = rvu_mbox_handler_npc_cn20k_mcam_write_entry(rvu, 1638 + &cn20k_wreq, 1639 + &rsp); 1640 + } else { 1641 + write_req.hdr.pcifunc = rule->owner; 1642 + write_req.entry = rule->entry; 1643 + write_req.intf = pfvf->nix_rx_intf; 1644 + err = rvu_mbox_handler_npc_mcam_write_entry(rvu, &write_req, 1645 + &rsp); 1646 + } 1989 1647 mutex_lock(&mcam->lock); 1990 1648 1991 1649 return err; ··· 2094 1710 u64 chan_val, u64 chan_mask, u64 exact_val, u64 exact_mask, 2095 1711 u64 bcast_mcast_val, u64 bcast_mcast_mask) 2096 1712 { 1713 + struct npc_cn20k_mcam_write_entry_req cn20k_req = { 0 }; 2097 1714 struct npc_mcam_alloc_counter_req cntr_req = { 0 }; 2098 1715 struct npc_mcam_alloc_counter_rsp cntr_rsp = { 0 }; 2099 1716 struct npc_mcam_write_entry_req req = { 0 }; 2100 1717 struct npc_mcam *mcam = &rvu->hw->mcam; 1718 + struct mcam_entry_mdata mdata = { }; 2101 1719 struct rvu_npc_mcam_rule *rule; 2102 1720 struct msg_rsp rsp; 2103 1721 bool enabled; ··· 2143 1757 /* Reserve slot 0 */ 2144 1758 npc_mcam_rsrcs_reserve(rvu, blkaddr, mcam_idx); 2145 1759 2146 - /* Allocate counter for this single drop on non hit rule */ 2147 - cntr_req.hdr.pcifunc = 0; /* AF request */ 2148 - cntr_req.contig = true; 2149 - cntr_req.count = 1; 2150 - err = rvu_mbox_handler_npc_mcam_alloc_counter(rvu, &cntr_req, &cntr_rsp); 2151 - if (err) { 2152 - dev_err(rvu->dev, "%s: Err to allocate cntr for drop rule (err=%d)\n", 2153 - __func__, err); 2154 - return -EFAULT; 1760 + if (!is_cn20k(rvu->pdev)) { 1761 + /* Allocate counter for this single drop on non hit rule */ 1762 + cntr_req.hdr.pcifunc = 0; /* AF request */ 1763 + cntr_req.contig = true; 1764 + cntr_req.count = 1; 1765 + err = rvu_mbox_handler_npc_mcam_alloc_counter(rvu, &cntr_req, 1766 + &cntr_rsp); 1767 + if (err) { 1768 + dev_err(rvu->dev, 1769 + "%s: Err to allocate cntr for drop rule (err=%d)\n", 1770 + __func__, err); 1771 + return -EFAULT; 1772 + } 1773 + *counter_idx = cntr_rsp.cntr; 2155 1774 } 2156 - *counter_idx = cntr_rsp.cntr; 1775 + 1776 + npc_populate_mcam_mdata(rvu, &mdata, 1777 + &cn20k_req.entry_data, 1778 + &req.entry_data); 2157 1779 2158 1780 /* Fill in fields for this mcam entry */ 2159 - npc_update_entry(rvu, NPC_EXACT_RESULT, &req.entry_data, exact_val, 0, 1781 + npc_update_entry(rvu, NPC_EXACT_RESULT, &mdata, exact_val, 0, 2160 1782 exact_mask, 0, NIX_INTF_RX); 2161 - npc_update_entry(rvu, NPC_CHAN, &req.entry_data, chan_val, 0, 1783 + npc_update_entry(rvu, NPC_CHAN, &mdata, chan_val, 0, 2162 1784 chan_mask, 0, NIX_INTF_RX); 2163 - npc_update_entry(rvu, NPC_LXMB, &req.entry_data, bcast_mcast_val, 0, 1785 + npc_update_entry(rvu, NPC_LXMB, &mdata, bcast_mcast_val, 0, 2164 1786 bcast_mcast_mask, 0, NIX_INTF_RX); 1787 + 1788 + if (is_cn20k(rvu->pdev)) { 1789 + cn20k_req.intf = NIX_INTF_RX; 1790 + cn20k_req.entry = mcam_idx; 1791 + 1792 + err = rvu_mbox_handler_npc_cn20k_mcam_write_entry(rvu, 1793 + &cn20k_req, 1794 + &rsp); 1795 + if (err) { 1796 + dev_err(rvu->dev, 1797 + "%s: Installation of single drop on non hit rule at %d failed\n", 1798 + __func__, mcam_idx); 1799 + return err; 1800 + } 1801 + 1802 + goto enable_entry; 1803 + } 2165 1804 2166 1805 req.intf = NIX_INTF_RX; 2167 1806 req.set_cntr = true; ··· 2195 1784 2196 1785 err = rvu_mbox_handler_npc_mcam_write_entry(rvu, &req, &rsp); 2197 1786 if (err) { 2198 - dev_err(rvu->dev, "%s: Installation of single drop on non hit rule at %d failed\n", 1787 + dev_err(rvu->dev, 1788 + "%s: Installation of single drop on non hit rule at %d failed\n", 2199 1789 __func__, mcam_idx); 2200 1790 return err; 2201 1791 } 2202 1792 2203 - dev_err(rvu->dev, "%s: Installed single drop on non hit rule at %d, cntr=%d\n", 1793 + dev_err(rvu->dev, 1794 + "%s: Installed single drop on non hit rule at %d, cntr=%d\n", 2204 1795 __func__, mcam_idx, req.cntr); 2205 1796 1797 + enable_entry: 2206 1798 /* disable entry at Bank 0, index 0 */ 2207 1799 npc_enable_mcam_entry(rvu, mcam, blkaddr, mcam_idx, false); 2208 1800
+13 -1
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.h
··· 15 15 #define NPC_LDATA_EN BIT_ULL(7) 16 16 17 17 void npc_update_entry(struct rvu *rvu, enum key_fields type, 18 - struct mcam_entry *entry, u64 val_lo, 18 + struct mcam_entry_mdata *mdata, u64 val_lo, 19 19 u64 val_hi, u64 mask_lo, u64 mask_hi, u8 intf); 20 + 21 + void npc_update_flow(struct rvu *rvu, struct mcam_entry_mdata *mdata, 22 + u64 features, struct flow_msg *pkt, 23 + struct flow_msg *mask, 24 + struct rvu_npc_mcam_rule *output, u8 intf, 25 + int blkaddr); 26 + 27 + void 28 + npc_populate_mcam_mdata(struct rvu *rvu, 29 + struct mcam_entry_mdata *mdata, 30 + struct cn20k_mcam_entry *cn20k_entry, 31 + struct mcam_entry *entry); 20 32 21 33 #endif /* RVU_NPC_FS_H */
+68 -52
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c
··· 125 125 struct npc_mcam_kex_hash *mkex_hash = rvu->kpu.mkex_hash; 126 126 int lid, lt, ld, hash_cnt = 0; 127 127 128 + if (is_cn20k(rvu->pdev)) 129 + return; 130 + 128 131 if (is_npc_intf_tx(intf)) 129 132 return; 130 133 ··· 167 164 { 168 165 struct npc_mcam_kex_hash *mkex_hash = rvu->kpu.mkex_hash; 169 166 int lid, lt, ld, hash_cnt = 0; 167 + 168 + if (is_cn20k(rvu->pdev)) 169 + return; 170 170 171 171 if (is_npc_intf_rx(intf)) 172 172 return; ··· 230 224 struct rvu_hwinfo *hw = rvu->hw; 231 225 u64 cfg; 232 226 227 + if (is_cn20k(rvu->pdev)) 228 + return; 229 + 233 230 /* Check if hardware supports hash extraction */ 234 231 if (!hwcap->npc_hash_extract) 235 232 return; ··· 282 273 } 283 274 284 275 void npc_update_field_hash(struct rvu *rvu, u8 intf, 285 - struct mcam_entry *entry, 276 + struct mcam_entry_mdata *mdata, 286 277 int blkaddr, 287 278 u64 features, 288 279 struct flow_msg *pkt, ··· 293 284 struct npc_mcam_kex_hash *mkex_hash = rvu->kpu.mkex_hash; 294 285 struct npc_get_field_hash_info_req req; 295 286 struct npc_get_field_hash_info_rsp rsp; 287 + u8 hash_idx, lid, ltype, ltype_mask; 296 288 u64 ldata[2], cfg; 297 289 u32 field_hash; 298 - u8 hash_idx; 290 + bool en; 291 + 292 + if (is_cn20k(rvu->pdev)) 293 + return; 299 294 300 295 if (!rvu->hw->cap.npc_hash_extract) { 301 296 dev_dbg(rvu->dev, "%s: Field hash extract feature is not supported\n", __func__); ··· 311 298 312 299 for (hash_idx = 0; hash_idx < NPC_MAX_HASH; hash_idx++) { 313 300 cfg = rvu_read64(rvu, blkaddr, NPC_AF_INTFX_HASHX_CFG(intf, hash_idx)); 314 - if ((cfg & BIT_ULL(11)) && (cfg & BIT_ULL(12))) { 315 - u8 lid = (cfg & GENMASK_ULL(10, 8)) >> 8; 316 - u8 ltype = (cfg & GENMASK_ULL(7, 4)) >> 4; 317 - u8 ltype_mask = cfg & GENMASK_ULL(3, 0); 301 + en = !!(cfg & BIT_ULL(11)) && (cfg & BIT_ULL(12)); 302 + if (!en) 303 + continue; 318 304 319 - if (mkex_hash->lid_lt_ld_hash_en[intf][lid][ltype][hash_idx]) { 320 - switch (ltype & ltype_mask) { 321 - /* If hash extract enabled is supported for IPv6 then 322 - * 128 bit IPv6 source and destination addressed 323 - * is hashed to 32 bit value. 324 - */ 325 - case NPC_LT_LC_IP6: 326 - /* ld[0] == hash_idx[0] == Source IPv6 327 - * ld[1] == hash_idx[1] == Destination IPv6 328 - */ 329 - if ((features & BIT_ULL(NPC_SIP_IPV6)) && !hash_idx) { 330 - u32 src_ip[IPV6_WORDS]; 305 + lid = (cfg & GENMASK_ULL(10, 8)) >> 8; 306 + ltype = (cfg & GENMASK_ULL(7, 4)) >> 4; 307 + ltype_mask = cfg & GENMASK_ULL(3, 0); 331 308 332 - be32_to_cpu_array(src_ip, pkt->ip6src, IPV6_WORDS); 333 - ldata[1] = (u64)src_ip[0] << 32 | src_ip[1]; 334 - ldata[0] = (u64)src_ip[2] << 32 | src_ip[3]; 335 - field_hash = npc_field_hash_calc(ldata, 336 - rsp, 337 - intf, 338 - hash_idx); 339 - npc_update_entry(rvu, NPC_SIP_IPV6, entry, 340 - field_hash, 0, 341 - GENMASK(31, 0), 0, intf); 342 - memcpy(&opkt->ip6src, &pkt->ip6src, 343 - sizeof(pkt->ip6src)); 344 - memcpy(&omask->ip6src, &mask->ip6src, 345 - sizeof(mask->ip6src)); 346 - } else if ((features & BIT_ULL(NPC_DIP_IPV6)) && hash_idx) { 347 - u32 dst_ip[IPV6_WORDS]; 309 + if (!mkex_hash->lid_lt_ld_hash_en[intf][lid][ltype][hash_idx]) 310 + continue; 348 311 349 - be32_to_cpu_array(dst_ip, pkt->ip6dst, IPV6_WORDS); 350 - ldata[1] = (u64)dst_ip[0] << 32 | dst_ip[1]; 351 - ldata[0] = (u64)dst_ip[2] << 32 | dst_ip[3]; 352 - field_hash = npc_field_hash_calc(ldata, 353 - rsp, 354 - intf, 355 - hash_idx); 356 - npc_update_entry(rvu, NPC_DIP_IPV6, entry, 357 - field_hash, 0, 358 - GENMASK(31, 0), 0, intf); 359 - memcpy(&opkt->ip6dst, &pkt->ip6dst, 360 - sizeof(pkt->ip6dst)); 361 - memcpy(&omask->ip6dst, &mask->ip6dst, 362 - sizeof(mask->ip6dst)); 363 - } 312 + /* If hash extract enabled is supported for IPv6 then 313 + * 128 bit IPv6 source and destination addressed 314 + * is hashed to 32 bit value. 315 + */ 316 + if ((ltype & ltype_mask) != NPC_LT_LC_IP6) 317 + continue; 364 318 365 - break; 366 - } 367 - } 319 + /* ld[0] == hash_idx[0] == Source IPv6 320 + * ld[1] == hash_idx[1] == Destination IPv6 321 + */ 322 + if ((features & BIT_ULL(NPC_SIP_IPV6)) && !hash_idx) { 323 + u32 src_ip[IPV6_WORDS]; 324 + 325 + be32_to_cpu_array(src_ip, pkt->ip6src, IPV6_WORDS); 326 + ldata[1] = (u64)src_ip[0] << 32 | src_ip[1]; 327 + ldata[0] = (u64)src_ip[2] << 32 | src_ip[3]; 328 + field_hash = npc_field_hash_calc(ldata, rsp, intf, 329 + hash_idx); 330 + npc_update_entry(rvu, NPC_SIP_IPV6, mdata, field_hash, 331 + 0, GENMASK(31, 0), 0, intf); 332 + memcpy(&opkt->ip6src, &pkt->ip6src, 333 + sizeof(pkt->ip6src)); 334 + memcpy(&omask->ip6src, &mask->ip6src, 335 + sizeof(mask->ip6src)); 336 + continue; 337 + } 338 + 339 + if ((features & BIT_ULL(NPC_DIP_IPV6)) && hash_idx) { 340 + u32 dst_ip[IPV6_WORDS]; 341 + 342 + be32_to_cpu_array(dst_ip, pkt->ip6dst, IPV6_WORDS); 343 + ldata[1] = (u64)dst_ip[0] << 32 | dst_ip[1]; 344 + ldata[0] = (u64)dst_ip[2] << 32 | dst_ip[3]; 345 + field_hash = npc_field_hash_calc(ldata, rsp, intf, 346 + hash_idx); 347 + npc_update_entry(rvu, NPC_DIP_IPV6, mdata, 348 + field_hash, 0, GENMASK(31, 0), 349 + 0, intf); 350 + memcpy(&opkt->ip6dst, &pkt->ip6dst, 351 + sizeof(pkt->ip6dst)); 352 + memcpy(&omask->ip6dst, &mask->ip6dst, 353 + sizeof(mask->ip6dst)); 354 + continue; 368 355 } 369 356 } 370 357 } ··· 1886 1873 int err, i; 1887 1874 u64 cfg; 1888 1875 bool rc; 1876 + 1877 + if (is_cn20k(rvu->pdev)) 1878 + return 0; 1889 1879 1890 1880 /* Read NPC_AF_CONST3 and check for have exact 1891 1881 * match functionality is present
+1 -1
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.h
··· 53 53 } __packed; 54 54 55 55 void npc_update_field_hash(struct rvu *rvu, u8 intf, 56 - struct mcam_entry *entry, 56 + struct mcam_entry_mdata *mdata, 57 57 int blkaddr, 58 58 u64 features, 59 59 struct flow_msg *pkt,
+266
drivers/net/ethernet/marvell/octeontx2/nic/cn20k.c
··· 251 251 #endif 252 252 } 253 253 254 + static int cn20k_tc_get_entry_index(struct otx2_flow_config *flow_cfg, 255 + struct otx2_tc_flow *node) 256 + { 257 + struct otx2_tc_flow *tmp; 258 + int index = 0; 259 + 260 + list_for_each_entry(tmp, &flow_cfg->flow_list_tc, list) { 261 + if (tmp == node) 262 + return index; 263 + 264 + index++; 265 + } 266 + 267 + return -1; 268 + } 269 + 270 + int cn20k_tc_free_mcam_entry(struct otx2_nic *nic, u16 entry) 271 + { 272 + struct npc_mcam_free_entry_req *req; 273 + int err; 274 + 275 + mutex_lock(&nic->mbox.lock); 276 + req = otx2_mbox_alloc_msg_npc_mcam_free_entry(&nic->mbox); 277 + if (!req) { 278 + mutex_unlock(&nic->mbox.lock); 279 + return -ENOMEM; 280 + } 281 + 282 + req->entry = entry; 283 + /* Send message to AF to free MCAM entries */ 284 + err = otx2_sync_mbox_msg(&nic->mbox); 285 + if (err) { 286 + mutex_unlock(&nic->mbox.lock); 287 + return err; 288 + } 289 + 290 + mutex_unlock(&nic->mbox.lock); 291 + 292 + return 0; 293 + } 294 + 295 + static bool cn20k_tc_check_entry_shiftable(struct otx2_nic *nic, 296 + struct otx2_flow_config *flow_cfg, 297 + struct otx2_tc_flow *node, int index, 298 + bool error) 299 + { 300 + struct otx2_tc_flow *first, *tmp, *n; 301 + u32 prio = 0; 302 + int i = 0; 303 + u8 type; 304 + 305 + first = list_first_entry(&flow_cfg->flow_list_tc, struct otx2_tc_flow, 306 + list); 307 + type = first->kw_type; 308 + 309 + /* Check all the nodes from start to given index (including index) has 310 + * same type i.e, either X2 or X4 311 + */ 312 + list_for_each_entry_safe(tmp, n, &flow_cfg->flow_list_tc, list) { 313 + if (i > index) 314 + break; 315 + 316 + if (type != tmp->kw_type) { 317 + /* List has both X2 and X4 entries so entries cannot be 318 + * shifted to save MCAM space. 319 + */ 320 + if (error) 321 + dev_err(nic->dev, "Rule %d cannot be shifted to %d\n", 322 + tmp->prio, prio); 323 + return false; 324 + } 325 + 326 + type = tmp->kw_type; 327 + prio = tmp->prio; 328 + i++; 329 + } 330 + 331 + return true; 332 + } 333 + 334 + void cn20k_tc_update_mcam_table_del_req(struct otx2_nic *nic, 335 + struct otx2_flow_config *flow_cfg, 336 + struct otx2_tc_flow *node) 337 + { 338 + struct otx2_tc_flow *first, *tmp, *n; 339 + int i = 0, index; 340 + u16 cntr_val = 0; 341 + u16 entry; 342 + 343 + index = cn20k_tc_get_entry_index(flow_cfg, node); 344 + if (index < 0) { 345 + netdev_dbg(nic->netdev, "Could not find node\n"); 346 + return; 347 + } 348 + 349 + first = list_first_entry(&flow_cfg->flow_list_tc, struct otx2_tc_flow, 350 + list); 351 + entry = first->entry; 352 + 353 + /* If entries cannot be shifted then delete given entry 354 + * and free it to AF too. 355 + */ 356 + if (!cn20k_tc_check_entry_shiftable(nic, flow_cfg, node, 357 + index, false)) { 358 + list_del(&node->list); 359 + entry = node->entry; 360 + goto free_mcam_entry; 361 + } 362 + 363 + /* Find and delete the entry from the list and re-install 364 + * all the entries from beginning to the index of the 365 + * deleted entry to higher mcam indexes. 366 + */ 367 + list_for_each_entry_safe(tmp, n, &flow_cfg->flow_list_tc, list) { 368 + if (node == tmp) { 369 + list_del(&tmp->list); 370 + break; 371 + } 372 + 373 + otx2_del_mcam_flow_entry(nic, tmp->entry, &cntr_val); 374 + tmp->entry = (list_next_entry(tmp, list))->entry; 375 + tmp->req.entry = tmp->entry; 376 + tmp->req.cntr_val = cntr_val; 377 + } 378 + 379 + list_for_each_entry_safe(tmp, n, &flow_cfg->flow_list_tc, list) { 380 + if (i == index) 381 + break; 382 + 383 + otx2_add_mcam_flow_entry(nic, &tmp->req); 384 + i++; 385 + } 386 + 387 + free_mcam_entry: 388 + if (cn20k_tc_free_mcam_entry(nic, entry)) 389 + netdev_err(nic->netdev, "Freeing entry %d to AF failed\n", 390 + entry); 391 + } 392 + 393 + int cn20k_tc_update_mcam_table_add_req(struct otx2_nic *nic, 394 + struct otx2_flow_config *flow_cfg, 395 + struct otx2_tc_flow *node) 396 + { 397 + struct otx2_tc_flow *tmp; 398 + u16 cntr_val = 0; 399 + int list_idx, i; 400 + int entry, prev; 401 + 402 + /* Find the index of the entry(list_idx) whose priority 403 + * is greater than the new entry and re-install all 404 + * the entries from beginning to list_idx to higher 405 + * mcam indexes. 406 + */ 407 + list_idx = otx2_tc_add_to_flow_list(flow_cfg, node); 408 + entry = node->entry; 409 + if (!cn20k_tc_check_entry_shiftable(nic, flow_cfg, node, 410 + list_idx, true)) 411 + /* Due to mix of X2 and X4, entries cannot be shifted. 412 + * In this case free the entry allocated for this rule. 413 + */ 414 + return -EINVAL; 415 + 416 + for (i = 0; i < list_idx; i++) { 417 + tmp = otx2_tc_get_entry_by_index(flow_cfg, i); 418 + if (!tmp) 419 + return -ENOMEM; 420 + 421 + otx2_del_mcam_flow_entry(nic, tmp->entry, &cntr_val); 422 + prev = tmp->entry; 423 + tmp->entry = entry; 424 + tmp->req.entry = tmp->entry; 425 + tmp->req.cntr_val = cntr_val; 426 + otx2_add_mcam_flow_entry(nic, &tmp->req); 427 + entry = prev; 428 + } 429 + 430 + return entry; 431 + } 432 + 433 + #define MAX_TC_HW_PRIORITY 125 434 + #define MAX_TC_VF_PRIORITY 126 435 + #define MAX_TC_PF_PRIORITY 127 436 + 437 + static int __cn20k_tc_alloc_entry(struct otx2_nic *nic, 438 + struct npc_install_flow_req *flow_req, 439 + u16 *entry, u8 *type, 440 + u32 tc_priority, bool hw_priority) 441 + { 442 + struct otx2_flow_config *flow_cfg = nic->flow_cfg; 443 + struct npc_install_flow_req *req; 444 + struct npc_install_flow_rsp *rsp; 445 + struct otx2_tc_flow *tmp; 446 + int ret = 0; 447 + 448 + req = otx2_mbox_alloc_msg_npc_install_flow(&nic->mbox); 449 + if (!req) 450 + return -ENOMEM; 451 + 452 + memcpy(&flow_req->hdr, &req->hdr, sizeof(struct mbox_msghdr)); 453 + memcpy(req, flow_req, sizeof(struct npc_install_flow_req)); 454 + req->alloc_entry = 1; 455 + 456 + /* Allocate very least priority for first rule */ 457 + if (hw_priority || list_empty(&flow_cfg->flow_list_tc)) { 458 + req->ref_prio = NPC_MCAM_LEAST_PRIO; 459 + } else { 460 + req->ref_prio = NPC_MCAM_HIGHER_PRIO; 461 + tmp = list_first_entry(&flow_cfg->flow_list_tc, 462 + struct otx2_tc_flow, list); 463 + req->ref_entry = tmp->entry; 464 + } 465 + 466 + ret = otx2_sync_mbox_msg(&nic->mbox); 467 + if (ret) 468 + return ret; 469 + 470 + rsp = (struct npc_install_flow_rsp *)otx2_mbox_get_rsp(&nic->mbox.mbox, 471 + 0, &req->hdr); 472 + if (IS_ERR(rsp)) 473 + return -EFAULT; 474 + 475 + if (entry) 476 + *entry = rsp->entry; 477 + if (type) 478 + *type = rsp->kw_type; 479 + 480 + return ret; 481 + } 482 + 483 + int cn20k_tc_alloc_entry(struct otx2_nic *nic, 484 + struct flow_cls_offload *tc_flow_cmd, 485 + struct otx2_tc_flow *new_node, 486 + struct npc_install_flow_req *flow_req) 487 + { 488 + bool hw_priority = false; 489 + u16 entry_from_af; 490 + u8 entry_type; 491 + int ret; 492 + 493 + if (is_otx2_vf(nic->pcifunc)) 494 + flow_req->hw_prio = MAX_TC_VF_PRIORITY; 495 + else 496 + flow_req->hw_prio = MAX_TC_PF_PRIORITY; 497 + 498 + if (new_node->prio <= MAX_TC_HW_PRIORITY) { 499 + flow_req->hw_prio = new_node->prio; 500 + hw_priority = true; 501 + } 502 + 503 + mutex_lock(&nic->mbox.lock); 504 + 505 + ret = __cn20k_tc_alloc_entry(nic, flow_req, &entry_from_af, &entry_type, 506 + new_node->prio, hw_priority); 507 + if (ret) { 508 + mutex_unlock(&nic->mbox.lock); 509 + return ret; 510 + } 511 + 512 + new_node->kw_type = entry_type; 513 + new_node->entry = entry_from_af; 514 + 515 + mutex_unlock(&nic->mbox.lock); 516 + 517 + return 0; 518 + } 519 + 254 520 static int cn20k_aura_aq_init(struct otx2_nic *pfvf, int aura_id, 255 521 int pool_id, int numptrs) 256 522 {
+14
drivers/net/ethernet/marvell/octeontx2/nic/cn20k.h
··· 10 10 11 11 #include "otx2_common.h" 12 12 13 + struct otx2_flow_config; 14 + struct otx2_tc_flow; 15 + 13 16 void cn20k_init(struct otx2_nic *pfvf); 14 17 int cn20k_register_pfvf_mbox_intr(struct otx2_nic *pf, int numvfs); 15 18 void cn20k_disable_pfvf_mbox_intr(struct otx2_nic *pf, int numvfs); 16 19 void cn20k_enable_pfvf_mbox_intr(struct otx2_nic *pf, int numvfs); 20 + void cn20k_tc_update_mcam_table_del_req(struct otx2_nic *nic, 21 + struct otx2_flow_config *flow_cfg, 22 + struct otx2_tc_flow *node); 23 + int cn20k_tc_update_mcam_table_add_req(struct otx2_nic *nic, 24 + struct otx2_flow_config *flow_cfg, 25 + struct otx2_tc_flow *node); 26 + int cn20k_tc_alloc_entry(struct otx2_nic *nic, 27 + struct flow_cls_offload *tc_flow_cmd, 28 + struct otx2_tc_flow *new_node, 29 + struct npc_install_flow_req *dummy); 30 + int cn20k_tc_free_mcam_entry(struct otx2_nic *nic, u16 entry); 17 31 #endif /* CN20K_H */
+35
drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
··· 366 366 u16 ntuple_cnt; 367 367 }; 368 368 369 + struct otx2_tc_flow_stats { 370 + u64 bytes; 371 + u64 pkts; 372 + u64 used; 373 + }; 374 + 375 + struct otx2_tc_flow { 376 + struct list_head list; 377 + unsigned long cookie; 378 + struct rcu_head rcu; 379 + struct otx2_tc_flow_stats stats; 380 + spinlock_t lock; /* lock for stats */ 381 + u16 rq; 382 + u16 entry; 383 + u16 leaf_profile; 384 + bool is_act_police; 385 + u32 prio; 386 + struct npc_install_flow_req req; 387 + u64 rate; 388 + u32 burst; 389 + u32 mcast_grp_idx; 390 + bool is_pps; 391 + u8 kw_type; /* X2/X4 */ 392 + }; 393 + 369 394 struct dev_hw_ops { 370 395 int (*sq_aq_init)(void *dev, u16 qidx, u8 chan_offset, 371 396 u16 sqb_aura); ··· 1248 1223 int otx2_read_free_sqe(struct otx2_nic *pfvf, u16 qidx); 1249 1224 void otx2_queue_vf_work(struct mbox *mw, struct workqueue_struct *mbox_wq, 1250 1225 int first, int mdevs, u64 intr); 1226 + int otx2_del_mcam_flow_entry(struct otx2_nic *nic, u16 entry, 1227 + u16 *cntr_val); 1228 + int otx2_add_mcam_flow_entry(struct otx2_nic *nic, 1229 + struct npc_install_flow_req *req); 1230 + int otx2_tc_add_to_flow_list(struct otx2_flow_config *flow_cfg, 1231 + struct otx2_tc_flow *node); 1232 + 1233 + struct otx2_tc_flow * 1234 + otx2_tc_get_entry_by_index(struct otx2_flow_config *flow_cfg, 1235 + int index); 1251 1236 #endif /* OTX2_COMMON_H */
+253 -14
drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
··· 37 37 flow_cfg->max_flows = 0; 38 38 } 39 39 40 + static int otx2_mcam_pfl_info_get(struct otx2_nic *pfvf, bool *is_x2, 41 + u16 *x4_slots) 42 + { 43 + struct npc_get_pfl_info_rsp *rsp; 44 + struct msg_req *req; 45 + static struct { 46 + bool is_set; 47 + bool is_x2; 48 + u16 x4_slots; 49 + } pfl_info; 50 + 51 + /* Avoid sending mboxes for constant information 52 + * like x4_slots 53 + */ 54 + mutex_lock(&pfvf->mbox.lock); 55 + if (pfl_info.is_set) { 56 + *is_x2 = pfl_info.is_x2; 57 + *x4_slots = pfl_info.x4_slots; 58 + mutex_unlock(&pfvf->mbox.lock); 59 + return 0; 60 + } 61 + 62 + req = otx2_mbox_alloc_msg_npc_get_pfl_info(&pfvf->mbox); 63 + if (!req) { 64 + mutex_unlock(&pfvf->mbox.lock); 65 + return -ENOMEM; 66 + } 67 + 68 + /* Send message to AF */ 69 + if (otx2_sync_mbox_msg(&pfvf->mbox)) { 70 + mutex_unlock(&pfvf->mbox.lock); 71 + return -EFAULT; 72 + } 73 + 74 + rsp = (struct npc_get_pfl_info_rsp *)otx2_mbox_get_rsp 75 + (&pfvf->mbox.mbox, 0, &req->hdr); 76 + 77 + if (IS_ERR(rsp)) { 78 + mutex_unlock(&pfvf->mbox.lock); 79 + return -EFAULT; 80 + } 81 + 82 + *is_x2 = (rsp->kw_type == NPC_MCAM_KEY_X2); 83 + if (*is_x2) 84 + *x4_slots = 0; 85 + else 86 + *x4_slots = rsp->x4_slots; 87 + 88 + pfl_info.is_x2 = *is_x2; 89 + pfl_info.x4_slots = *x4_slots; 90 + pfl_info.is_set = true; 91 + 92 + mutex_unlock(&pfvf->mbox.lock); 93 + return 0; 94 + } 95 + 96 + static int otx2_get_dft_rl_idx(struct otx2_nic *pfvf, u16 *mcam_idx) 97 + { 98 + struct npc_get_dft_rl_idxs_rsp *rsp; 99 + struct msg_req *req; 100 + 101 + mutex_lock(&pfvf->mbox.lock); 102 + 103 + req = otx2_mbox_alloc_msg_npc_get_dft_rl_idxs(&pfvf->mbox); 104 + if (!req) { 105 + mutex_unlock(&pfvf->mbox.lock); 106 + return -ENOMEM; 107 + } 108 + 109 + /* Send message to AF */ 110 + if (otx2_sync_mbox_msg(&pfvf->mbox)) { 111 + mutex_unlock(&pfvf->mbox.lock); 112 + return -EINVAL; 113 + } 114 + 115 + rsp = (struct npc_get_dft_rl_idxs_rsp *)otx2_mbox_get_rsp 116 + (&pfvf->mbox.mbox, 0, &req->hdr); 117 + 118 + if (IS_ERR(rsp)) { 119 + mutex_unlock(&pfvf->mbox.lock); 120 + return -EFAULT; 121 + } 122 + 123 + if (is_otx2_lbkvf(pfvf->pdev)) 124 + *mcam_idx = rsp->promisc; 125 + else 126 + *mcam_idx = rsp->ucast; 127 + 128 + mutex_unlock(&pfvf->mbox.lock); 129 + return 0; 130 + } 131 + 40 132 static int otx2_free_ntuple_mcam_entries(struct otx2_nic *pfvf) 41 133 { 42 134 struct otx2_flow_config *flow_cfg = pfvf->flow_cfg; ··· 161 69 struct otx2_flow_config *flow_cfg = pfvf->flow_cfg; 162 70 struct npc_mcam_alloc_entry_req *req; 163 71 struct npc_mcam_alloc_entry_rsp *rsp; 164 - int ent, allocated = 0; 72 + u16 dft_idx = 0, x4_slots = 0; 73 + int ent, allocated = 0, ref; 74 + bool is_x2 = false; 75 + int rc; 165 76 166 77 /* Free current ones and allocate new ones with requested count */ 167 78 otx2_free_ntuple_mcam_entries(pfvf); ··· 181 86 return -ENOMEM; 182 87 } 183 88 89 + if (is_cn20k(pfvf->pdev)) { 90 + rc = otx2_mcam_pfl_info_get(pfvf, &is_x2, &x4_slots); 91 + if (rc) { 92 + netdev_err(pfvf->netdev, "Error to retrieve profile info\n"); 93 + return rc; 94 + } 95 + 96 + rc = otx2_get_dft_rl_idx(pfvf, &dft_idx); 97 + if (rc) { 98 + netdev_err(pfvf->netdev, 99 + "Error to retrieve ucast mcam idx for pcifunc %#x\n", 100 + pfvf->pcifunc); 101 + return rc; 102 + } 103 + } 104 + 184 105 mutex_lock(&pfvf->mbox.lock); 185 106 186 107 /* In a single request a max of NPC_MAX_NONCONTIG_ENTRIES MCAM entries ··· 207 96 if (!req) 208 97 goto exit; 209 98 99 + req->kw_type = is_x2 ? NPC_MCAM_KEY_X2 : NPC_MCAM_KEY_X4; 210 100 req->contig = false; 211 101 req->count = (count - allocated) > NPC_MAX_NONCONTIG_ENTRIES ? 212 102 NPC_MAX_NONCONTIG_ENTRIES : count - allocated; 103 + 104 + ref = 0; 105 + 106 + if (is_cn20k(pfvf->pdev)) { 107 + req->ref_prio = NPC_MCAM_HIGHER_PRIO; 108 + ref = dft_idx; 109 + } 213 110 214 111 /* Allocate higher priority entries for PFs, so that VF's entries 215 112 * will be on top of PF. 216 113 */ 217 114 if (!is_otx2_vf(pfvf->pcifunc)) { 218 - req->priority = NPC_MCAM_HIGHER_PRIO; 219 - req->ref_entry = flow_cfg->def_ent[0]; 115 + req->ref_prio = NPC_MCAM_HIGHER_PRIO; 116 + ref = flow_cfg->def_ent[0]; 220 117 } 118 + 119 + if (is_cn20k(pfvf->pdev)) 120 + ref = is_x2 ? ref : ref & (x4_slots - 1); 121 + 122 + req->ref_entry = ref; 221 123 222 124 /* Send message to AF */ 223 125 if (otx2_sync_mbox_msg(&pfvf->mbox)) ··· 287 163 struct npc_get_field_status_rsp *frsp; 288 164 struct npc_mcam_alloc_entry_req *req; 289 165 struct npc_mcam_alloc_entry_rsp *rsp; 290 - int vf_vlan_max_flows; 291 - int ent, count; 166 + int vf_vlan_max_flows, count; 167 + int rc, ref, prio, ent; 168 + u16 dft_idx; 169 + 170 + ref = 0; 171 + prio = 0; 172 + if (is_cn20k(pfvf->pdev)) { 173 + rc = otx2_get_dft_rl_idx(pfvf, &dft_idx); 174 + if (rc) { 175 + netdev_err(pfvf->netdev, 176 + "Error to retrieve ucast mcam idx for pcifunc %#x\n", 177 + pfvf->pcifunc); 178 + return rc; 179 + } 180 + 181 + ref = dft_idx; 182 + prio = NPC_MCAM_HIGHER_PRIO; 183 + } 292 184 293 185 vf_vlan_max_flows = pfvf->total_vfs * OTX2_PER_VF_VLAN_FLOWS; 294 186 count = flow_cfg->ucast_flt_cnt + ··· 323 183 return -ENOMEM; 324 184 } 325 185 186 + req->kw_type = NPC_MCAM_KEY_X2; 326 187 req->contig = false; 327 188 req->count = count; 189 + req->ref_prio = prio; 190 + req->ref_entry = ref; 328 191 329 192 /* Send message to AF */ 330 193 if (otx2_sync_mbox_msg(&pfvf->mbox)) { ··· 962 819 } 963 820 964 821 static int otx2_prepare_flow_request(struct ethtool_rx_flow_spec *fsp, 965 - struct npc_install_flow_req *req) 822 + struct npc_install_flow_req *req) 966 823 { 967 824 struct ethhdr *eth_mask = &fsp->m_u.ether_spec; 968 825 struct ethhdr *eth_hdr = &fsp->h_u.ether_spec; ··· 1088 945 return 0; 1089 946 } 1090 947 948 + static int otx2_get_kw_type(struct otx2_nic *pfvf, 949 + struct npc_install_flow_req *fl_req, 950 + u8 *kw_type) 951 + { 952 + struct npc_get_num_kws_req *req; 953 + struct npc_get_num_kws_rsp *rsp; 954 + u8 *src, *dst; 955 + int off, err; 956 + int kw_bits; 957 + 958 + off = offsetof(struct npc_install_flow_req, packet); 959 + 960 + mutex_lock(&pfvf->mbox.lock); 961 + 962 + req = otx2_mbox_alloc_msg_npc_get_num_kws(&pfvf->mbox); 963 + if (!req) { 964 + mutex_unlock(&pfvf->mbox.lock); 965 + return -ENOMEM; 966 + } 967 + 968 + dst = (u8 *)&req->fl + off; 969 + src = (u8 *)fl_req + off; 970 + 971 + memcpy(dst, src, sizeof(struct npc_install_flow_req) - off); 972 + 973 + err = otx2_sync_mbox_msg(&pfvf->mbox); 974 + if (err) { 975 + mutex_unlock(&pfvf->mbox.lock); 976 + netdev_err(pfvf->netdev, 977 + "Error to get default number of keywords\n"); 978 + return err; 979 + } 980 + 981 + rsp = (struct npc_get_num_kws_rsp *)otx2_mbox_get_rsp 982 + (&pfvf->mbox.mbox, 0, &req->hdr); 983 + if (IS_ERR(rsp)) { 984 + mutex_unlock(&pfvf->mbox.lock); 985 + return -EFAULT; 986 + } 987 + 988 + kw_bits = rsp->kws * 64; 989 + 990 + if (kw_bits <= 256) 991 + *kw_type = NPC_MCAM_KEY_X2; 992 + else 993 + *kw_type = NPC_MCAM_KEY_X4; 994 + 995 + mutex_unlock(&pfvf->mbox.lock); 996 + 997 + return 0; 998 + } 999 + 1091 1000 static int otx2_is_flow_rule_dmacfilter(struct otx2_nic *pfvf, 1092 1001 struct ethtool_rx_flow_spec *fsp) 1093 1002 { ··· 1168 973 1169 974 static int otx2_add_flow_msg(struct otx2_nic *pfvf, struct otx2_flow *flow) 1170 975 { 976 + struct otx2_flow_config *flow_cfg = pfvf->flow_cfg; 977 + struct npc_install_flow_req *req, treq = { 0 }; 1171 978 u64 ring_cookie = flow->flow_spec.ring_cookie; 1172 979 #ifdef CONFIG_DCB 1173 980 int vlan_prio, qidx, pfc_rule = 0; 1174 981 #endif 1175 - struct npc_install_flow_req *req; 1176 - int err, vf = 0; 982 + int err, vf = 0, off, sz; 983 + bool modify = false; 984 + u8 kw_type = 0; 985 + u8 *src, *dst; 986 + u16 x4_slots; 987 + bool is_x2; 988 + 989 + if (is_cn20k(pfvf->pdev)) { 990 + err = otx2_mcam_pfl_info_get(pfvf, &is_x2, &x4_slots); 991 + if (err) { 992 + netdev_err(pfvf->netdev, 993 + "Error to retrieve NPC profile info, pcifunc=%#x\n", 994 + pfvf->pcifunc); 995 + return -EFAULT; 996 + } 997 + 998 + if (!is_x2) { 999 + err = otx2_prepare_flow_request(&flow->flow_spec, 1000 + &treq); 1001 + if (err) 1002 + return err; 1003 + 1004 + err = otx2_get_kw_type(pfvf, &treq, &kw_type); 1005 + if (err) 1006 + return err; 1007 + 1008 + modify = true; 1009 + } 1010 + } 1177 1011 1178 1012 mutex_lock(&pfvf->mbox.lock); 1179 1013 req = otx2_mbox_alloc_msg_npc_install_flow(&pfvf->mbox); ··· 1211 987 return -ENOMEM; 1212 988 } 1213 989 1214 - err = otx2_prepare_flow_request(&flow->flow_spec, req); 1215 - if (err) { 1216 - /* free the allocated msg above */ 1217 - otx2_mbox_reset(&pfvf->mbox.mbox, 0); 1218 - mutex_unlock(&pfvf->mbox.lock); 1219 - return err; 990 + if (modify) { 991 + off = offsetof(struct npc_install_flow_req, packet); 992 + sz = sizeof(struct npc_install_flow_req) - off; 993 + dst = (u8 *)req + off; 994 + src = (u8 *)&treq + off; 995 + 996 + memcpy(dst, src, sz); 997 + req->req_kw_type = kw_type; 998 + } else { 999 + err = otx2_prepare_flow_request(&flow->flow_spec, req); 1000 + if (err) { 1001 + /* free the allocated msg above */ 1002 + otx2_mbox_reset(&pfvf->mbox.mbox, 0); 1003 + mutex_unlock(&pfvf->mbox.lock); 1004 + return err; 1005 + } 1220 1006 } 1007 + 1008 + netdev_dbg(pfvf->netdev, 1009 + "flow entry (%u) installed at loc:%u kw_type=%u\n", 1010 + flow_cfg->flow_ent[flow->location], 1011 + flow->location, kw_type); 1221 1012 1222 1013 req->entry = flow->entry; 1223 1014 req->intf = NIX_INTF_RX;
+41 -38
drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c
··· 31 31 32 32 #define MCAST_INVALID_GRP (-1U) 33 33 34 - struct otx2_tc_flow_stats { 35 - u64 bytes; 36 - u64 pkts; 37 - u64 used; 38 - }; 39 - 40 - struct otx2_tc_flow { 41 - struct list_head list; 42 - unsigned long cookie; 43 - struct rcu_head rcu; 44 - struct otx2_tc_flow_stats stats; 45 - spinlock_t lock; /* lock for stats */ 46 - u16 rq; 47 - u16 entry; 48 - u16 leaf_profile; 49 - bool is_act_police; 50 - u32 prio; 51 - struct npc_install_flow_req req; 52 - u32 mcast_grp_idx; 53 - u64 rate; 54 - u32 burst; 55 - bool is_pps; 56 - }; 57 - 58 34 static void otx2_get_egress_burst_cfg(struct otx2_nic *nic, u32 burst, 59 35 u32 *burst_exp, u32 *burst_mantissa) 60 36 { ··· 947 971 } 948 972 } 949 973 950 - static struct otx2_tc_flow *otx2_tc_get_entry_by_cookie(struct otx2_flow_config *flow_cfg, 951 - unsigned long cookie) 974 + static struct otx2_tc_flow * 975 + otx2_tc_get_entry_by_cookie(struct otx2_flow_config *flow_cfg, 976 + unsigned long cookie) 952 977 { 953 978 struct otx2_tc_flow *tmp; 954 979 ··· 961 984 return NULL; 962 985 } 963 986 964 - static struct otx2_tc_flow *otx2_tc_get_entry_by_index(struct otx2_flow_config *flow_cfg, 965 - int index) 987 + struct otx2_tc_flow * 988 + otx2_tc_get_entry_by_index(struct otx2_flow_config *flow_cfg, int index) 966 989 { 967 990 struct otx2_tc_flow *tmp; 968 991 int i = 0; ··· 991 1014 } 992 1015 } 993 1016 994 - static int otx2_tc_add_to_flow_list(struct otx2_flow_config *flow_cfg, 995 - struct otx2_tc_flow *node) 1017 + int otx2_tc_add_to_flow_list(struct otx2_flow_config *flow_cfg, 1018 + struct otx2_tc_flow *node) 996 1019 { 997 1020 struct list_head *pos, *n; 998 1021 struct otx2_tc_flow *tmp; ··· 1015 1038 return index; 1016 1039 } 1017 1040 1018 - static int otx2_add_mcam_flow_entry(struct otx2_nic *nic, struct npc_install_flow_req *req) 1041 + int otx2_add_mcam_flow_entry(struct otx2_nic *nic, 1042 + struct npc_install_flow_req *req) 1019 1043 { 1020 1044 struct npc_install_flow_req *tmp_req; 1021 1045 int err; ··· 1042 1064 return 0; 1043 1065 } 1044 1066 1045 - static int otx2_del_mcam_flow_entry(struct otx2_nic *nic, u16 entry, u16 *cntr_val) 1067 + int otx2_del_mcam_flow_entry(struct otx2_nic *nic, u16 entry, u16 *cntr_val) 1046 1068 { 1047 1069 struct npc_delete_flow_rsp *rsp; 1048 1070 struct npc_delete_flow_req *req; ··· 1092 1114 int i = 0, index = 0; 1093 1115 u16 cntr_val = 0; 1094 1116 1117 + if (is_cn20k(nic->pdev)) { 1118 + cn20k_tc_update_mcam_table_del_req(nic, flow_cfg, node); 1119 + return 0; 1120 + } 1121 + 1095 1122 /* Find and delete the entry from the list and re-install 1096 1123 * all the entries from beginning to the index of the 1097 1124 * deleted entry to higher mcam indexes. ··· 1136 1153 int list_idx, i; 1137 1154 u16 cntr_val = 0; 1138 1155 1156 + if (is_cn20k(nic->pdev)) 1157 + return cn20k_tc_update_mcam_table_add_req(nic, flow_cfg, node); 1158 + 1139 1159 /* Find the index of the entry(list_idx) whose priority 1140 1160 * is greater than the new entry and re-install all 1141 1161 * the entries from beginning to list_idx to higher ··· 1158 1172 mcam_idx++; 1159 1173 } 1160 1174 1161 - return mcam_idx; 1175 + return flow_cfg->flow_ent[mcam_idx]; 1162 1176 } 1163 1177 1164 1178 static int otx2_tc_update_mcam_table(struct otx2_nic *nic, ··· 1224 1238 mutex_unlock(&nic->mbox.lock); 1225 1239 } 1226 1240 1227 - 1228 1241 free_mcam_flow: 1229 1242 otx2_del_mcam_flow_entry(nic, flow_node->entry, NULL); 1230 1243 otx2_tc_update_mcam_table(nic, flow_cfg, flow_node, false); ··· 1239 1254 struct otx2_flow_config *flow_cfg = nic->flow_cfg; 1240 1255 struct otx2_tc_flow *new_node, *old_node; 1241 1256 struct npc_install_flow_req *req, dummy; 1242 - int rc, err, mcam_idx; 1257 + int rc, err, entry; 1243 1258 1244 1259 if (!(nic->flags & OTX2_FLAG_TC_FLOWER_SUPPORT)) 1245 1260 return -ENOMEM; ··· 1249 1264 return -EINVAL; 1250 1265 } 1251 1266 1252 - if (flow_cfg->nr_flows == flow_cfg->max_flows) { 1267 + if (!is_cn20k(nic->pdev) && flow_cfg->nr_flows == flow_cfg->max_flows) { 1253 1268 NL_SET_ERR_MSG_MOD(extack, 1254 1269 "Free MCAM entry not available to add the flow"); 1255 1270 return -ENOMEM; ··· 1277 1292 if (old_node) 1278 1293 otx2_tc_del_flow(nic, tc_flow_cmd); 1279 1294 1280 - mcam_idx = otx2_tc_update_mcam_table(nic, flow_cfg, new_node, true); 1295 + if (is_cn20k(nic->pdev)) { 1296 + rc = cn20k_tc_alloc_entry(nic, tc_flow_cmd, new_node, &dummy); 1297 + if (rc) { 1298 + NL_SET_ERR_MSG_MOD(extack, 1299 + "MCAM rule allocation failed"); 1300 + kfree_rcu(new_node, rcu); 1301 + return rc; 1302 + } 1303 + } 1304 + 1305 + entry = otx2_tc_update_mcam_table(nic, flow_cfg, new_node, true); 1306 + if (entry < 0) { 1307 + NL_SET_ERR_MSG_MOD(extack, "Adding rule failed"); 1308 + rc = entry; 1309 + goto free_leaf; 1310 + } 1311 + 1281 1312 mutex_lock(&nic->mbox.lock); 1282 1313 req = otx2_mbox_alloc_msg_npc_install_flow(&nic->mbox); 1283 1314 if (!req) { ··· 1305 1304 memcpy(&dummy.hdr, &req->hdr, sizeof(struct mbox_msghdr)); 1306 1305 memcpy(req, &dummy, sizeof(struct npc_install_flow_req)); 1307 1306 req->channel = nic->hw.rx_chan_base; 1308 - req->entry = flow_cfg->flow_ent[mcam_idx]; 1307 + req->entry = (u16)entry; 1309 1308 req->intf = NIX_INTF_RX; 1310 1309 req->vf = nic->pcifunc; 1311 1310 req->set_cntr = 1; ··· 1326 1325 return 0; 1327 1326 1328 1327 free_leaf: 1328 + if (is_cn20k(nic->pdev)) 1329 + cn20k_tc_free_mcam_entry(nic, new_node->entry); 1329 1330 otx2_tc_del_from_flow_list(flow_cfg, new_node); 1330 1331 if (new_node->is_act_police) { 1331 1332 mutex_lock(&nic->mbox.lock);