1
2
3
4#include "roc_api.h"
5#include "roc_priv.h"
6
7static int
8npc_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
26int
27npc_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
40int
41npc_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
59int
60npc_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
73int
74npc_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
87int
88npc_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
101static int
102npc_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
115
116
117
118static int
119npc_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
127 if (x_info->enable && x_info->len > 0)
128 return true;
129 }
130
131 return false;
132}
133
134static void
135npc_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
175
176
177
178
179
180
181
182
183
184
185
186
187
188static bool
189npc_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
227uint64_t
228npc_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
235 kex_cap.bit.ethtype_0 = npc_is_kex_enabled(
236 npc, NPC_LID_LA, NPC_LT_LA_ETHER, 12 * 8, 2 * 8);
237
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
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
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
247 kex_cap.bit.dmac = npc_is_kex_enabled(npc, NPC_LID_LA, NPC_LT_LA_ETHER,
248 0 * 8, 6 * 8);
249
250 kex_cap.bit.ip_proto =
251 npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP, 9 * 8, 1 * 8);
252
253 kex_cap.bit.udp_dport = npc_is_kex_enabled(npc, NPC_LID_LD,
254 NPC_LT_LD_UDP, 2 * 8, 2 * 8);
255
256 kex_cap.bit.udp_sport = npc_is_kex_enabled(npc, NPC_LID_LD,
257 NPC_LT_LD_UDP, 0 * 8, 2 * 8);
258
259 kex_cap.bit.tcp_dport = npc_is_kex_enabled(npc, NPC_LID_LD,
260 NPC_LT_LD_TCP, 2 * 8, 2 * 8);
261
262 kex_cap.bit.tcp_sport = npc_is_kex_enabled(npc, NPC_LID_LD,
263 NPC_LT_LD_TCP, 0 * 8, 2 * 8);
264
265 kex_cap.bit.sip_addr = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP,
266 12 * 8, 4 * 8);
267
268 kex_cap.bit.dip_addr = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP,
269 14 * 8, 4 * 8);
270
271 kex_cap.bit.sip6_addr = npc_is_kex_enabled(
272 npc, NPC_LID_LC, NPC_LT_LC_IP6, 8 * 8, 16 * 8);
273
274 kex_cap.bit.dip6_addr = npc_is_kex_enabled(
275 npc, NPC_LID_LC, NPC_LT_LC_IP6, 24 * 8, 16 * 8);
276
277 kex_cap.bit.ipsec_spi = npc_is_kex_enabled(npc, NPC_LID_LE,
278 NPC_LT_LE_ESP, 0 * 8, 4 * 8);
279
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
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
289 kex_cap.bit.sctp_sport = npc_is_kex_enabled(
290 npc, NPC_LID_LD, NPC_LT_LD_SCTP, 0 * 8, 2 * 8);
291
292 kex_cap.bit.sctp_dport = npc_is_kex_enabled(
293 npc, NPC_LID_LD, NPC_LT_LD_SCTP, 2 * 8, 2 * 8);
294
295 kex_cap.bit.icmp_type = npc_is_kex_enabled(
296 npc, NPC_LID_LD, NPC_LT_LD_ICMP, 0 * 8, 1 * 8);
297
298 kex_cap.bit.icmp_code = npc_is_kex_enabled(
299 npc, NPC_LID_LD, NPC_LT_LD_ICMP, 1 * 8, 1 * 8);
300
301 kex_cap.bit.icmp_id = npc_is_kex_enabled(npc, NPC_LID_LD,
302 NPC_LT_LD_ICMP, 4 * 8, 2 * 8);
303
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
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
314static void
315npc_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
324int
325npc_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
351int
352npc_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
378int
379npc_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
397int
398npc_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
421static void
422npc_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
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
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
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
477int
478npc_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
496done:
497 return rc;
498}
499
500int
501npc_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 mbox *mbox = npc->mbox;
507 struct mbox_msghdr *rsp;
508 uint16_t ctr = ~(0);
509 int rc, idx;
510 int entry;
511
512 PLT_SET_USED(pst);
513
514 if (use_ctr) {
515 rc = npc_mcam_alloc_counter(npc, &ctr);
516 if (rc)
517 return rc;
518 }
519
520 entry = npc_check_preallocated_entry_cache(mbox, flow, npc);
521 if (entry < 0) {
522 npc_mcam_free_counter(npc, ctr);
523 return NPC_ERR_MCAM_ALLOC;
524 }
525
526 req = mbox_alloc_msg_npc_mcam_write_entry(mbox);
527 if (req == NULL)
528 return -ENOSPC;
529 req->set_cntr = use_ctr;
530 req->cntr = ctr;
531 req->entry = entry;
532
533 req->intf = (flow->nix_intf == NIX_INTF_RX) ? NPC_MCAM_RX : NPC_MCAM_TX;
534 req->enable_entry = 1;
535 req->entry_data.action = flow->npc_action;
536
537
538
539
540
541
542
543
544
545
546
547
548
549 req->entry_data.vtag_action = 0ULL;
550
551 for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
552 req->entry_data.kw[idx] = flow->mcam_data[idx];
553 req->entry_data.kw_mask[idx] = flow->mcam_mask[idx];
554 }
555
556 if (flow->nix_intf == NIX_INTF_RX) {
557 req->entry_data.kw[0] |= (uint64_t)npc->channel;
558 req->entry_data.kw_mask[0] |= (BIT_ULL(12) - 1);
559 } else {
560 uint16_t pf_func = (flow->npc_action >> 4) & 0xffff;
561
562 pf_func = plt_cpu_to_be_16(pf_func);
563 req->entry_data.kw[0] |= ((uint64_t)pf_func << 32);
564 req->entry_data.kw_mask[0] |= ((uint64_t)0xffff << 32);
565 }
566
567 rc = mbox_process_msg(mbox, (void *)&rsp);
568 if (rc != 0)
569 return rc;
570
571 flow->mcam_id = entry;
572 if (use_ctr)
573 flow->ctr_id = ctr;
574 return 0;
575}
576
577int
578npc_program_mcam(struct npc *npc, struct npc_parse_state *pst, bool mcam_alloc)
579{
580 struct npc_mcam_read_base_rule_rsp *base_rule_rsp;
581
582 uint64_t key_data[2] = {0ULL, 0ULL};
583 uint64_t key_mask[2] = {0ULL, 0ULL};
584 int key_len, bit = 0, index, rc = 0;
585 int intf = pst->flow->nix_intf;
586 struct mcam_entry *base_entry;
587 int off, idx, data_off = 0;
588 uint8_t lid, mask, data;
589 uint16_t layer_info;
590 uint64_t lt, flags;
591
592
593 while (bit < NPC_PARSE_KEX_S_LA_OFFSET) {
594 if (npc->keyx_supp_nmask[intf] & (1 << bit))
595 data_off++;
596 bit++;
597 }
598
599
600 data_off *= 4;
601
602 index = 0;
603 for (lid = 0; lid < NPC_MAX_LID; lid++) {
604
605 off = NPC_PARSE_KEX_S_LID_OFFSET(lid);
606 lt = pst->lt[lid] & 0xf;
607 flags = pst->flags[lid] & 0xff;
608
609
610 layer_info = ((npc->keyx_supp_nmask[intf] >> off) & 0x7);
611
612 if (layer_info) {
613 for (idx = 0; idx <= 2; idx++) {
614 if (layer_info & (1 << idx)) {
615 if (idx == 2)
616 data = lt;
617 else if (idx == 1)
618 data = ((flags >> 4) & 0xf);
619 else
620 data = (flags & 0xf);
621
622 if (data_off >= 64) {
623 data_off = 0;
624 index++;
625 }
626 key_data[index] |=
627 ((uint64_t)data << data_off);
628 mask = 0xf;
629 if (lt == 0)
630 mask = 0;
631 key_mask[index] |=
632 ((uint64_t)mask << data_off);
633 data_off += 4;
634 }
635 }
636 }
637 }
638
639
640 key_len = (pst->npc->keyx_len[intf] + 7) / 8;
641 memcpy(pst->flow->mcam_data, key_data, key_len);
642 memcpy(pst->flow->mcam_mask, key_mask, key_len);
643
644 if (pst->is_vf) {
645 (void)mbox_alloc_msg_npc_read_base_steer_rule(npc->mbox);
646 rc = mbox_process_msg(npc->mbox, (void *)&base_rule_rsp);
647 if (rc) {
648 plt_err("Failed to fetch VF's base MCAM entry");
649 return rc;
650 }
651 base_entry = &base_rule_rsp->entry_data;
652 for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
653 pst->flow->mcam_data[idx] |= base_entry->kw[idx];
654 pst->flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
655 }
656 }
657
658
659
660
661
662
663
664
665
666 if (mcam_alloc)
667 return npc_mcam_alloc_and_write(npc, pst->flow, pst);
668 else
669 return 0;
670}
671
672int
673npc_flow_free_all_resources(struct npc *npc)
674{
675 struct npc_mcam_ents_info *info;
676 struct roc_npc_flow *flow;
677 struct plt_bitmap *bmap;
678 int entry_count = 0;
679 int rc, idx;
680
681 for (idx = 0; idx < npc->flow_max_priority; idx++) {
682 info = &npc->flow_entry_info[idx];
683 entry_count += info->live_ent;
684 }
685
686 if (entry_count == 0)
687 return 0;
688
689
690 rc = npc_mcam_free_all_entries(npc);
691
692
693 for (idx = 0; idx < npc->flow_max_priority; idx++) {
694 while ((flow = TAILQ_FIRST(&npc->flow_list[idx])) != NULL) {
695 npc_rss_group_free(npc, flow);
696 if (flow->ctr_id != NPC_COUNTER_NONE)
697 rc |= npc_mcam_free_counter(npc, flow->ctr_id);
698
699 TAILQ_REMOVE(&npc->flow_list[idx], flow, next);
700 plt_free(flow);
701 bmap = npc->live_entries[flow->priority];
702 plt_bitmap_clear(bmap, flow->mcam_id);
703 }
704 info = &npc->flow_entry_info[idx];
705 info->free_ent = 0;
706 info->live_ent = 0;
707 }
708 return rc;
709}
710