d5f0645dc52da1390e788ad384686be19e38f7ed
[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         info->spec = item->spec;
394
395         /* If mask is not set, use default mask, err if default mask is
396          * also NULL.
397          */
398         if (item->mask == NULL) {
399                 otx2_npc_dbg("Item mask null, using default mask");
400                 if (info->def_mask == NULL) {
401                         rte_flow_error_set(error, EINVAL,
402                                            RTE_FLOW_ERROR_TYPE_ITEM, item,
403                                            "No mask or default mask given");
404                         return -rte_errno;
405                 }
406                 info->mask = info->def_mask;
407         } else {
408                 info->mask = item->mask;
409         }
410
411         /* mask specified must be subset of hw supported mask
412          * mask | hw_mask == hw_mask
413          */
414         if (!flow_mask_is_supported(info->mask, info->hw_mask, info->len)) {
415                 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,
416                                    item, "Unsupported field in the mask");
417                 return -rte_errno;
418         }
419
420         /* Now we have spec and mask. OTX2 does not support non-contiguous
421          * range. We should have either:
422          * - spec & mask == last & mask or,
423          * - last == 0 or,
424          * - last == NULL
425          */
426         if (item->last != NULL && !flow_mem_is_zero(item->last, info->len)) {
427                 if (!flow_range_is_valid(item->spec, item->last, info->mask,
428                                          info->len)) {
429                         rte_flow_error_set(error, EINVAL,
430                                            RTE_FLOW_ERROR_TYPE_ITEM, item,
431                                            "Unsupported range for match");
432                         return -rte_errno;
433                 }
434         }
435
436         return 0;
437 }
438
439 void
440 otx2_flow_keyx_compress(uint64_t *data, uint32_t nibble_mask)
441 {
442         uint64_t cdata[2] = {0ULL, 0ULL}, nibble;
443         int i, j = 0;
444
445         for (i = 0; i < NPC_MAX_KEY_NIBBLES; i++) {
446                 if (nibble_mask & (1 << i)) {
447                         nibble = (data[i / 16] >> ((i & 0xf) * 4)) & 0xf;
448                         cdata[j / 16] |= (nibble << ((j & 0xf) * 4));
449                         j += 1;
450                 }
451         }
452
453         data[0] = cdata[0];
454         data[1] = cdata[1];
455 }
456
457 static int
458 flow_first_set_bit(uint64_t slab)
459 {
460         int num = 0;
461
462         if ((slab & 0xffffffff) == 0) {
463                 num += 32;
464                 slab >>= 32;
465         }
466         if ((slab & 0xffff) == 0) {
467                 num += 16;
468                 slab >>= 16;
469         }
470         if ((slab & 0xff) == 0) {
471                 num += 8;
472                 slab >>= 8;
473         }
474         if ((slab & 0xf) == 0) {
475                 num += 4;
476                 slab >>= 4;
477         }
478         if ((slab & 0x3) == 0) {
479                 num += 2;
480                 slab >>= 2;
481         }
482         if ((slab & 0x1) == 0)
483                 num += 1;
484
485         return num;
486 }
487
488 static int
489 flow_shift_lv_ent(struct otx2_mbox *mbox, struct rte_flow *flow,
490                   struct otx2_npc_flow_info *flow_info,
491                   uint32_t old_ent, uint32_t new_ent)
492 {
493         struct npc_mcam_shift_entry_req *req;
494         struct npc_mcam_shift_entry_rsp *rsp;
495         struct otx2_flow_list *list;
496         struct rte_flow *flow_iter;
497         int rc = 0;
498
499         otx2_npc_dbg("Old ent:%u new ent:%u priority:%u", old_ent, new_ent,
500                      flow->priority);
501
502         list = &flow_info->flow_list[flow->priority];
503
504         /* Old entry is disabled & it's contents are moved to new_entry,
505          * new entry is enabled finally.
506          */
507         req = otx2_mbox_alloc_msg_npc_mcam_shift_entry(mbox);
508         req->curr_entry[0] = old_ent;
509         req->new_entry[0] = new_ent;
510         req->shift_count = 1;
511
512         otx2_mbox_msg_send(mbox, 0);
513         rc = otx2_mbox_get_rsp(mbox, 0, (void *)&rsp);
514         if (rc)
515                 return rc;
516
517         /* Remove old node from list */
518         TAILQ_FOREACH(flow_iter, list, next) {
519                 if (flow_iter->mcam_id == old_ent)
520                         TAILQ_REMOVE(list, flow_iter, next);
521         }
522
523         /* Insert node with new mcam id at right place */
524         TAILQ_FOREACH(flow_iter, list, next) {
525                 if (flow_iter->mcam_id > new_ent)
526                         TAILQ_INSERT_BEFORE(flow_iter, flow, next);
527         }
528         return rc;
529 }
530
531 /* Exchange all required entries with a given priority level */
532 static int
533 flow_shift_ent(struct otx2_mbox *mbox, struct rte_flow *flow,
534                struct otx2_npc_flow_info *flow_info,
535                struct npc_mcam_alloc_entry_rsp *rsp, int dir, int prio_lvl)
536 {
537         struct rte_bitmap *fr_bmp, *fr_bmp_rev, *lv_bmp, *lv_bmp_rev, *bmp;
538         uint32_t e_fr = 0, e_lv = 0, e, e_id = 0, mcam_entries;
539         uint64_t fr_bit_pos = 0, lv_bit_pos = 0, bit_pos = 0;
540         /* Bit position within the slab */
541         uint32_t sl_fr_bit_off = 0, sl_lv_bit_off = 0;
542         /* Overall bit position of the start of slab */
543         /* free & live entry index */
544         int rc_fr = 0, rc_lv = 0, rc = 0, idx = 0;
545         struct otx2_mcam_ents_info *ent_info;
546         /* free & live bitmap slab */
547         uint64_t sl_fr = 0, sl_lv = 0, *sl;
548
549         fr_bmp = flow_info->free_entries[prio_lvl];
550         fr_bmp_rev = flow_info->free_entries_rev[prio_lvl];
551         lv_bmp = flow_info->live_entries[prio_lvl];
552         lv_bmp_rev = flow_info->live_entries_rev[prio_lvl];
553         ent_info = &flow_info->flow_entry_info[prio_lvl];
554         mcam_entries = flow_info->mcam_entries;
555
556
557         /* New entries allocated are always contiguous, but older entries
558          * already in free/live bitmap can be non-contiguous: so return
559          * shifted entries should be in non-contiguous format.
560          */
561         while (idx <= rsp->count) {
562                 if (!sl_fr && !sl_lv) {
563                         /* Lower index elements to be exchanged */
564                         if (dir < 0) {
565                                 rc_fr = rte_bitmap_scan(fr_bmp, &e_fr, &sl_fr);
566                                 rc_lv = rte_bitmap_scan(lv_bmp, &e_lv, &sl_lv);
567                                 otx2_npc_dbg("Fwd slab rc fr %u rc lv %u "
568                                              "e_fr %u e_lv %u", rc_fr, rc_lv,
569                                               e_fr, e_lv);
570                         } else {
571                                 rc_fr = rte_bitmap_scan(fr_bmp_rev,
572                                                         &sl_fr_bit_off,
573                                                         &sl_fr);
574                                 rc_lv = rte_bitmap_scan(lv_bmp_rev,
575                                                         &sl_lv_bit_off,
576                                                         &sl_lv);
577
578                                 otx2_npc_dbg("Rev slab rc fr %u rc lv %u "
579                                              "e_fr %u e_lv %u", rc_fr, rc_lv,
580                                               e_fr, e_lv);
581                         }
582                 }
583
584                 if (rc_fr) {
585                         fr_bit_pos = flow_first_set_bit(sl_fr);
586                         e_fr = sl_fr_bit_off + fr_bit_pos;
587                         otx2_npc_dbg("Fr_bit_pos 0x%" PRIx64, fr_bit_pos);
588                 } else {
589                         e_fr = ~(0);
590                 }
591
592                 if (rc_lv) {
593                         lv_bit_pos = flow_first_set_bit(sl_lv);
594                         e_lv = sl_lv_bit_off + lv_bit_pos;
595                         otx2_npc_dbg("Lv_bit_pos 0x%" PRIx64, lv_bit_pos);
596                 } else {
597                         e_lv = ~(0);
598                 }
599
600                 /* First entry is from free_bmap */
601                 if (e_fr < e_lv) {
602                         bmp = fr_bmp;
603                         e = e_fr;
604                         sl = &sl_fr;
605                         bit_pos = fr_bit_pos;
606                         if (dir > 0)
607                                 e_id = mcam_entries - e - 1;
608                         else
609                                 e_id = e;
610                         otx2_npc_dbg("Fr e %u e_id %u", e, e_id);
611                 } else {
612                         bmp = lv_bmp;
613                         e = e_lv;
614                         sl = &sl_lv;
615                         bit_pos = lv_bit_pos;
616                         if (dir > 0)
617                                 e_id = mcam_entries - e - 1;
618                         else
619                                 e_id = e;
620
621                         otx2_npc_dbg("Lv e %u e_id %u", e, e_id);
622                         if (idx < rsp->count)
623                                 rc =
624                                   flow_shift_lv_ent(mbox, flow,
625                                                     flow_info, e_id,
626                                                     rsp->entry + idx);
627                 }
628
629                 rte_bitmap_clear(bmp, e);
630                 rte_bitmap_set(bmp, rsp->entry + idx);
631                 /* Update entry list, use non-contiguous
632                  * list now.
633                  */
634                 rsp->entry_list[idx] = e_id;
635                 *sl &= ~(1 << bit_pos);
636
637                 /* Update min & max entry identifiers in current
638                  * priority level.
639                  */
640                 if (dir < 0) {
641                         ent_info->max_id = rsp->entry + idx;
642                         ent_info->min_id = e_id;
643                 } else {
644                         ent_info->max_id = e_id;
645                         ent_info->min_id = rsp->entry;
646                 }
647
648                 idx++;
649         }
650         return rc;
651 }
652
653 /* Validate if newly allocated entries lie in the correct priority zone
654  * since NPC_MCAM_LOWER_PRIO & NPC_MCAM_HIGHER_PRIO don't ensure zone accuracy.
655  * If not properly aligned, shift entries to do so
656  */
657 static int
658 flow_validate_and_shift_prio_ent(struct otx2_mbox *mbox, struct rte_flow *flow,
659                                  struct otx2_npc_flow_info *flow_info,
660                                  struct npc_mcam_alloc_entry_rsp *rsp,
661                                  int req_prio)
662 {
663         int prio_idx = 0, rc = 0, needs_shift = 0, idx, prio = flow->priority;
664         struct otx2_mcam_ents_info *info = flow_info->flow_entry_info;
665         int dir = (req_prio == NPC_MCAM_HIGHER_PRIO) ? 1 : -1;
666         uint32_t tot_ent = 0;
667
668         otx2_npc_dbg("Dir %d, priority = %d", dir, prio);
669
670         if (dir < 0)
671                 prio_idx = flow_info->flow_max_priority - 1;
672
673         /* Only live entries needs to be shifted, free entries can just be
674          * moved by bits manipulation.
675          */
676
677         /* For dir = -1(NPC_MCAM_LOWER_PRIO), when shifting,
678          * NPC_MAX_PREALLOC_ENT are exchanged with adjoining higher priority
679          * level entries(lower indexes).
680          *
681          * For dir = +1(NPC_MCAM_HIGHER_PRIO), during shift,
682          * NPC_MAX_PREALLOC_ENT are exchanged with adjoining lower priority
683          * level entries(higher indexes) with highest indexes.
684          */
685         do {
686                 tot_ent = info[prio_idx].free_ent + info[prio_idx].live_ent;
687
688                 if (dir < 0 && prio_idx != prio &&
689                     rsp->entry > info[prio_idx].max_id && tot_ent) {
690                         otx2_npc_dbg("Rsp entry %u prio idx %u "
691                                      "max id %u", rsp->entry, prio_idx,
692                                       info[prio_idx].max_id);
693
694                         needs_shift = 1;
695                 } else if ((dir > 0) && (prio_idx != prio) &&
696                      (rsp->entry < info[prio_idx].min_id) && tot_ent) {
697                         otx2_npc_dbg("Rsp entry %u prio idx %u "
698                                      "min id %u", rsp->entry, prio_idx,
699                                       info[prio_idx].min_id);
700                         needs_shift = 1;
701                 }
702
703                 otx2_npc_dbg("Needs_shift = %d", needs_shift);
704                 if (needs_shift) {
705                         needs_shift = 0;
706                         rc = flow_shift_ent(mbox, flow, flow_info, rsp, dir,
707                                             prio_idx);
708                 } else {
709                         for (idx = 0; idx < rsp->count; idx++)
710                                 rsp->entry_list[idx] = rsp->entry + idx;
711                 }
712         } while ((prio_idx != prio) && (prio_idx += dir));
713
714         return rc;
715 }
716
717 static int
718 flow_find_ref_entry(struct otx2_npc_flow_info *flow_info, int *prio,
719                     int prio_lvl)
720 {
721         struct otx2_mcam_ents_info *info = flow_info->flow_entry_info;
722         int step = 1;
723
724         while (step < flow_info->flow_max_priority) {
725                 if (((prio_lvl + step) < flow_info->flow_max_priority) &&
726                     info[prio_lvl + step].live_ent) {
727                         *prio = NPC_MCAM_HIGHER_PRIO;
728                         return info[prio_lvl + step].min_id;
729                 }
730
731                 if (((prio_lvl - step) >= 0) &&
732                     info[prio_lvl - step].live_ent) {
733                         otx2_npc_dbg("Prio_lvl %u live %u", prio_lvl - step,
734                                      info[prio_lvl - step].live_ent);
735                         *prio = NPC_MCAM_LOWER_PRIO;
736                         return info[prio_lvl - step].max_id;
737                 }
738                 step++;
739         }
740         *prio = NPC_MCAM_ANY_PRIO;
741         return 0;
742 }
743
744 static int
745 flow_fill_entry_cache(struct otx2_mbox *mbox, struct rte_flow *flow,
746                       struct otx2_npc_flow_info *flow_info, uint32_t *free_ent)
747 {
748         struct rte_bitmap *free_bmp, *free_bmp_rev, *live_bmp, *live_bmp_rev;
749         struct npc_mcam_alloc_entry_rsp rsp_local;
750         struct npc_mcam_alloc_entry_rsp *rsp_cmd;
751         struct npc_mcam_alloc_entry_req *req;
752         struct npc_mcam_alloc_entry_rsp *rsp;
753         struct otx2_mcam_ents_info *info;
754         uint16_t ref_ent, idx;
755         int rc, prio;
756
757         info = &flow_info->flow_entry_info[flow->priority];
758         free_bmp = flow_info->free_entries[flow->priority];
759         free_bmp_rev = flow_info->free_entries_rev[flow->priority];
760         live_bmp = flow_info->live_entries[flow->priority];
761         live_bmp_rev = flow_info->live_entries_rev[flow->priority];
762
763         ref_ent = flow_find_ref_entry(flow_info, &prio, flow->priority);
764
765         req = otx2_mbox_alloc_msg_npc_mcam_alloc_entry(mbox);
766         req->contig = 1;
767         req->count = flow_info->flow_prealloc_size;
768         req->priority = prio;
769         req->ref_entry = ref_ent;
770
771         otx2_npc_dbg("Fill cache ref entry %u prio %u", ref_ent, prio);
772
773         otx2_mbox_msg_send(mbox, 0);
774         rc = otx2_mbox_get_rsp(mbox, 0, (void *)&rsp_cmd);
775         if (rc)
776                 return rc;
777
778         rsp = &rsp_local;
779         memcpy(rsp, rsp_cmd, sizeof(*rsp));
780
781         otx2_npc_dbg("Alloc entry %u count %u , prio = %d", rsp->entry,
782                      rsp->count, prio);
783
784         /* Non-first ent cache fill */
785         if (prio != NPC_MCAM_ANY_PRIO) {
786                 flow_validate_and_shift_prio_ent(mbox, flow, flow_info, rsp,
787                                                  prio);
788         } else {
789                 /* Copy into response entry list */
790                 for (idx = 0; idx < rsp->count; idx++)
791                         rsp->entry_list[idx] = rsp->entry + idx;
792         }
793
794         otx2_npc_dbg("Fill entry cache rsp count %u", rsp->count);
795         /* Update free entries, reverse free entries list,
796          * min & max entry ids.
797          */
798         for (idx = 0; idx < rsp->count; idx++) {
799                 if (unlikely(rsp->entry_list[idx] < info->min_id))
800                         info->min_id = rsp->entry_list[idx];
801
802                 if (unlikely(rsp->entry_list[idx] > info->max_id))
803                         info->max_id = rsp->entry_list[idx];
804
805                 /* Skip entry to be returned, not to be part of free
806                  * list.
807                  */
808                 if (prio == NPC_MCAM_HIGHER_PRIO) {
809                         if (unlikely(idx == (rsp->count - 1))) {
810                                 *free_ent = rsp->entry_list[idx];
811                                 continue;
812                         }
813                 } else {
814                         if (unlikely(!idx)) {
815                                 *free_ent = rsp->entry_list[idx];
816                                 continue;
817                         }
818                 }
819                 info->free_ent++;
820                 rte_bitmap_set(free_bmp, rsp->entry_list[idx]);
821                 rte_bitmap_set(free_bmp_rev, flow_info->mcam_entries -
822                                rsp->entry_list[idx] - 1);
823
824                 otx2_npc_dbg("Final rsp entry %u rsp entry rev %u",
825                              rsp->entry_list[idx],
826                 flow_info->mcam_entries - rsp->entry_list[idx] - 1);
827         }
828
829         otx2_npc_dbg("Cache free entry %u, rev = %u", *free_ent,
830                      flow_info->mcam_entries - *free_ent - 1);
831         info->live_ent++;
832         rte_bitmap_set(live_bmp, *free_ent);
833         rte_bitmap_set(live_bmp_rev, flow_info->mcam_entries - *free_ent - 1);
834
835         return 0;
836 }
837
838 static int
839 flow_check_preallocated_entry_cache(struct otx2_mbox *mbox,
840                                     struct rte_flow *flow,
841                                     struct otx2_npc_flow_info *flow_info)
842 {
843         struct rte_bitmap *free, *free_rev, *live, *live_rev;
844         uint32_t pos = 0, free_ent = 0, mcam_entries;
845         struct otx2_mcam_ents_info *info;
846         uint64_t slab = 0;
847         int rc;
848
849         otx2_npc_dbg("Flow priority %u", flow->priority);
850
851         info = &flow_info->flow_entry_info[flow->priority];
852
853         free_rev = flow_info->free_entries_rev[flow->priority];
854         free = flow_info->free_entries[flow->priority];
855         live_rev = flow_info->live_entries_rev[flow->priority];
856         live = flow_info->live_entries[flow->priority];
857         mcam_entries = flow_info->mcam_entries;
858
859         if (info->free_ent) {
860                 rc = rte_bitmap_scan(free, &pos, &slab);
861                 if (rc) {
862                         /* Get free_ent from free entry bitmap */
863                         free_ent = pos + __builtin_ctzll(slab);
864                         otx2_npc_dbg("Allocated from cache entry %u", free_ent);
865                         /* Remove from free bitmaps and add to live ones */
866                         rte_bitmap_clear(free, free_ent);
867                         rte_bitmap_set(live, free_ent);
868                         rte_bitmap_clear(free_rev,
869                                          mcam_entries - free_ent - 1);
870                         rte_bitmap_set(live_rev,
871                                        mcam_entries - free_ent - 1);
872
873                         info->free_ent--;
874                         info->live_ent++;
875                         return free_ent;
876                 }
877
878                 otx2_npc_dbg("No free entry:its a mess");
879                 return -1;
880         }
881
882         rc = flow_fill_entry_cache(mbox, flow, flow_info, &free_ent);
883         if (rc)
884                 return rc;
885
886         return free_ent;
887 }
888
889 int
890 otx2_flow_mcam_alloc_and_write(struct rte_flow *flow, struct otx2_mbox *mbox,
891                                struct otx2_parse_state *pst,
892                                struct otx2_npc_flow_info *flow_info)
893 {
894         int use_ctr = (flow->ctr_id == NPC_COUNTER_NONE ? 0 : 1);
895         struct npc_mcam_read_base_rule_rsp *base_rule_rsp;
896         struct npc_mcam_write_entry_req *req;
897         struct mcam_entry *base_entry;
898         struct mbox_msghdr *rsp;
899         uint16_t ctr = ~(0);
900         int rc, idx;
901         int entry;
902
903         if (use_ctr) {
904                 rc = flow_mcam_alloc_counter(mbox, &ctr);
905                 if (rc)
906                         return rc;
907         }
908
909         entry = flow_check_preallocated_entry_cache(mbox, flow, flow_info);
910         if (entry < 0) {
911                 otx2_err("Prealloc failed");
912                 otx2_flow_mcam_free_counter(mbox, ctr);
913                 return NPC_MCAM_ALLOC_FAILED;
914         }
915
916         if (pst->is_vf) {
917                 (void)otx2_mbox_alloc_msg_npc_read_base_steer_rule(mbox);
918                 rc = otx2_mbox_process_msg(mbox, (void *)&base_rule_rsp);
919                 if (rc) {
920                         otx2_err("Failed to fetch VF's base MCAM entry");
921                         return rc;
922                 }
923                 base_entry = &base_rule_rsp->entry_data;
924                 for (idx = 0; idx < OTX2_MAX_MCAM_WIDTH_DWORDS; idx++) {
925                         flow->mcam_data[idx] |= base_entry->kw[idx];
926                         flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
927                 }
928         }
929
930         req = otx2_mbox_alloc_msg_npc_mcam_write_entry(mbox);
931         req->set_cntr = use_ctr;
932         req->cntr = ctr;
933         req->entry = entry;
934         otx2_npc_dbg("Alloc & write entry %u", entry);
935
936         req->intf =
937                 (flow->nix_intf == OTX2_INTF_RX) ? NPC_MCAM_RX : NPC_MCAM_TX;
938         req->enable_entry = 1;
939         req->entry_data.action = flow->npc_action;
940         req->entry_data.vtag_action = flow->vtag_action;
941
942         for (idx = 0; idx < OTX2_MAX_MCAM_WIDTH_DWORDS; idx++) {
943                 req->entry_data.kw[idx] = flow->mcam_data[idx];
944                 req->entry_data.kw_mask[idx] = flow->mcam_mask[idx];
945         }
946
947         if (flow->nix_intf == OTX2_INTF_RX) {
948                 req->entry_data.kw[0] |= flow_info->channel;
949                 req->entry_data.kw_mask[0] |=  (BIT_ULL(12) - 1);
950         } else {
951                 uint16_t pf_func = (flow->npc_action >> 48) & 0xffff;
952
953                 pf_func = htons(pf_func);
954                 req->entry_data.kw[0] |= ((uint64_t)pf_func << 32);
955                 req->entry_data.kw_mask[0] |= ((uint64_t)0xffff << 32);
956         }
957
958         otx2_mbox_msg_send(mbox, 0);
959         rc = otx2_mbox_get_rsp(mbox, 0, (void *)&rsp);
960         if (rc != 0)
961                 return rc;
962
963         flow->mcam_id = entry;
964         if (use_ctr)
965                 flow->ctr_id = ctr;
966         return 0;
967 }