net/mlx5: fix TCP flags size for modify actions
[dpdk.git] / drivers / net / octeontx2 / otx2_flow_utils.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2019 Marvell International Ltd.
3  */
4
5 #include "otx2_ethdev.h"
6 #include "otx2_flow.h"
7
8 static int
9 flow_mcam_alloc_counter(struct otx2_mbox *mbox, uint16_t *ctr)
10 {
11         struct npc_mcam_alloc_counter_req *req;
12         struct npc_mcam_alloc_counter_rsp *rsp;
13         int rc;
14
15         req = otx2_mbox_alloc_msg_npc_mcam_alloc_counter(mbox);
16         req->count = 1;
17         otx2_mbox_msg_send(mbox, 0);
18         rc = otx2_mbox_get_rsp(mbox, 0, (void *)&rsp);
19
20         *ctr = rsp->cntr_list[0];
21         return rc;
22 }
23
24 int
25 otx2_flow_mcam_free_counter(struct otx2_mbox *mbox, uint16_t ctr_id)
26 {
27         struct npc_mcam_oper_counter_req *req;
28         int rc;
29
30         req = otx2_mbox_alloc_msg_npc_mcam_free_counter(mbox);
31         req->cntr = ctr_id;
32         otx2_mbox_msg_send(mbox, 0);
33         rc = otx2_mbox_get_rsp(mbox, 0, NULL);
34
35         return rc;
36 }
37
38 int
39 otx2_flow_mcam_read_counter(struct otx2_mbox *mbox, uint32_t ctr_id,
40                             uint64_t *count)
41 {
42         struct npc_mcam_oper_counter_req *req;
43         struct npc_mcam_oper_counter_rsp *rsp;
44         int rc;
45
46         req = otx2_mbox_alloc_msg_npc_mcam_counter_stats(mbox);
47         req->cntr = ctr_id;
48         otx2_mbox_msg_send(mbox, 0);
49         rc = otx2_mbox_get_rsp(mbox, 0, (void *)&rsp);
50
51         *count = rsp->stat;
52         return rc;
53 }
54
55 int
56 otx2_flow_mcam_clear_counter(struct otx2_mbox *mbox, uint32_t ctr_id)
57 {
58         struct npc_mcam_oper_counter_req *req;
59         int rc;
60
61         req = otx2_mbox_alloc_msg_npc_mcam_clear_counter(mbox);
62         req->cntr = ctr_id;
63         otx2_mbox_msg_send(mbox, 0);
64         rc = otx2_mbox_get_rsp(mbox, 0, NULL);
65
66         return rc;
67 }
68
69 int
70 otx2_flow_mcam_free_entry(struct otx2_mbox *mbox, uint32_t entry)
71 {
72         struct npc_mcam_free_entry_req *req;
73         int rc;
74
75         req = otx2_mbox_alloc_msg_npc_mcam_free_entry(mbox);
76         req->entry = entry;
77         otx2_mbox_msg_send(mbox, 0);
78         rc = otx2_mbox_get_rsp(mbox, 0, NULL);
79
80         return rc;
81 }
82
83 int
84 otx2_flow_mcam_free_all_entries(struct otx2_mbox *mbox)
85 {
86         struct npc_mcam_free_entry_req *req;
87         int rc;
88
89         req = otx2_mbox_alloc_msg_npc_mcam_free_entry(mbox);
90         req->all = 1;
91         otx2_mbox_msg_send(mbox, 0);
92         rc = otx2_mbox_get_rsp(mbox, 0, NULL);
93
94         return rc;
95 }
96
97 static void
98 flow_prep_mcam_ldata(uint8_t *ptr, const uint8_t *data, int len)
99 {
100         int idx;
101
102         for (idx = 0; idx < len; idx++)
103                 ptr[idx] = data[len - 1 - idx];
104 }
105
106 static int
107 flow_check_copysz(size_t size, size_t len)
108 {
109         if (len <= size)
110                 return len;
111         return -1;
112 }
113
114 static inline int
115 flow_mem_is_zero(const void *mem, int len)
116 {
117         const char *m = mem;
118         int i;
119
120         for (i = 0; i < len; i++) {
121                 if (m[i] != 0)
122                         return 0;
123         }
124         return 1;
125 }
126
127 static void
128 flow_set_hw_mask(struct otx2_flow_item_info *info,
129                  struct npc_xtract_info *xinfo,
130                  char *hw_mask)
131 {
132         int max_off, offset;
133         int j;
134
135         if (xinfo->enable == 0)
136                 return;
137
138         if (xinfo->hdr_off < info->hw_hdr_len)
139                 return;
140
141         max_off = xinfo->hdr_off + xinfo->len - info->hw_hdr_len;
142
143         if (max_off > info->len)
144                 max_off = info->len;
145
146         offset = xinfo->hdr_off - info->hw_hdr_len;
147         for (j = offset; j < max_off; j++)
148                 hw_mask[j] = 0xff;
149 }
150
151 void
152 otx2_flow_get_hw_supp_mask(struct otx2_parse_state *pst,
153                            struct otx2_flow_item_info *info, int lid, int lt)
154 {
155         struct npc_xtract_info *xinfo, *lfinfo;
156         char *hw_mask = info->hw_mask;
157         int lf_cfg;
158         int i, j;
159         int intf;
160
161         intf = pst->flow->nix_intf;
162         xinfo = pst->npc->prx_dxcfg[intf][lid][lt].xtract;
163         memset(hw_mask, 0, info->len);
164
165         for (i = 0; i < NPC_MAX_LD; i++) {
166                 flow_set_hw_mask(info, &xinfo[i], hw_mask);
167         }
168
169         for (i = 0; i < NPC_MAX_LD; i++) {
170
171                 if (xinfo[i].flags_enable == 0)
172                         continue;
173
174                 lf_cfg = pst->npc->prx_lfcfg[i].i;
175                 if (lf_cfg == lid) {
176                         for (j = 0; j < NPC_MAX_LFL; j++) {
177                                 lfinfo = pst->npc->prx_fxcfg[intf]
178                                         [i][j].xtract;
179                                 flow_set_hw_mask(info, &lfinfo[0], hw_mask);
180                         }
181                 }
182         }
183 }
184
185 static int
186 flow_update_extraction_data(struct otx2_parse_state *pst,
187                             struct otx2_flow_item_info *info,
188                             struct npc_xtract_info *xinfo)
189 {
190         uint8_t int_info_mask[NPC_MAX_EXTRACT_DATA_LEN];
191         uint8_t int_info[NPC_MAX_EXTRACT_DATA_LEN];
192         struct npc_xtract_info *x;
193         int k, idx, hdr_off;
194         int len = 0;
195
196         x = xinfo;
197         len = x->len;
198         hdr_off = x->hdr_off;
199
200         if (hdr_off < info->hw_hdr_len)
201                 return 0;
202
203         if (x->enable == 0)
204                 return 0;
205
206         otx2_npc_dbg("x->hdr_off = %d, len = %d, info->len = %d,"
207                      "x->key_off = %d", x->hdr_off, len, info->len,
208                      x->key_off);
209
210         hdr_off -= info->hw_hdr_len;
211
212         if (hdr_off + len > info->len)
213                 len = info->len - hdr_off;
214
215         /* Check for over-write of previous layer */
216         if (!flow_mem_is_zero(pst->mcam_mask + x->key_off,
217                               len)) {
218                 /* Cannot support this data match */
219                 rte_flow_error_set(pst->error, ENOTSUP,
220                                    RTE_FLOW_ERROR_TYPE_ITEM,
221                                    pst->pattern,
222                                    "Extraction unsupported");
223                 return -rte_errno;
224         }
225
226         len = flow_check_copysz((OTX2_MAX_MCAM_WIDTH_DWORDS * 8)
227                                 - x->key_off,
228                                 len);
229         if (len < 0) {
230                 rte_flow_error_set(pst->error, ENOTSUP,
231                                    RTE_FLOW_ERROR_TYPE_ITEM,
232                                    pst->pattern,
233                                    "Internal Error");
234                 return -rte_errno;
235         }
236
237         /* Need to reverse complete structure so that dest addr is at
238          * MSB so as to program the MCAM using mcam_data & mcam_mask
239          * arrays
240          */
241         flow_prep_mcam_ldata(int_info,
242                              (const uint8_t *)info->spec + hdr_off,
243                              x->len);
244         flow_prep_mcam_ldata(int_info_mask,
245                              (const uint8_t *)info->mask + hdr_off,
246                              x->len);
247
248         otx2_npc_dbg("Spec: ");
249         for (k = 0; k < info->len; k++)
250                 otx2_npc_dbg("0x%.2x ",
251                              ((const uint8_t *)info->spec)[k]);
252
253         otx2_npc_dbg("Int_info: ");
254         for (k = 0; k < info->len; k++)
255                 otx2_npc_dbg("0x%.2x ", int_info[k]);
256
257         memcpy(pst->mcam_mask + x->key_off, int_info_mask, len);
258         memcpy(pst->mcam_data + x->key_off, int_info, len);
259
260         otx2_npc_dbg("Parse state mcam data & mask");
261         for (idx = 0; idx < len ; idx++)
262                 otx2_npc_dbg("data[%d]: 0x%x, mask[%d]: 0x%x", idx,
263                              *(pst->mcam_data + idx + x->key_off), idx,
264                              *(pst->mcam_mask + idx + x->key_off));
265         return 0;
266 }
267
268 int
269 otx2_flow_update_parse_state(struct otx2_parse_state *pst,
270                              struct otx2_flow_item_info *info, int lid, int lt,
271                              uint8_t flags)
272 {
273         struct npc_lid_lt_xtract_info *xinfo;
274         struct otx2_flow_dump_data *dump;
275         struct npc_xtract_info *lfinfo;
276         int intf, lf_cfg;
277         int i, j, rc = 0;
278
279         otx2_npc_dbg("Parse state function info mask total %s",
280                      (const uint8_t *)info->mask);
281
282         pst->layer_mask |= lid;
283         pst->lt[lid] = lt;
284         pst->flags[lid] = flags;
285
286         intf = pst->flow->nix_intf;
287         xinfo = &pst->npc->prx_dxcfg[intf][lid][lt];
288         otx2_npc_dbg("Is_terminating = %d", xinfo->is_terminating);
289         if (xinfo->is_terminating)
290                 pst->terminate = 1;
291
292         if (info->spec == NULL) {
293                 otx2_npc_dbg("Info spec NULL");
294                 goto done;
295         }
296
297         for (i = 0; i < NPC_MAX_LD; i++) {
298                 rc = flow_update_extraction_data(pst, info, &xinfo->xtract[i]);
299                 if (rc != 0)
300                         return rc;
301         }
302
303         for (i = 0; i < NPC_MAX_LD; i++) {
304                 if (xinfo->xtract[i].flags_enable == 0)
305                         continue;
306
307                 lf_cfg = pst->npc->prx_lfcfg[i].i;
308                 if (lf_cfg == lid) {
309                         for (j = 0; j < NPC_MAX_LFL; j++) {
310                                 lfinfo = pst->npc->prx_fxcfg[intf]
311                                         [i][j].xtract;
312                                 rc = flow_update_extraction_data(pst, info,
313                                                                  &lfinfo[0]);
314                                 if (rc != 0)
315                                         return rc;
316
317                                 if (lfinfo[0].enable)
318                                         pst->flags[lid] = j;
319                         }
320                 }
321         }
322
323 done:
324         dump = &pst->flow->dump_data[pst->flow->num_patterns++];
325         dump->lid = lid;
326         dump->ltype = lt;
327         /* Next pattern to parse by subsequent layers */
328         pst->pattern++;
329         return 0;
330 }
331
332 static inline int
333 flow_range_is_valid(const char *spec, const char *last, const char *mask,
334                     int len)
335 {
336         /* Mask must be zero or equal to spec as we do not support
337          * non-contiguous ranges.
338          */
339         while (len--) {
340                 if (last[len] &&
341                     (spec[len] & mask[len]) != (last[len] & mask[len]))
342                         return 0; /* False */
343         }
344         return 1;
345 }
346
347
348 static inline int
349 flow_mask_is_supported(const char *mask, const char *hw_mask, int len)
350 {
351         /*
352          * If no hw_mask, assume nothing is supported.
353          * mask is never NULL
354          */
355         if (hw_mask == NULL)
356                 return flow_mem_is_zero(mask, len);
357
358         while (len--) {
359                 if ((mask[len] | hw_mask[len]) != hw_mask[len])
360                         return 0; /* False */
361         }
362         return 1;
363 }
364
365 int
366 otx2_flow_parse_item_basic(const struct rte_flow_item *item,
367                            struct otx2_flow_item_info *info,
368                            struct rte_flow_error *error)
369 {
370         /* Item must not be NULL */
371         if (item == NULL) {
372                 rte_flow_error_set(error, EINVAL,
373                                    RTE_FLOW_ERROR_TYPE_ITEM, NULL,
374                                    "Item is NULL");
375                 return -rte_errno;
376         }
377         /* If spec is NULL, both mask and last must be NULL, this
378          * makes it to match ANY value (eq to mask = 0).
379          * Setting either mask or last without spec is an error
380          */
381         if (item->spec == NULL) {
382                 if (item->last == NULL && item->mask == NULL) {
383                         info->spec = NULL;
384                         return 0;
385                 }
386                 rte_flow_error_set(error, EINVAL,
387                                    RTE_FLOW_ERROR_TYPE_ITEM, item,
388                                    "mask or last set without spec");
389                 return -rte_errno;
390         }
391
392         /* We have valid spec */
393         if (item->type != RTE_FLOW_ITEM_TYPE_RAW)
394                 info->spec = item->spec;
395
396         /* If mask is not set, use default mask, err if default mask is
397          * also NULL.
398          */
399         if (item->mask == NULL) {
400                 otx2_npc_dbg("Item mask null, using default mask");
401                 if (info->def_mask == NULL) {
402                         rte_flow_error_set(error, EINVAL,
403                                            RTE_FLOW_ERROR_TYPE_ITEM, item,
404                                            "No mask or default mask given");
405                         return -rte_errno;
406                 }
407                 info->mask = info->def_mask;
408         } else {
409                 if (item->type != RTE_FLOW_ITEM_TYPE_RAW)
410                         info->mask = item->mask;
411         }
412
413         /* mask specified must be subset of hw supported mask
414          * mask | hw_mask == hw_mask
415          */
416         if (!flow_mask_is_supported(info->mask, info->hw_mask, info->len)) {
417                 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,
418                                    item, "Unsupported field in the mask");
419                 return -rte_errno;
420         }
421
422         /* Now we have spec and mask. OTX2 does not support non-contiguous
423          * range. We should have either:
424          * - spec & mask == last & mask or,
425          * - last == 0 or,
426          * - last == NULL
427          */
428         if (item->last != NULL && !flow_mem_is_zero(item->last, info->len)) {
429                 if (!flow_range_is_valid(item->spec, item->last, info->mask,
430                                          info->len)) {
431                         rte_flow_error_set(error, EINVAL,
432                                            RTE_FLOW_ERROR_TYPE_ITEM, item,
433                                            "Unsupported range for match");
434                         return -rte_errno;
435                 }
436         }
437
438         return 0;
439 }
440
441 void
442 otx2_flow_keyx_compress(uint64_t *data, uint32_t nibble_mask)
443 {
444         uint64_t cdata[2] = {0ULL, 0ULL}, nibble;
445         int i, j = 0;
446
447         for (i = 0; i < NPC_MAX_KEY_NIBBLES; i++) {
448                 if (nibble_mask & (1 << i)) {
449                         nibble = (data[i / 16] >> ((i & 0xf) * 4)) & 0xf;
450                         cdata[j / 16] |= (nibble << ((j & 0xf) * 4));
451                         j += 1;
452                 }
453         }
454
455         data[0] = cdata[0];
456         data[1] = cdata[1];
457 }
458
459 static int
460 flow_first_set_bit(uint64_t slab)
461 {
462         int num = 0;
463
464         if ((slab & 0xffffffff) == 0) {
465                 num += 32;
466                 slab >>= 32;
467         }
468         if ((slab & 0xffff) == 0) {
469                 num += 16;
470                 slab >>= 16;
471         }
472         if ((slab & 0xff) == 0) {
473                 num += 8;
474                 slab >>= 8;
475         }
476         if ((slab & 0xf) == 0) {
477                 num += 4;
478                 slab >>= 4;
479         }
480         if ((slab & 0x3) == 0) {
481                 num += 2;
482                 slab >>= 2;
483         }
484         if ((slab & 0x1) == 0)
485                 num += 1;
486
487         return num;
488 }
489
490 static int
491 flow_shift_lv_ent(struct otx2_mbox *mbox, struct rte_flow *flow,
492                   struct otx2_npc_flow_info *flow_info,
493                   uint32_t old_ent, uint32_t new_ent)
494 {
495         struct npc_mcam_shift_entry_req *req;
496         struct npc_mcam_shift_entry_rsp *rsp;
497         struct otx2_flow_list *list;
498         struct rte_flow *flow_iter;
499         int rc = 0;
500
501         otx2_npc_dbg("Old ent:%u new ent:%u priority:%u", old_ent, new_ent,
502                      flow->priority);
503
504         list = &flow_info->flow_list[flow->priority];
505
506         /* Old entry is disabled & it's contents are moved to new_entry,
507          * new entry is enabled finally.
508          */
509         req = otx2_mbox_alloc_msg_npc_mcam_shift_entry(mbox);
510         req->curr_entry[0] = old_ent;
511         req->new_entry[0] = new_ent;
512         req->shift_count = 1;
513
514         otx2_mbox_msg_send(mbox, 0);
515         rc = otx2_mbox_get_rsp(mbox, 0, (void *)&rsp);
516         if (rc)
517                 return rc;
518
519         /* Remove old node from list */
520         TAILQ_FOREACH(flow_iter, list, next) {
521                 if (flow_iter->mcam_id == old_ent)
522                         TAILQ_REMOVE(list, flow_iter, next);
523         }
524
525         /* Insert node with new mcam id at right place */
526         TAILQ_FOREACH(flow_iter, list, next) {
527                 if (flow_iter->mcam_id > new_ent)
528                         TAILQ_INSERT_BEFORE(flow_iter, flow, next);
529         }
530         return rc;
531 }
532
533 /* Exchange all required entries with a given priority level */
534 static int
535 flow_shift_ent(struct otx2_mbox *mbox, struct rte_flow *flow,
536                struct otx2_npc_flow_info *flow_info,
537                struct npc_mcam_alloc_entry_rsp *rsp, int dir, int prio_lvl)
538 {
539         struct rte_bitmap *fr_bmp, *fr_bmp_rev, *lv_bmp, *lv_bmp_rev, *bmp;
540         uint32_t e_fr = 0, e_lv = 0, e, e_id = 0, mcam_entries;
541         uint64_t fr_bit_pos = 0, lv_bit_pos = 0, bit_pos = 0;
542         /* Bit position within the slab */
543         uint32_t sl_fr_bit_off = 0, sl_lv_bit_off = 0;
544         /* Overall bit position of the start of slab */
545         /* free & live entry index */
546         int rc_fr = 0, rc_lv = 0, rc = 0, idx = 0;
547         struct otx2_mcam_ents_info *ent_info;
548         /* free & live bitmap slab */
549         uint64_t sl_fr = 0, sl_lv = 0, *sl;
550
551         fr_bmp = flow_info->free_entries[prio_lvl];
552         fr_bmp_rev = flow_info->free_entries_rev[prio_lvl];
553         lv_bmp = flow_info->live_entries[prio_lvl];
554         lv_bmp_rev = flow_info->live_entries_rev[prio_lvl];
555         ent_info = &flow_info->flow_entry_info[prio_lvl];
556         mcam_entries = flow_info->mcam_entries;
557
558
559         /* New entries allocated are always contiguous, but older entries
560          * already in free/live bitmap can be non-contiguous: so return
561          * shifted entries should be in non-contiguous format.
562          */
563         while (idx <= rsp->count) {
564                 if (!sl_fr && !sl_lv) {
565                         /* Lower index elements to be exchanged */
566                         if (dir < 0) {
567                                 rc_fr = rte_bitmap_scan(fr_bmp, &e_fr, &sl_fr);
568                                 rc_lv = rte_bitmap_scan(lv_bmp, &e_lv, &sl_lv);
569                                 otx2_npc_dbg("Fwd slab rc fr %u rc lv %u "
570                                              "e_fr %u e_lv %u", rc_fr, rc_lv,
571                                               e_fr, e_lv);
572                         } else {
573                                 rc_fr = rte_bitmap_scan(fr_bmp_rev,
574                                                         &sl_fr_bit_off,
575                                                         &sl_fr);
576                                 rc_lv = rte_bitmap_scan(lv_bmp_rev,
577                                                         &sl_lv_bit_off,
578                                                         &sl_lv);
579
580                                 otx2_npc_dbg("Rev slab rc fr %u rc lv %u "
581                                              "e_fr %u e_lv %u", rc_fr, rc_lv,
582                                               e_fr, e_lv);
583                         }
584                 }
585
586                 if (rc_fr) {
587                         fr_bit_pos = flow_first_set_bit(sl_fr);
588                         e_fr = sl_fr_bit_off + fr_bit_pos;
589                         otx2_npc_dbg("Fr_bit_pos 0x%" PRIx64, fr_bit_pos);
590                 } else {
591                         e_fr = ~(0);
592                 }
593
594                 if (rc_lv) {
595                         lv_bit_pos = flow_first_set_bit(sl_lv);
596                         e_lv = sl_lv_bit_off + lv_bit_pos;
597                         otx2_npc_dbg("Lv_bit_pos 0x%" PRIx64, lv_bit_pos);
598                 } else {
599                         e_lv = ~(0);
600                 }
601
602                 /* First entry is from free_bmap */
603                 if (e_fr < e_lv) {
604                         bmp = fr_bmp;
605                         e = e_fr;
606                         sl = &sl_fr;
607                         bit_pos = fr_bit_pos;
608                         if (dir > 0)
609                                 e_id = mcam_entries - e - 1;
610                         else
611                                 e_id = e;
612                         otx2_npc_dbg("Fr e %u e_id %u", e, e_id);
613                 } else {
614                         bmp = lv_bmp;
615                         e = e_lv;
616                         sl = &sl_lv;
617                         bit_pos = lv_bit_pos;
618                         if (dir > 0)
619                                 e_id = mcam_entries - e - 1;
620                         else
621                                 e_id = e;
622
623                         otx2_npc_dbg("Lv e %u e_id %u", e, e_id);
624                         if (idx < rsp->count)
625                                 rc =
626                                   flow_shift_lv_ent(mbox, flow,
627                                                     flow_info, e_id,
628                                                     rsp->entry + idx);
629                 }
630
631                 rte_bitmap_clear(bmp, e);
632                 rte_bitmap_set(bmp, rsp->entry + idx);
633                 /* Update entry list, use non-contiguous
634                  * list now.
635                  */
636                 rsp->entry_list[idx] = e_id;
637                 *sl &= ~(1 << bit_pos);
638
639                 /* Update min & max entry identifiers in current
640                  * priority level.
641                  */
642                 if (dir < 0) {
643                         ent_info->max_id = rsp->entry + idx;
644                         ent_info->min_id = e_id;
645                 } else {
646                         ent_info->max_id = e_id;
647                         ent_info->min_id = rsp->entry;
648                 }
649
650                 idx++;
651         }
652         return rc;
653 }
654
655 /* Validate if newly allocated entries lie in the correct priority zone
656  * since NPC_MCAM_LOWER_PRIO & NPC_MCAM_HIGHER_PRIO don't ensure zone accuracy.
657  * If not properly aligned, shift entries to do so
658  */
659 static int
660 flow_validate_and_shift_prio_ent(struct otx2_mbox *mbox, struct rte_flow *flow,
661                                  struct otx2_npc_flow_info *flow_info,
662                                  struct npc_mcam_alloc_entry_rsp *rsp,
663                                  int req_prio)
664 {
665         int prio_idx = 0, rc = 0, needs_shift = 0, idx, prio = flow->priority;
666         struct otx2_mcam_ents_info *info = flow_info->flow_entry_info;
667         int dir = (req_prio == NPC_MCAM_HIGHER_PRIO) ? 1 : -1;
668         uint32_t tot_ent = 0;
669
670         otx2_npc_dbg("Dir %d, priority = %d", dir, prio);
671
672         if (dir < 0)
673                 prio_idx = flow_info->flow_max_priority - 1;
674
675         /* Only live entries needs to be shifted, free entries can just be
676          * moved by bits manipulation.
677          */
678
679         /* For dir = -1(NPC_MCAM_LOWER_PRIO), when shifting,
680          * NPC_MAX_PREALLOC_ENT are exchanged with adjoining higher priority
681          * level entries(lower indexes).
682          *
683          * For dir = +1(NPC_MCAM_HIGHER_PRIO), during shift,
684          * NPC_MAX_PREALLOC_ENT are exchanged with adjoining lower priority
685          * level entries(higher indexes) with highest indexes.
686          */
687         do {
688                 tot_ent = info[prio_idx].free_ent + info[prio_idx].live_ent;
689
690                 if (dir < 0 && prio_idx != prio &&
691                     rsp->entry > info[prio_idx].max_id && tot_ent) {
692                         otx2_npc_dbg("Rsp entry %u prio idx %u "
693                                      "max id %u", rsp->entry, prio_idx,
694                                       info[prio_idx].max_id);
695
696                         needs_shift = 1;
697                 } else if ((dir > 0) && (prio_idx != prio) &&
698                      (rsp->entry < info[prio_idx].min_id) && tot_ent) {
699                         otx2_npc_dbg("Rsp entry %u prio idx %u "
700                                      "min id %u", rsp->entry, prio_idx,
701                                       info[prio_idx].min_id);
702                         needs_shift = 1;
703                 }
704
705                 otx2_npc_dbg("Needs_shift = %d", needs_shift);
706                 if (needs_shift) {
707                         needs_shift = 0;
708                         rc = flow_shift_ent(mbox, flow, flow_info, rsp, dir,
709                                             prio_idx);
710                 } else {
711                         for (idx = 0; idx < rsp->count; idx++)
712                                 rsp->entry_list[idx] = rsp->entry + idx;
713                 }
714         } while ((prio_idx != prio) && (prio_idx += dir));
715
716         return rc;
717 }
718
719 static int
720 flow_find_ref_entry(struct otx2_npc_flow_info *flow_info, int *prio,
721                     int prio_lvl)
722 {
723         struct otx2_mcam_ents_info *info = flow_info->flow_entry_info;
724         int step = 1;
725
726         while (step < flow_info->flow_max_priority) {
727                 if (((prio_lvl + step) < flow_info->flow_max_priority) &&
728                     info[prio_lvl + step].live_ent) {
729                         *prio = NPC_MCAM_HIGHER_PRIO;
730                         return info[prio_lvl + step].min_id;
731                 }
732
733                 if (((prio_lvl - step) >= 0) &&
734                     info[prio_lvl - step].live_ent) {
735                         otx2_npc_dbg("Prio_lvl %u live %u", prio_lvl - step,
736                                      info[prio_lvl - step].live_ent);
737                         *prio = NPC_MCAM_LOWER_PRIO;
738                         return info[prio_lvl - step].max_id;
739                 }
740                 step++;
741         }
742         *prio = NPC_MCAM_ANY_PRIO;
743         return 0;
744 }
745
746 static int
747 flow_fill_entry_cache(struct otx2_mbox *mbox, struct rte_flow *flow,
748                       struct otx2_npc_flow_info *flow_info, uint32_t *free_ent)
749 {
750         struct rte_bitmap *free_bmp, *free_bmp_rev, *live_bmp, *live_bmp_rev;
751         struct npc_mcam_alloc_entry_rsp rsp_local;
752         struct npc_mcam_alloc_entry_rsp *rsp_cmd;
753         struct npc_mcam_alloc_entry_req *req;
754         struct npc_mcam_alloc_entry_rsp *rsp;
755         struct otx2_mcam_ents_info *info;
756         uint16_t ref_ent, idx;
757         int rc, prio;
758
759         info = &flow_info->flow_entry_info[flow->priority];
760         free_bmp = flow_info->free_entries[flow->priority];
761         free_bmp_rev = flow_info->free_entries_rev[flow->priority];
762         live_bmp = flow_info->live_entries[flow->priority];
763         live_bmp_rev = flow_info->live_entries_rev[flow->priority];
764
765         ref_ent = flow_find_ref_entry(flow_info, &prio, flow->priority);
766
767         req = otx2_mbox_alloc_msg_npc_mcam_alloc_entry(mbox);
768         req->contig = 1;
769         req->count = flow_info->flow_prealloc_size;
770         req->priority = prio;
771         req->ref_entry = ref_ent;
772
773         otx2_npc_dbg("Fill cache ref entry %u prio %u", ref_ent, prio);
774
775         otx2_mbox_msg_send(mbox, 0);
776         rc = otx2_mbox_get_rsp(mbox, 0, (void *)&rsp_cmd);
777         if (rc)
778                 return rc;
779
780         rsp = &rsp_local;
781         memcpy(rsp, rsp_cmd, sizeof(*rsp));
782
783         otx2_npc_dbg("Alloc entry %u count %u , prio = %d", rsp->entry,
784                      rsp->count, prio);
785
786         /* Non-first ent cache fill */
787         if (prio != NPC_MCAM_ANY_PRIO) {
788                 flow_validate_and_shift_prio_ent(mbox, flow, flow_info, rsp,
789                                                  prio);
790         } else {
791                 /* Copy into response entry list */
792                 for (idx = 0; idx < rsp->count; idx++)
793                         rsp->entry_list[idx] = rsp->entry + idx;
794         }
795
796         otx2_npc_dbg("Fill entry cache rsp count %u", rsp->count);
797         /* Update free entries, reverse free entries list,
798          * min & max entry ids.
799          */
800         for (idx = 0; idx < rsp->count; idx++) {
801                 if (unlikely(rsp->entry_list[idx] < info->min_id))
802                         info->min_id = rsp->entry_list[idx];
803
804                 if (unlikely(rsp->entry_list[idx] > info->max_id))
805                         info->max_id = rsp->entry_list[idx];
806
807                 /* Skip entry to be returned, not to be part of free
808                  * list.
809                  */
810                 if (prio == NPC_MCAM_HIGHER_PRIO) {
811                         if (unlikely(idx == (rsp->count - 1))) {
812                                 *free_ent = rsp->entry_list[idx];
813                                 continue;
814                         }
815                 } else {
816                         if (unlikely(!idx)) {
817                                 *free_ent = rsp->entry_list[idx];
818                                 continue;
819                         }
820                 }
821                 info->free_ent++;
822                 rte_bitmap_set(free_bmp, rsp->entry_list[idx]);
823                 rte_bitmap_set(free_bmp_rev, flow_info->mcam_entries -
824                                rsp->entry_list[idx] - 1);
825
826                 otx2_npc_dbg("Final rsp entry %u rsp entry rev %u",
827                              rsp->entry_list[idx],
828                 flow_info->mcam_entries - rsp->entry_list[idx] - 1);
829         }
830
831         otx2_npc_dbg("Cache free entry %u, rev = %u", *free_ent,
832                      flow_info->mcam_entries - *free_ent - 1);
833         info->live_ent++;
834         rte_bitmap_set(live_bmp, *free_ent);
835         rte_bitmap_set(live_bmp_rev, flow_info->mcam_entries - *free_ent - 1);
836
837         return 0;
838 }
839
840 static int
841 flow_check_preallocated_entry_cache(struct otx2_mbox *mbox,
842                                     struct rte_flow *flow,
843                                     struct otx2_npc_flow_info *flow_info)
844 {
845         struct rte_bitmap *free, *free_rev, *live, *live_rev;
846         uint32_t pos = 0, free_ent = 0, mcam_entries;
847         struct otx2_mcam_ents_info *info;
848         uint64_t slab = 0;
849         int rc;
850
851         otx2_npc_dbg("Flow priority %u", flow->priority);
852
853         info = &flow_info->flow_entry_info[flow->priority];
854
855         free_rev = flow_info->free_entries_rev[flow->priority];
856         free = flow_info->free_entries[flow->priority];
857         live_rev = flow_info->live_entries_rev[flow->priority];
858         live = flow_info->live_entries[flow->priority];
859         mcam_entries = flow_info->mcam_entries;
860
861         if (info->free_ent) {
862                 rc = rte_bitmap_scan(free, &pos, &slab);
863                 if (rc) {
864                         /* Get free_ent from free entry bitmap */
865                         free_ent = pos + __builtin_ctzll(slab);
866                         otx2_npc_dbg("Allocated from cache entry %u", free_ent);
867                         /* Remove from free bitmaps and add to live ones */
868                         rte_bitmap_clear(free, free_ent);
869                         rte_bitmap_set(live, free_ent);
870                         rte_bitmap_clear(free_rev,
871                                          mcam_entries - free_ent - 1);
872                         rte_bitmap_set(live_rev,
873                                        mcam_entries - free_ent - 1);
874
875                         info->free_ent--;
876                         info->live_ent++;
877                         return free_ent;
878                 }
879
880                 otx2_npc_dbg("No free entry:its a mess");
881                 return -1;
882         }
883
884         rc = flow_fill_entry_cache(mbox, flow, flow_info, &free_ent);
885         if (rc)
886                 return rc;
887
888         return free_ent;
889 }
890
891 int
892 otx2_flow_mcam_alloc_and_write(struct rte_flow *flow, struct otx2_mbox *mbox,
893                                struct otx2_parse_state *pst,
894                                struct otx2_npc_flow_info *flow_info)
895 {
896         int use_ctr = (flow->ctr_id == NPC_COUNTER_NONE ? 0 : 1);
897         struct npc_mcam_read_base_rule_rsp *base_rule_rsp;
898         struct npc_mcam_write_entry_req *req;
899         struct mcam_entry *base_entry;
900         struct mbox_msghdr *rsp;
901         uint16_t ctr = ~(0);
902         int rc, idx;
903         int entry;
904
905         if (use_ctr) {
906                 rc = flow_mcam_alloc_counter(mbox, &ctr);
907                 if (rc)
908                         return rc;
909         }
910
911         entry = flow_check_preallocated_entry_cache(mbox, flow, flow_info);
912         if (entry < 0) {
913                 otx2_err("Prealloc failed");
914                 otx2_flow_mcam_free_counter(mbox, ctr);
915                 return NPC_MCAM_ALLOC_FAILED;
916         }
917
918         if (pst->is_vf) {
919                 (void)otx2_mbox_alloc_msg_npc_read_base_steer_rule(mbox);
920                 rc = otx2_mbox_process_msg(mbox, (void *)&base_rule_rsp);
921                 if (rc) {
922                         otx2_err("Failed to fetch VF's base MCAM entry");
923                         return rc;
924                 }
925                 base_entry = &base_rule_rsp->entry_data;
926                 for (idx = 0; idx < OTX2_MAX_MCAM_WIDTH_DWORDS; idx++) {
927                         flow->mcam_data[idx] |= base_entry->kw[idx];
928                         flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
929                 }
930         }
931
932         req = otx2_mbox_alloc_msg_npc_mcam_write_entry(mbox);
933         req->set_cntr = use_ctr;
934         req->cntr = ctr;
935         req->entry = entry;
936         otx2_npc_dbg("Alloc & write entry %u", entry);
937
938         req->intf =
939                 (flow->nix_intf == OTX2_INTF_RX) ? NPC_MCAM_RX : NPC_MCAM_TX;
940         req->enable_entry = 1;
941         req->entry_data.action = flow->npc_action;
942         req->entry_data.vtag_action = flow->vtag_action;
943
944         for (idx = 0; idx < OTX2_MAX_MCAM_WIDTH_DWORDS; idx++) {
945                 req->entry_data.kw[idx] = flow->mcam_data[idx];
946                 req->entry_data.kw_mask[idx] = flow->mcam_mask[idx];
947         }
948
949         if (flow->nix_intf == OTX2_INTF_RX) {
950                 req->entry_data.kw[0] |= flow_info->channel;
951                 req->entry_data.kw_mask[0] |=  (BIT_ULL(12) - 1);
952         } else {
953                 uint16_t pf_func = (flow->npc_action >> 48) & 0xffff;
954
955                 pf_func = htons(pf_func);
956                 req->entry_data.kw[0] |= ((uint64_t)pf_func << 32);
957                 req->entry_data.kw_mask[0] |= ((uint64_t)0xffff << 32);
958         }
959
960         otx2_mbox_msg_send(mbox, 0);
961         rc = otx2_mbox_get_rsp(mbox, 0, (void *)&rsp);
962         if (rc != 0)
963                 return rc;
964
965         flow->mcam_id = entry;
966         if (use_ctr)
967                 flow->ctr_id = ctr;
968         return 0;
969 }