app/testpmd: fix GTP PSC extension header length
[dpdk.git] / drivers / common / cnxk / roc_npc_mcam.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4 #include "roc_api.h"
5 #include "roc_priv.h"
6
7 static int
8 npc_mcam_alloc_counter(struct npc *npc, uint16_t *ctr)
9 {
10         struct npc_mcam_alloc_counter_req *req;
11         struct npc_mcam_alloc_counter_rsp *rsp;
12         struct mbox *mbox = npc->mbox;
13         int rc = -ENOSPC;
14
15         req = mbox_alloc_msg_npc_mcam_alloc_counter(mbox);
16         if (req == NULL)
17                 return rc;
18         req->count = 1;
19         rc = mbox_process_msg(mbox, (void *)&rsp);
20         if (rc)
21                 return rc;
22         *ctr = rsp->cntr_list[0];
23         return rc;
24 }
25
26 int
27 npc_mcam_free_counter(struct npc *npc, uint16_t ctr_id)
28 {
29         struct npc_mcam_oper_counter_req *req;
30         struct mbox *mbox = npc->mbox;
31         int rc = -ENOSPC;
32
33         req = mbox_alloc_msg_npc_mcam_free_counter(mbox);
34         if (req == NULL)
35                 return rc;
36         req->cntr = ctr_id;
37         return mbox_process(mbox);
38 }
39
40 int
41 npc_mcam_read_counter(struct npc *npc, uint32_t ctr_id, uint64_t *count)
42 {
43         struct npc_mcam_oper_counter_req *req;
44         struct npc_mcam_oper_counter_rsp *rsp;
45         struct mbox *mbox = npc->mbox;
46         int rc = -ENOSPC;
47
48         req = mbox_alloc_msg_npc_mcam_counter_stats(mbox);
49         if (req == NULL)
50                 return rc;
51         req->cntr = ctr_id;
52         rc = mbox_process_msg(mbox, (void *)&rsp);
53         if (rc)
54                 return rc;
55         *count = rsp->stat;
56         return rc;
57 }
58
59 int
60 npc_mcam_clear_counter(struct npc *npc, uint32_t ctr_id)
61 {
62         struct npc_mcam_oper_counter_req *req;
63         struct mbox *mbox = npc->mbox;
64         int rc = -ENOSPC;
65
66         req = mbox_alloc_msg_npc_mcam_clear_counter(mbox);
67         if (req == NULL)
68                 return rc;
69         req->cntr = ctr_id;
70         return mbox_process(mbox);
71 }
72
73 int
74 npc_mcam_free_entry(struct npc *npc, uint32_t entry)
75 {
76         struct npc_mcam_free_entry_req *req;
77         struct mbox *mbox = npc->mbox;
78         int rc = -ENOSPC;
79
80         req = mbox_alloc_msg_npc_mcam_free_entry(mbox);
81         if (req == NULL)
82                 return rc;
83         req->entry = entry;
84         return mbox_process(mbox);
85 }
86
87 int
88 npc_mcam_free_all_entries(struct npc *npc)
89 {
90         struct npc_mcam_free_entry_req *req;
91         struct mbox *mbox = npc->mbox;
92         int rc = -ENOSPC;
93
94         req = mbox_alloc_msg_npc_mcam_free_entry(mbox);
95         if (req == NULL)
96                 return rc;
97         req->all = 1;
98         return mbox_process(mbox);
99 }
100
101 static int
102 npc_supp_key_len(uint32_t supp_mask)
103 {
104         int nib_count = 0;
105
106         while (supp_mask) {
107                 nib_count++;
108                 supp_mask &= (supp_mask - 1);
109         }
110         return nib_count * 4;
111 }
112
113 /**
114  * Returns true if any LDATA bits are extracted for specific LID+LTYPE.
115  *
116  * No LFLAG extraction is taken into account.
117  */
118 static int
119 npc_lid_lt_in_kex(struct npc *npc, uint8_t lid, uint8_t lt)
120 {
121         struct npc_xtract_info *x_info;
122         int i;
123
124         for (i = 0; i < NPC_MAX_LD; i++) {
125                 x_info = &npc->prx_dxcfg[NIX_INTF_RX][lid][lt].xtract[i];
126                 /* Check for LDATA */
127                 if (x_info->enable && x_info->len > 0)
128                         return true;
129         }
130
131         return false;
132 }
133
134 static void
135 npc_construct_ldata_mask(struct npc *npc, struct plt_bitmap *bmap, uint8_t lid,
136                          uint8_t lt, uint8_t ld)
137 {
138         struct npc_xtract_info *x_info, *infoflag;
139         int hdr_off, keylen;
140         npc_dxcfg_t *p;
141         npc_fxcfg_t *q;
142         int i, j;
143
144         p = &npc->prx_dxcfg;
145         x_info = &(*p)[0][lid][lt].xtract[ld];
146
147         if (x_info->enable == 0)
148                 return;
149
150         hdr_off = x_info->hdr_off * 8;
151         keylen = x_info->len * 8;
152         for (i = hdr_off; i < (hdr_off + keylen); i++)
153                 plt_bitmap_set(bmap, i);
154
155         if (x_info->flags_enable == 0)
156                 return;
157
158         if ((npc->prx_lfcfg[0].i & 0x7) != lid)
159                 return;
160
161         q = &npc->prx_fxcfg;
162         for (j = 0; j < NPC_MAX_LFL; j++) {
163                 infoflag = &(*q)[0][ld][j].xtract[0];
164                 if (infoflag->enable) {
165                         hdr_off = infoflag->hdr_off * 8;
166                         keylen = infoflag->len * 8;
167                         for (i = hdr_off; i < (hdr_off + keylen); i++)
168                                 plt_bitmap_set(bmap, i);
169                 }
170         }
171 }
172
173 /**
174  * Check if given LID+LTYPE combination is present in KEX
175  *
176  * len is non-zero, this function will return true if KEX extracts len bytes
177  * at given offset. Otherwise it'll return true if any bytes are extracted
178  * specifically for given LID+LTYPE combination (meaning not LFLAG based).
179  * The second case increases flexibility for custom frames whose extracted
180  * bits may change depending on KEX profile loaded.
181  *
182  * @param npc NPC context structure
183  * @param lid Layer ID to check for
184  * @param lt Layer Type to check for
185  * @param offset offset into the layer header to match
186  * @param len length of the match
187  */
188 static bool
189 npc_is_kex_enabled(struct npc *npc, uint8_t lid, uint8_t lt, int offset,
190                    int len)
191 {
192         struct plt_bitmap *bmap;
193         uint32_t bmap_sz;
194         uint8_t *mem;
195         int i;
196
197         if (!len)
198                 return npc_lid_lt_in_kex(npc, lid, lt);
199
200         bmap_sz = plt_bitmap_get_memory_footprint(300 * 8);
201         mem = plt_zmalloc(bmap_sz, 0);
202         if (mem == NULL) {
203                 plt_err("mem alloc failed");
204                 return false;
205         }
206         bmap = plt_bitmap_init(300 * 8, mem, bmap_sz);
207         if (bmap == NULL) {
208                 plt_err("mem alloc failed");
209                 plt_free(mem);
210                 return false;
211         }
212
213         npc_construct_ldata_mask(npc, bmap, lid, lt, 0);
214         npc_construct_ldata_mask(npc, bmap, lid, lt, 1);
215
216         for (i = offset; i < (offset + len); i++) {
217                 if (plt_bitmap_get(bmap, i) != 0x1) {
218                         plt_free(mem);
219                         return false;
220                 }
221         }
222
223         plt_free(mem);
224         return true;
225 }
226
227 uint64_t
228 npc_get_kex_capability(struct npc *npc)
229 {
230         npc_kex_cap_terms_t kex_cap;
231
232         memset(&kex_cap, 0, sizeof(kex_cap));
233
234         /* Ethtype: Offset 12B, len 2B */
235         kex_cap.bit.ethtype_0 = npc_is_kex_enabled(
236                 npc, NPC_LID_LA, NPC_LT_LA_ETHER, 12 * 8, 2 * 8);
237         /* QINQ VLAN Ethtype: ofset 8B, len 2B */
238         kex_cap.bit.ethtype_x = npc_is_kex_enabled(
239                 npc, NPC_LID_LB, NPC_LT_LB_STAG_QINQ, 8 * 8, 2 * 8);
240         /* VLAN ID0 : Outer VLAN: Offset 2B, len 2B */
241         kex_cap.bit.vlan_id_0 = npc_is_kex_enabled(
242                 npc, NPC_LID_LB, NPC_LT_LB_CTAG, 2 * 8, 2 * 8);
243         /* VLAN ID0 : Inner VLAN: offset 6B, len 2B */
244         kex_cap.bit.vlan_id_x = npc_is_kex_enabled(
245                 npc, NPC_LID_LB, NPC_LT_LB_STAG_QINQ, 6 * 8, 2 * 8);
246         /* DMCA: offset 0B, len 6B */
247         kex_cap.bit.dmac = npc_is_kex_enabled(npc, NPC_LID_LA, NPC_LT_LA_ETHER,
248                                               0 * 8, 6 * 8);
249         /* IP proto: offset 9B, len 1B */
250         kex_cap.bit.ip_proto =
251                 npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP, 9 * 8, 1 * 8);
252         /* UDP dport: offset 2B, len 2B */
253         kex_cap.bit.udp_dport = npc_is_kex_enabled(npc, NPC_LID_LD,
254                                                    NPC_LT_LD_UDP, 2 * 8, 2 * 8);
255         /* UDP sport: offset 0B, len 2B */
256         kex_cap.bit.udp_sport = npc_is_kex_enabled(npc, NPC_LID_LD,
257                                                    NPC_LT_LD_UDP, 0 * 8, 2 * 8);
258         /* TCP dport: offset 2B, len 2B */
259         kex_cap.bit.tcp_dport = npc_is_kex_enabled(npc, NPC_LID_LD,
260                                                    NPC_LT_LD_TCP, 2 * 8, 2 * 8);
261         /* TCP sport: offset 0B, len 2B */
262         kex_cap.bit.tcp_sport = npc_is_kex_enabled(npc, NPC_LID_LD,
263                                                    NPC_LT_LD_TCP, 0 * 8, 2 * 8);
264         /* IP SIP: offset 12B, len 4B */
265         kex_cap.bit.sip_addr = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP,
266                                                   12 * 8, 4 * 8);
267         /* IP DIP: offset 14B, len 4B */
268         kex_cap.bit.dip_addr = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP,
269                                                   14 * 8, 4 * 8);
270         /* IP6 SIP: offset 8B, len 16B */
271         kex_cap.bit.sip6_addr = npc_is_kex_enabled(
272                 npc, NPC_LID_LC, NPC_LT_LC_IP6, 8 * 8, 16 * 8);
273         /* IP6 DIP: offset 24B, len 16B */
274         kex_cap.bit.dip6_addr = npc_is_kex_enabled(
275                 npc, NPC_LID_LC, NPC_LT_LC_IP6, 24 * 8, 16 * 8);
276         /* ESP SPI: offset 0B, len 4B */
277         kex_cap.bit.ipsec_spi = npc_is_kex_enabled(npc, NPC_LID_LE,
278                                                    NPC_LT_LE_ESP, 0 * 8, 4 * 8);
279         /* VXLAN VNI: offset 4B, len 3B */
280         kex_cap.bit.ld_vni = npc_is_kex_enabled(npc, NPC_LID_LE,
281                                                 NPC_LT_LE_VXLAN, 0 * 8, 3 * 8);
282
283         /* Custom L3 frame: varied offset and lengths */
284         kex_cap.bit.custom_l3 =
285                 npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_CUSTOM0, 0, 0);
286         kex_cap.bit.custom_l3 |=
287                 npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_CUSTOM1, 0, 0);
288         /* SCTP sport : offset 0B, len 2B */
289         kex_cap.bit.sctp_sport = npc_is_kex_enabled(
290                 npc, NPC_LID_LD, NPC_LT_LD_SCTP, 0 * 8, 2 * 8);
291         /* SCTP dport : offset 2B, len 2B */
292         kex_cap.bit.sctp_dport = npc_is_kex_enabled(
293                 npc, NPC_LID_LD, NPC_LT_LD_SCTP, 2 * 8, 2 * 8);
294         /* ICMP type : offset 0B, len 1B */
295         kex_cap.bit.icmp_type = npc_is_kex_enabled(
296                 npc, NPC_LID_LD, NPC_LT_LD_ICMP, 0 * 8, 1 * 8);
297         /* ICMP code : offset 1B, len 1B */
298         kex_cap.bit.icmp_code = npc_is_kex_enabled(
299                 npc, NPC_LID_LD, NPC_LT_LD_ICMP, 1 * 8, 1 * 8);
300         /* ICMP id : offset 4B, len 2B */
301         kex_cap.bit.icmp_id = npc_is_kex_enabled(npc, NPC_LID_LD,
302                                                  NPC_LT_LD_ICMP, 4 * 8, 2 * 8);
303         /* IGMP grp_addr : offset 4B, len 4B */
304         kex_cap.bit.igmp_grp_addr = npc_is_kex_enabled(
305                 npc, NPC_LID_LD, NPC_LT_LD_IGMP, 4 * 8, 4 * 8);
306         /* GTPU teid : offset 4B, len 4B */
307         kex_cap.bit.gtpu_teid = npc_is_kex_enabled(
308                 npc, NPC_LID_LE, NPC_LT_LE_GTPU, 4 * 8, 4 * 8);
309         return kex_cap.all_bits;
310 }
311
312 #define BYTESM1_SHIFT 16
313 #define HDR_OFF_SHIFT 8
314 static void
315 npc_update_kex_info(struct npc_xtract_info *xtract_info, uint64_t val)
316 {
317         xtract_info->len = ((val >> BYTESM1_SHIFT) & 0xf) + 1;
318         xtract_info->hdr_off = (val >> HDR_OFF_SHIFT) & 0xff;
319         xtract_info->key_off = val & 0x3f;
320         xtract_info->enable = ((val >> 7) & 0x1);
321         xtract_info->flags_enable = ((val >> 6) & 0x1);
322 }
323
324 int
325 npc_mcam_alloc_entries(struct npc *npc, int ref_mcam, int *alloc_entry,
326                        int req_count, int prio, int *resp_count)
327 {
328         struct npc_mcam_alloc_entry_req *req;
329         struct npc_mcam_alloc_entry_rsp *rsp;
330         struct mbox *mbox = npc->mbox;
331         int rc = -ENOSPC;
332         int i;
333
334         req = mbox_alloc_msg_npc_mcam_alloc_entry(mbox);
335         if (req == NULL)
336                 return rc;
337         req->contig = 0;
338         req->count = req_count;
339         req->priority = prio;
340         req->ref_entry = ref_mcam;
341
342         rc = mbox_process_msg(mbox, (void *)&rsp);
343         if (rc)
344                 return rc;
345         for (i = 0; i < rsp->count; i++)
346                 alloc_entry[i] = rsp->entry_list[i];
347         *resp_count = rsp->count;
348         return 0;
349 }
350
351 int
352 npc_mcam_alloc_entry(struct npc *npc, struct roc_npc_flow *mcam,
353                      struct roc_npc_flow *ref_mcam, int prio, int *resp_count)
354 {
355         struct npc_mcam_alloc_entry_req *req;
356         struct npc_mcam_alloc_entry_rsp *rsp;
357         struct mbox *mbox = npc->mbox;
358         int rc = -ENOSPC;
359
360         req = mbox_alloc_msg_npc_mcam_alloc_entry(mbox);
361         if (req == NULL)
362                 return rc;
363         req->contig = 1;
364         req->count = 1;
365         req->priority = prio;
366         req->ref_entry = ref_mcam->mcam_id;
367
368         rc = mbox_process_msg(mbox, (void *)&rsp);
369         if (rc)
370                 return rc;
371         memset(mcam, 0, sizeof(struct roc_npc_flow));
372         mcam->mcam_id = rsp->entry;
373         mcam->nix_intf = ref_mcam->nix_intf;
374         *resp_count = rsp->count;
375         return 0;
376 }
377
378 int
379 npc_mcam_ena_dis_entry(struct npc *npc, struct roc_npc_flow *mcam, bool enable)
380 {
381         struct npc_mcam_ena_dis_entry_req *req;
382         struct mbox *mbox = npc->mbox;
383         int rc = -ENOSPC;
384
385         if (enable)
386                 req = mbox_alloc_msg_npc_mcam_ena_entry(mbox);
387         else
388                 req = mbox_alloc_msg_npc_mcam_dis_entry(mbox);
389
390         if (req == NULL)
391                 return rc;
392         req->entry = mcam->mcam_id;
393         mcam->enable = enable;
394         return mbox_process(mbox);
395 }
396
397 int
398 npc_mcam_write_entry(struct npc *npc, struct roc_npc_flow *mcam)
399 {
400         struct npc_mcam_write_entry_req *req;
401         struct mbox *mbox = npc->mbox;
402         struct mbox_msghdr *rsp;
403         int rc = -ENOSPC;
404         int i;
405
406         req = mbox_alloc_msg_npc_mcam_write_entry(mbox);
407         if (req == NULL)
408                 return rc;
409         req->entry = mcam->mcam_id;
410         req->intf = mcam->nix_intf;
411         req->enable_entry = mcam->enable;
412         req->entry_data.action = mcam->npc_action;
413         req->entry_data.vtag_action = mcam->vtag_action;
414         for (i = 0; i < NPC_MCAM_KEY_X4_WORDS; i++) {
415                 req->entry_data.kw[i] = mcam->mcam_data[i];
416                 req->entry_data.kw_mask[i] = mcam->mcam_mask[i];
417         }
418         return mbox_process_msg(mbox, (void *)&rsp);
419 }
420
421 static void
422 npc_mcam_process_mkex_cfg(struct npc *npc, struct npc_get_kex_cfg_rsp *kex_rsp)
423 {
424         volatile uint64_t(
425                 *q)[NPC_MAX_INTF][NPC_MAX_LID][NPC_MAX_LT][NPC_MAX_LD];
426         struct npc_xtract_info *x_info = NULL;
427         int lid, lt, ld, fl, ix;
428         npc_dxcfg_t *p;
429         uint64_t keyw;
430         uint64_t val;
431
432         npc->keyx_supp_nmask[NPC_MCAM_RX] =
433                 kex_rsp->rx_keyx_cfg & 0x7fffffffULL;
434         npc->keyx_supp_nmask[NPC_MCAM_TX] =
435                 kex_rsp->tx_keyx_cfg & 0x7fffffffULL;
436         npc->keyx_len[NPC_MCAM_RX] =
437                 npc_supp_key_len(npc->keyx_supp_nmask[NPC_MCAM_RX]);
438         npc->keyx_len[NPC_MCAM_TX] =
439                 npc_supp_key_len(npc->keyx_supp_nmask[NPC_MCAM_TX]);
440
441         keyw = (kex_rsp->rx_keyx_cfg >> 32) & 0x7ULL;
442         npc->keyw[NPC_MCAM_RX] = keyw;
443         keyw = (kex_rsp->tx_keyx_cfg >> 32) & 0x7ULL;
444         npc->keyw[NPC_MCAM_TX] = keyw;
445
446         /* Update KEX_LD_FLAG */
447         for (ix = 0; ix < NPC_MAX_INTF; ix++) {
448                 for (ld = 0; ld < NPC_MAX_LD; ld++) {
449                         for (fl = 0; fl < NPC_MAX_LFL; fl++) {
450                                 x_info = &npc->prx_fxcfg[ix][ld][fl].xtract[0];
451                                 val = kex_rsp->intf_ld_flags[ix][ld][fl];
452                                 npc_update_kex_info(x_info, val);
453                         }
454                 }
455         }
456
457         /* Update LID, LT and LDATA cfg */
458         p = &npc->prx_dxcfg;
459         q = (volatile uint64_t(*)[][NPC_MAX_LID][NPC_MAX_LT][NPC_MAX_LD])(
460                 &kex_rsp->intf_lid_lt_ld);
461         for (ix = 0; ix < NPC_MAX_INTF; ix++) {
462                 for (lid = 0; lid < NPC_MAX_LID; lid++) {
463                         for (lt = 0; lt < NPC_MAX_LT; lt++) {
464                                 for (ld = 0; ld < NPC_MAX_LD; ld++) {
465                                         x_info = &(*p)[ix][lid][lt].xtract[ld];
466                                         val = (*q)[ix][lid][lt][ld];
467                                         npc_update_kex_info(x_info, val);
468                                 }
469                         }
470                 }
471         }
472         /* Update LDATA Flags cfg */
473         npc->prx_lfcfg[0].i = kex_rsp->kex_ld_flags[0];
474         npc->prx_lfcfg[1].i = kex_rsp->kex_ld_flags[1];
475 }
476
477 int
478 npc_mcam_fetch_kex_cfg(struct npc *npc)
479 {
480         struct npc_get_kex_cfg_rsp *kex_rsp;
481         struct mbox *mbox = npc->mbox;
482         int rc = 0;
483
484         mbox_alloc_msg_npc_get_kex_cfg(mbox);
485         rc = mbox_process_msg(mbox, (void *)&kex_rsp);
486         if (rc) {
487                 plt_err("Failed to fetch NPC KEX config");
488                 goto done;
489         }
490
491         mbox_memcpy((char *)npc->profile_name, kex_rsp->mkex_pfl_name,
492                     MKEX_NAME_LEN);
493
494         npc_mcam_process_mkex_cfg(npc, kex_rsp);
495
496 done:
497         return rc;
498 }
499
500 int
501 npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow,
502                          struct npc_parse_state *pst)
503 {
504         int use_ctr = (flow->ctr_id == NPC_COUNTER_NONE ? 0 : 1);
505         struct npc_mcam_write_entry_req *req;
506         struct nix_inl_dev *inl_dev = NULL;
507         struct mbox *mbox = npc->mbox;
508         struct mbox_msghdr *rsp;
509         struct idev_cfg *idev;
510         uint16_t pf_func = 0;
511         uint16_t ctr = ~(0);
512         int rc, idx;
513         int entry;
514
515         PLT_SET_USED(pst);
516
517         if (use_ctr) {
518                 rc = npc_mcam_alloc_counter(npc, &ctr);
519                 if (rc)
520                         return rc;
521         }
522
523         entry = npc_get_free_mcam_entry(mbox, flow, npc);
524         if (entry < 0) {
525                 if (use_ctr)
526                         npc_mcam_free_counter(npc, ctr);
527                 return NPC_ERR_MCAM_ALLOC;
528         }
529
530         req = mbox_alloc_msg_npc_mcam_write_entry(mbox);
531         if (req == NULL)
532                 return -ENOSPC;
533         req->set_cntr = use_ctr;
534         req->cntr = ctr;
535         req->entry = entry;
536
537         req->intf = (flow->nix_intf == NIX_INTF_RX) ? NPC_MCAM_RX : NPC_MCAM_TX;
538         req->enable_entry = 1;
539         req->entry_data.action = flow->npc_action;
540
541         /*
542          * Driver sets vtag action on per interface basis, not
543          * per flow basis. It is a matter of how we decide to support
544          * this pmd specific behavior. There are two ways:
545          *      1. Inherit the vtag action from the one configured
546          *         for this interface. This can be read from the
547          *         vtag_action configured for default mcam entry of
548          *         this pf_func.
549          *      2. Do not support vtag action with npc_flow.
550          *
551          * Second approach is used now.
552          */
553         req->entry_data.vtag_action = flow->vtag_action;
554
555         for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
556                 req->entry_data.kw[idx] = flow->mcam_data[idx];
557                 req->entry_data.kw_mask[idx] = flow->mcam_mask[idx];
558         }
559
560         idev = idev_get_cfg();
561         if (idev)
562                 inl_dev = idev->nix_inl_dev;
563
564         if (flow->nix_intf == NIX_INTF_RX) {
565                 if (inl_dev && inl_dev->is_multi_channel &&
566                     (flow->npc_action & NIX_RX_ACTIONOP_UCAST_IPSEC)) {
567                         req->entry_data.kw[0] |= (uint64_t)inl_dev->channel;
568                         req->entry_data.kw_mask[0] |=
569                                 (uint64_t)inl_dev->chan_mask;
570                         pf_func = nix_inl_dev_pffunc_get();
571                         req->entry_data.action &= ~(GENMASK(19, 4));
572                         req->entry_data.action |= (uint64_t)pf_func << 4;
573
574                         flow->npc_action &= ~(GENMASK(19, 4));
575                         flow->npc_action |= (uint64_t)pf_func << 4;
576                         flow->mcam_data[0] |= (uint64_t)inl_dev->channel;
577                         flow->mcam_mask[0] |= (uint64_t)inl_dev->chan_mask;
578                 } else {
579                         req->entry_data.kw[0] |= (uint64_t)npc->channel;
580                         req->entry_data.kw_mask[0] |= (BIT_ULL(12) - 1);
581                         flow->mcam_data[0] |= (uint64_t)npc->channel;
582                         flow->mcam_mask[0] |= (BIT_ULL(12) - 1);
583                 }
584         } else {
585                 uint16_t pf_func = (flow->npc_action >> 4) & 0xffff;
586
587                 pf_func = plt_cpu_to_be_16(pf_func);
588                 req->entry_data.kw[0] |= ((uint64_t)pf_func << 32);
589                 req->entry_data.kw_mask[0] |= ((uint64_t)0xffff << 32);
590
591                 flow->mcam_data[0] |= ((uint64_t)pf_func << 32);
592                 flow->mcam_mask[0] |= ((uint64_t)0xffff << 32);
593         }
594
595         rc = mbox_process_msg(mbox, (void *)&rsp);
596         if (rc != 0)
597                 return rc;
598
599         flow->mcam_id = entry;
600
601         if (use_ctr)
602                 flow->ctr_id = ctr;
603         return 0;
604 }
605
606 int
607 npc_program_mcam(struct npc *npc, struct npc_parse_state *pst, bool mcam_alloc)
608 {
609         struct npc_mcam_read_base_rule_rsp *base_rule_rsp;
610         /* This is non-LDATA part in search key */
611         uint64_t key_data[2] = {0ULL, 0ULL};
612         uint64_t key_mask[2] = {0ULL, 0ULL};
613         int key_len, bit = 0, index, rc = 0;
614         int intf = pst->flow->nix_intf;
615         struct mcam_entry *base_entry;
616         int off, idx, data_off = 0;
617         uint8_t lid, mask, data;
618         uint16_t layer_info;
619         uint64_t lt, flags;
620
621         /* Skip till Layer A data start */
622         while (bit < NPC_PARSE_KEX_S_LA_OFFSET) {
623                 if (npc->keyx_supp_nmask[intf] & (1 << bit))
624                         data_off++;
625                 bit++;
626         }
627
628         /* Each bit represents 1 nibble */
629         data_off *= 4;
630
631         index = 0;
632         for (lid = 0; lid < NPC_MAX_LID; lid++) {
633                 /* Offset in key */
634                 off = NPC_PARSE_KEX_S_LID_OFFSET(lid);
635                 lt = pst->lt[lid] & 0xf;
636                 flags = pst->flags[lid] & 0xff;
637
638                 /* NPC_LAYER_KEX_S */
639                 layer_info = ((npc->keyx_supp_nmask[intf] >> off) & 0x7);
640
641                 if (layer_info) {
642                         for (idx = 0; idx <= 2; idx++) {
643                                 if (layer_info & (1 << idx)) {
644                                         if (idx == 2)
645                                                 data = lt;
646                                         else if (idx == 1)
647                                                 data = ((flags >> 4) & 0xf);
648                                         else
649                                                 data = (flags & 0xf);
650
651                                         if (data_off >= 64) {
652                                                 data_off = 0;
653                                                 index++;
654                                         }
655                                         key_data[index] |=
656                                                 ((uint64_t)data << data_off);
657                                         mask = 0xf;
658                                         if (lt == 0)
659                                                 mask = 0;
660                                         key_mask[index] |=
661                                                 ((uint64_t)mask << data_off);
662                                         data_off += 4;
663                                 }
664                         }
665                 }
666         }
667
668         /* Copy this into mcam string */
669         key_len = (pst->npc->keyx_len[intf] + 7) / 8;
670         memcpy(pst->flow->mcam_data, key_data, key_len);
671         memcpy(pst->flow->mcam_mask, key_mask, key_len);
672
673         if (pst->is_vf) {
674                 (void)mbox_alloc_msg_npc_read_base_steer_rule(npc->mbox);
675                 rc = mbox_process_msg(npc->mbox, (void *)&base_rule_rsp);
676                 if (rc) {
677                         plt_err("Failed to fetch VF's base MCAM entry");
678                         return rc;
679                 }
680                 base_entry = &base_rule_rsp->entry_data;
681                 for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
682                         pst->flow->mcam_data[idx] |= base_entry->kw[idx];
683                         pst->flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
684                 }
685         }
686
687         /*
688          * Now we have mcam data and mask formatted as
689          * [Key_len/4 nibbles][0 or 1 nibble hole][data]
690          * hole is present if key_len is odd number of nibbles.
691          * mcam data must be split into 64 bits + 48 bits segments
692          * for each back W0, W1.
693          */
694
695         if (mcam_alloc)
696                 return npc_mcam_alloc_and_write(npc, pst->flow, pst);
697         else
698                 return 0;
699 }
700
701 int
702 npc_flow_free_all_resources(struct npc *npc)
703 {
704         struct roc_npc_flow *flow;
705         int rc, idx;
706
707         /* Free all MCAM entries allocated */
708         rc = npc_mcam_free_all_entries(npc);
709
710         /* Free any MCAM counters and delete flow list */
711         for (idx = 0; idx < npc->flow_max_priority; idx++) {
712                 while ((flow = TAILQ_FIRST(&npc->flow_list[idx])) != NULL) {
713                         npc_rss_group_free(npc, flow);
714                         if (flow->ctr_id != NPC_COUNTER_NONE)
715                                 rc |= npc_mcam_free_counter(npc, flow->ctr_id);
716
717                         npc_delete_prio_list_entry(npc, flow);
718
719                         TAILQ_REMOVE(&npc->flow_list[idx], flow, next);
720                         plt_free(flow);
721                 }
722         }
723         return rc;
724 }