net/mlx5: support matching on VXLAN reserved field
[dpdk.git] / drivers / common / cnxk / roc_nix_tm_utils.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4
5 #include "roc_api.h"
6 #include "roc_priv.h"
7
8 static inline uint64_t
9 nix_tm_shaper2regval(struct nix_tm_shaper_data *shaper)
10 {
11         return (shaper->burst_exponent << 37) | (shaper->burst_mantissa << 29) |
12                (shaper->div_exp << 13) | (shaper->exponent << 9) |
13                (shaper->mantissa << 1);
14 }
15
16 uint16_t
17 nix_tm_lvl2nix_tl1_root(uint32_t lvl)
18 {
19         switch (lvl) {
20         case ROC_TM_LVL_ROOT:
21                 return NIX_TXSCH_LVL_TL1;
22         case ROC_TM_LVL_SCH1:
23                 return NIX_TXSCH_LVL_TL2;
24         case ROC_TM_LVL_SCH2:
25                 return NIX_TXSCH_LVL_TL3;
26         case ROC_TM_LVL_SCH3:
27                 return NIX_TXSCH_LVL_TL4;
28         case ROC_TM_LVL_SCH4:
29                 return NIX_TXSCH_LVL_SMQ;
30         default:
31                 return NIX_TXSCH_LVL_CNT;
32         }
33 }
34
35 uint16_t
36 nix_tm_lvl2nix_tl2_root(uint32_t lvl)
37 {
38         switch (lvl) {
39         case ROC_TM_LVL_ROOT:
40                 return NIX_TXSCH_LVL_TL2;
41         case ROC_TM_LVL_SCH1:
42                 return NIX_TXSCH_LVL_TL3;
43         case ROC_TM_LVL_SCH2:
44                 return NIX_TXSCH_LVL_TL4;
45         case ROC_TM_LVL_SCH3:
46                 return NIX_TXSCH_LVL_SMQ;
47         default:
48                 return NIX_TXSCH_LVL_CNT;
49         }
50 }
51
52 uint16_t
53 nix_tm_lvl2nix(struct nix *nix, uint32_t lvl)
54 {
55         if (nix_tm_have_tl1_access(nix))
56                 return nix_tm_lvl2nix_tl1_root(lvl);
57         else
58                 return nix_tm_lvl2nix_tl2_root(lvl);
59 }
60
61 static uint8_t
62 nix_tm_relchan_get(struct nix *nix)
63 {
64         return nix->tx_chan_base & 0xff;
65 }
66
67 static int
68 nix_tm_find_prio_anchor(struct nix *nix, uint32_t node_id,
69                         enum roc_nix_tm_tree tree)
70 {
71         struct nix_tm_node *child_node;
72         struct nix_tm_node_list *list;
73
74         list = nix_tm_node_list(nix, tree);
75
76         TAILQ_FOREACH(child_node, list, node) {
77                 if (!child_node->parent)
78                         continue;
79                 if (!(child_node->parent->id == node_id))
80                         continue;
81                 if (child_node->priority == child_node->parent->rr_prio)
82                         continue;
83                 return child_node->hw_id - child_node->priority;
84         }
85         return 0;
86 }
87
88 struct nix_tm_shaper_profile *
89 nix_tm_shaper_profile_search(struct nix *nix, uint32_t id)
90 {
91         struct nix_tm_shaper_profile *profile;
92
93         TAILQ_FOREACH(profile, &nix->shaper_profile_list, shaper) {
94                 if (profile->id == id)
95                         return profile;
96         }
97         return NULL;
98 }
99
100 struct nix_tm_node *
101 nix_tm_node_search(struct nix *nix, uint32_t node_id, enum roc_nix_tm_tree tree)
102 {
103         struct nix_tm_node_list *list;
104         struct nix_tm_node *node;
105
106         list = nix_tm_node_list(nix, tree);
107         TAILQ_FOREACH(node, list, node) {
108                 if (node->id == node_id)
109                         return node;
110         }
111         return NULL;
112 }
113
114 uint64_t
115 nix_tm_shaper_rate_conv(uint64_t value, uint64_t *exponent_p,
116                         uint64_t *mantissa_p, uint64_t *div_exp_p)
117 {
118         uint64_t div_exp, exponent, mantissa;
119
120         /* Boundary checks */
121         if (value < NIX_TM_MIN_SHAPER_RATE || value > NIX_TM_MAX_SHAPER_RATE)
122                 return 0;
123
124         if (value <= NIX_TM_SHAPER_RATE(0, 0, 0)) {
125                 /* Calculate rate div_exp and mantissa using
126                  * the following formula:
127                  *
128                  * value = (2E6 * (256 + mantissa)
129                  *              / ((1 << div_exp) * 256))
130                  */
131                 div_exp = 0;
132                 exponent = 0;
133                 mantissa = NIX_TM_MAX_RATE_MANTISSA;
134
135                 while (value < (NIX_TM_SHAPER_RATE_CONST / (1 << div_exp)))
136                         div_exp += 1;
137
138                 while (value < ((NIX_TM_SHAPER_RATE_CONST * (256 + mantissa)) /
139                                 ((1 << div_exp) * 256)))
140                         mantissa -= 1;
141         } else {
142                 /* Calculate rate exponent and mantissa using
143                  * the following formula:
144                  *
145                  * value = (2E6 * ((256 + mantissa) << exponent)) / 256
146                  *
147                  */
148                 div_exp = 0;
149                 exponent = NIX_TM_MAX_RATE_EXPONENT;
150                 mantissa = NIX_TM_MAX_RATE_MANTISSA;
151
152                 while (value < (NIX_TM_SHAPER_RATE_CONST * (1 << exponent)))
153                         exponent -= 1;
154
155                 while (value < ((NIX_TM_SHAPER_RATE_CONST *
156                                  ((256 + mantissa) << exponent)) /
157                                 256))
158                         mantissa -= 1;
159         }
160
161         if (div_exp > NIX_TM_MAX_RATE_DIV_EXP ||
162             exponent > NIX_TM_MAX_RATE_EXPONENT ||
163             mantissa > NIX_TM_MAX_RATE_MANTISSA)
164                 return 0;
165
166         if (div_exp_p)
167                 *div_exp_p = div_exp;
168         if (exponent_p)
169                 *exponent_p = exponent;
170         if (mantissa_p)
171                 *mantissa_p = mantissa;
172
173         /* Calculate real rate value */
174         return NIX_TM_SHAPER_RATE(exponent, mantissa, div_exp);
175 }
176
177 uint64_t
178 nix_tm_shaper_burst_conv(uint64_t value, uint64_t *exponent_p,
179                          uint64_t *mantissa_p)
180 {
181         uint64_t exponent, mantissa;
182
183         if (value < NIX_TM_MIN_SHAPER_BURST || value > NIX_TM_MAX_SHAPER_BURST)
184                 return 0;
185
186         /* Calculate burst exponent and mantissa using
187          * the following formula:
188          *
189          * value = (((256 + mantissa) << (exponent + 1)
190          / 256)
191          *
192          */
193         exponent = NIX_TM_MAX_BURST_EXPONENT;
194         mantissa = NIX_TM_MAX_BURST_MANTISSA;
195
196         while (value < (1ull << (exponent + 1)))
197                 exponent -= 1;
198
199         while (value < ((256 + mantissa) << (exponent + 1)) / 256)
200                 mantissa -= 1;
201
202         if (exponent > NIX_TM_MAX_BURST_EXPONENT ||
203             mantissa > NIX_TM_MAX_BURST_MANTISSA)
204                 return 0;
205
206         if (exponent_p)
207                 *exponent_p = exponent;
208         if (mantissa_p)
209                 *mantissa_p = mantissa;
210
211         return NIX_TM_SHAPER_BURST(exponent, mantissa);
212 }
213
214 static void
215 nix_tm_shaper_conf_get(struct nix_tm_shaper_profile *profile,
216                        struct nix_tm_shaper_data *cir,
217                        struct nix_tm_shaper_data *pir)
218 {
219         if (!profile)
220                 return;
221
222         /* Calculate CIR exponent and mantissa */
223         if (profile->commit.rate)
224                 cir->rate = nix_tm_shaper_rate_conv(
225                         profile->commit.rate, &cir->exponent, &cir->mantissa,
226                         &cir->div_exp);
227
228         /* Calculate PIR exponent and mantissa */
229         if (profile->peak.rate)
230                 pir->rate = nix_tm_shaper_rate_conv(
231                         profile->peak.rate, &pir->exponent, &pir->mantissa,
232                         &pir->div_exp);
233
234         /* Calculate CIR burst exponent and mantissa */
235         if (profile->commit.size)
236                 cir->burst = nix_tm_shaper_burst_conv(profile->commit.size,
237                                                       &cir->burst_exponent,
238                                                       &cir->burst_mantissa);
239
240         /* Calculate PIR burst exponent and mantissa */
241         if (profile->peak.size)
242                 pir->burst = nix_tm_shaper_burst_conv(profile->peak.size,
243                                                       &pir->burst_exponent,
244                                                       &pir->burst_mantissa);
245 }
246
247 uint32_t
248 nix_tm_check_rr(struct nix *nix, uint32_t parent_id, enum roc_nix_tm_tree tree,
249                 uint32_t *rr_prio, uint32_t *max_prio)
250 {
251         uint32_t node_cnt[NIX_TM_TLX_SP_PRIO_MAX];
252         struct nix_tm_node_list *list;
253         struct nix_tm_node *node;
254         uint32_t rr_num = 0, i;
255         uint32_t children = 0;
256         uint32_t priority;
257
258         memset(node_cnt, 0, sizeof(node_cnt));
259         *rr_prio = 0xF;
260         *max_prio = UINT32_MAX;
261
262         list = nix_tm_node_list(nix, tree);
263         TAILQ_FOREACH(node, list, node) {
264                 if (!node->parent)
265                         continue;
266
267                 if (!(node->parent->id == parent_id))
268                         continue;
269
270                 priority = node->priority;
271                 node_cnt[priority]++;
272                 children++;
273         }
274
275         for (i = 0; i < NIX_TM_TLX_SP_PRIO_MAX; i++) {
276                 if (!node_cnt[i])
277                         break;
278
279                 if (node_cnt[i] > rr_num) {
280                         *rr_prio = i;
281                         rr_num = node_cnt[i];
282                 }
283         }
284
285         /* RR group of single RR child is considered as SP */
286         if (rr_num == 1) {
287                 *rr_prio = 0xF;
288                 rr_num = 0;
289         }
290
291         /* Max prio will be returned only when we have non zero prio
292          * or if a parent has single child.
293          */
294         if (i > 1 || (children == 1))
295                 *max_prio = i - 1;
296         return rr_num;
297 }
298
299 static uint16_t
300 nix_tm_max_prio(struct nix *nix, uint16_t hw_lvl)
301 {
302         if (hw_lvl >= NIX_TXSCH_LVL_CNT)
303                 return 0;
304
305         /* MDQ does not support SP */
306         if (hw_lvl == NIX_TXSCH_LVL_MDQ)
307                 return 0;
308
309         /* PF's TL1 with VF's enabled does not support SP */
310         if (hw_lvl == NIX_TXSCH_LVL_TL1 && (!nix_tm_have_tl1_access(nix) ||
311                                             (nix->tm_flags & NIX_TM_TL1_NO_SP)))
312                 return 0;
313
314         return NIX_TM_TLX_SP_PRIO_MAX - 1;
315 }
316
317 int
318 nix_tm_validate_prio(struct nix *nix, uint32_t lvl, uint32_t parent_id,
319                      uint32_t priority, enum roc_nix_tm_tree tree)
320 {
321         uint8_t priorities[NIX_TM_TLX_SP_PRIO_MAX];
322         struct nix_tm_node_list *list;
323         struct nix_tm_node *node;
324         uint32_t rr_num = 0;
325         int i;
326
327         list = nix_tm_node_list(nix, tree);
328         /* Validate priority against max */
329         if (priority > nix_tm_max_prio(nix, nix_tm_lvl2nix(nix, lvl - 1)))
330                 return NIX_ERR_TM_PRIO_EXCEEDED;
331
332         if (parent_id == ROC_NIX_TM_NODE_ID_INVALID)
333                 return 0;
334
335         memset(priorities, 0, sizeof(priorities));
336         priorities[priority] = 1;
337
338         TAILQ_FOREACH(node, list, node) {
339                 if (!node->parent)
340                         continue;
341
342                 if (node->parent->id != parent_id)
343                         continue;
344
345                 priorities[node->priority]++;
346         }
347
348         for (i = 0; i < NIX_TM_TLX_SP_PRIO_MAX; i++)
349                 if (priorities[i] > 1)
350                         rr_num++;
351
352         /* At max, one rr groups per parent */
353         if (rr_num > 1)
354                 return NIX_ERR_TM_MULTIPLE_RR_GROUPS;
355
356         /* Check for previous priority to avoid holes in priorities */
357         if (priority && !priorities[priority - 1])
358                 return NIX_ERR_TM_PRIO_ORDER;
359
360         return 0;
361 }
362
363 bool
364 nix_tm_child_res_valid(struct nix_tm_node_list *list,
365                        struct nix_tm_node *parent)
366 {
367         struct nix_tm_node *child;
368
369         TAILQ_FOREACH(child, list, node) {
370                 if (child->parent != parent)
371                         continue;
372                 if (!(child->flags & NIX_TM_NODE_HWRES))
373                         return false;
374         }
375         return true;
376 }
377
378 uint8_t
379 nix_tm_tl1_default_prep(uint32_t schq, volatile uint64_t *reg,
380                         volatile uint64_t *regval)
381 {
382         uint8_t k = 0;
383
384         /*
385          * Default config for TL1.
386          * For VF this is always ignored.
387          */
388         plt_tm_dbg("Default config for main root %s(%u)",
389                    nix_tm_hwlvl2str(NIX_TXSCH_LVL_TL1), schq);
390
391         /* Set DWRR quantum */
392         reg[k] = NIX_AF_TL1X_SCHEDULE(schq);
393         regval[k] = NIX_TM_TL1_DFLT_RR_QTM;
394         k++;
395
396         reg[k] = NIX_AF_TL1X_TOPOLOGY(schq);
397         regval[k] = (NIX_TM_TL1_DFLT_RR_PRIO << 1);
398         k++;
399
400         reg[k] = NIX_AF_TL1X_CIR(schq);
401         regval[k] = 0;
402         k++;
403
404         return k;
405 }
406
407 uint8_t
408 nix_tm_topology_reg_prep(struct nix *nix, struct nix_tm_node *node,
409                          volatile uint64_t *reg, volatile uint64_t *regval,
410                          volatile uint64_t *regval_mask)
411 {
412         struct roc_nix *roc_nix = nix_priv_to_roc_nix(nix);
413         uint8_t k = 0, hw_lvl, parent_lvl;
414         uint64_t parent = 0, child = 0;
415         enum roc_nix_tm_tree tree;
416         uint32_t rr_prio, schq;
417         uint16_t link, relchan;
418
419         tree = node->tree;
420         schq = node->hw_id;
421         hw_lvl = node->hw_lvl;
422         parent_lvl = hw_lvl + 1;
423         rr_prio = node->rr_prio;
424
425         /* Root node will not have a parent node */
426         if (hw_lvl == nix->tm_root_lvl)
427                 parent = node->parent_hw_id;
428         else
429                 parent = node->parent->hw_id;
430
431         link = nix->tx_link;
432         relchan = nix_tm_relchan_get(nix);
433
434         if (hw_lvl != NIX_TXSCH_LVL_SMQ)
435                 child = nix_tm_find_prio_anchor(nix, node->id, tree);
436
437         /* Override default rr_prio when TL1
438          * Static Priority is disabled
439          */
440         if (hw_lvl == NIX_TXSCH_LVL_TL1 && nix->tm_flags & NIX_TM_TL1_NO_SP) {
441                 rr_prio = NIX_TM_TL1_DFLT_RR_PRIO;
442                 child = 0;
443         }
444
445         plt_tm_dbg("Topology config node %s(%u)->%s(%" PRIu64 ") lvl %u, id %u"
446                    " prio_anchor %" PRIu64 " rr_prio %u (%p)",
447                    nix_tm_hwlvl2str(hw_lvl), schq, nix_tm_hwlvl2str(parent_lvl),
448                    parent, node->lvl, node->id, child, rr_prio, node);
449
450         /* Prepare Topology and Link config */
451         switch (hw_lvl) {
452         case NIX_TXSCH_LVL_SMQ:
453
454                 /* Set xoff which will be cleared later */
455                 reg[k] = NIX_AF_SMQX_CFG(schq);
456                 regval[k] = (BIT_ULL(50) | NIX_MIN_HW_FRS |
457                              ((nix->mtu & 0xFFFF) << 8));
458                 /* Maximum Vtag insertion size as a multiple of four bytes */
459                 if (roc_nix->hw_vlan_ins)
460                         regval[k] |= (0x2ULL << 36);
461                 regval_mask[k] = ~(BIT_ULL(50) | GENMASK_ULL(6, 0) |
462                                    GENMASK_ULL(23, 8) | GENMASK_ULL(38, 36));
463                 k++;
464
465                 /* Parent and schedule conf */
466                 reg[k] = NIX_AF_MDQX_PARENT(schq);
467                 regval[k] = parent << 16;
468                 k++;
469
470                 break;
471         case NIX_TXSCH_LVL_TL4:
472                 /* Parent and schedule conf */
473                 reg[k] = NIX_AF_TL4X_PARENT(schq);
474                 regval[k] = parent << 16;
475                 k++;
476
477                 reg[k] = NIX_AF_TL4X_TOPOLOGY(schq);
478                 regval[k] = (child << 32) | (rr_prio << 1);
479                 k++;
480
481                 /* Configure TL4 to send to SDP channel instead of CGX/LBK */
482                 if (nix->sdp_link) {
483                         reg[k] = NIX_AF_TL4X_SDP_LINK_CFG(schq);
484                         regval[k] = BIT_ULL(12);
485                         k++;
486                 }
487                 break;
488         case NIX_TXSCH_LVL_TL3:
489                 /* Parent and schedule conf */
490                 reg[k] = NIX_AF_TL3X_PARENT(schq);
491                 regval[k] = parent << 16;
492                 k++;
493
494                 reg[k] = NIX_AF_TL3X_TOPOLOGY(schq);
495                 regval[k] = (child << 32) | (rr_prio << 1);
496                 k++;
497
498                 /* Link configuration */
499                 if (!nix->sdp_link &&
500                     nix->tm_link_cfg_lvl == NIX_TXSCH_LVL_TL3) {
501                         reg[k] = NIX_AF_TL3_TL2X_LINKX_CFG(schq, link);
502                         regval[k] = BIT_ULL(12) | relchan;
503                         k++;
504                 }
505
506                 break;
507         case NIX_TXSCH_LVL_TL2:
508                 /* Parent and schedule conf */
509                 reg[k] = NIX_AF_TL2X_PARENT(schq);
510                 regval[k] = parent << 16;
511                 k++;
512
513                 reg[k] = NIX_AF_TL2X_TOPOLOGY(schq);
514                 regval[k] = (child << 32) | (rr_prio << 1);
515                 k++;
516
517                 /* Link configuration */
518                 if (!nix->sdp_link &&
519                     nix->tm_link_cfg_lvl == NIX_TXSCH_LVL_TL2) {
520                         reg[k] = NIX_AF_TL3_TL2X_LINKX_CFG(schq, link);
521                         regval[k] = BIT_ULL(12) | relchan;
522                         k++;
523                 }
524
525                 break;
526         case NIX_TXSCH_LVL_TL1:
527                 reg[k] = NIX_AF_TL1X_TOPOLOGY(schq);
528                 regval[k] = (child << 32) | (rr_prio << 1 /*RR_PRIO*/);
529                 k++;
530
531                 break;
532         }
533
534         return k;
535 }
536
537 uint8_t
538 nix_tm_sched_reg_prep(struct nix *nix, struct nix_tm_node *node,
539                       volatile uint64_t *reg, volatile uint64_t *regval)
540 {
541         uint64_t strict_prio = node->priority;
542         uint32_t hw_lvl = node->hw_lvl;
543         uint32_t schq = node->hw_id;
544         uint64_t rr_quantum;
545         uint8_t k = 0;
546
547         rr_quantum = nix_tm_weight_to_rr_quantum(node->weight);
548
549         /* For children to root, strict prio is default if either
550          * device root is TL2 or TL1 Static Priority is disabled.
551          */
552         if (hw_lvl == NIX_TXSCH_LVL_TL2 &&
553             (!nix_tm_have_tl1_access(nix) || nix->tm_flags & NIX_TM_TL1_NO_SP))
554                 strict_prio = NIX_TM_TL1_DFLT_RR_PRIO;
555
556         plt_tm_dbg("Schedule config node %s(%u) lvl %u id %u, "
557                    "prio 0x%" PRIx64 ", rr_quantum 0x%" PRIx64 " (%p)",
558                    nix_tm_hwlvl2str(node->hw_lvl), schq, node->lvl, node->id,
559                    strict_prio, rr_quantum, node);
560
561         switch (hw_lvl) {
562         case NIX_TXSCH_LVL_SMQ:
563                 reg[k] = NIX_AF_MDQX_SCHEDULE(schq);
564                 regval[k] = (strict_prio << 24) | rr_quantum;
565                 k++;
566
567                 break;
568         case NIX_TXSCH_LVL_TL4:
569                 reg[k] = NIX_AF_TL4X_SCHEDULE(schq);
570                 regval[k] = (strict_prio << 24) | rr_quantum;
571                 k++;
572
573                 break;
574         case NIX_TXSCH_LVL_TL3:
575                 reg[k] = NIX_AF_TL3X_SCHEDULE(schq);
576                 regval[k] = (strict_prio << 24) | rr_quantum;
577                 k++;
578
579                 break;
580         case NIX_TXSCH_LVL_TL2:
581                 reg[k] = NIX_AF_TL2X_SCHEDULE(schq);
582                 regval[k] = (strict_prio << 24) | rr_quantum;
583                 k++;
584
585                 break;
586         case NIX_TXSCH_LVL_TL1:
587                 reg[k] = NIX_AF_TL1X_SCHEDULE(schq);
588                 regval[k] = rr_quantum;
589                 k++;
590
591                 break;
592         }
593
594         return k;
595 }
596
597 uint8_t
598 nix_tm_shaper_reg_prep(struct nix_tm_node *node,
599                        struct nix_tm_shaper_profile *profile,
600                        volatile uint64_t *reg, volatile uint64_t *regval)
601 {
602         struct nix_tm_shaper_data cir, pir;
603         uint32_t schq = node->hw_id;
604         uint64_t adjust = 0;
605         uint8_t k = 0;
606
607         memset(&cir, 0, sizeof(cir));
608         memset(&pir, 0, sizeof(pir));
609         nix_tm_shaper_conf_get(profile, &cir, &pir);
610
611         if (node->pkt_mode)
612                 adjust = 1;
613         else if (profile)
614                 adjust = profile->pkt_len_adj;
615
616         plt_tm_dbg("Shaper config node %s(%u) lvl %u id %u, "
617                    "pir %" PRIu64 "(%" PRIu64 "B),"
618                    " cir %" PRIu64 "(%" PRIu64 "B)"
619                    "adjust 0x%" PRIx64 "(pktmode %u) (%p)",
620                    nix_tm_hwlvl2str(node->hw_lvl), schq, node->lvl, node->id,
621                    pir.rate, pir.burst, cir.rate, cir.burst, adjust,
622                    node->pkt_mode, node);
623
624         switch (node->hw_lvl) {
625         case NIX_TXSCH_LVL_SMQ:
626                 /* Configure PIR, CIR */
627                 reg[k] = NIX_AF_MDQX_PIR(schq);
628                 regval[k] = (pir.rate && pir.burst) ?
629                                           (nix_tm_shaper2regval(&pir) | 1) :
630                                           0;
631                 k++;
632
633                 reg[k] = NIX_AF_MDQX_CIR(schq);
634                 regval[k] = (cir.rate && cir.burst) ?
635                                           (nix_tm_shaper2regval(&cir) | 1) :
636                                           0;
637                 k++;
638
639                 /* Configure RED ALG */
640                 reg[k] = NIX_AF_MDQX_SHAPE(schq);
641                 regval[k] = (adjust | (uint64_t)node->red_algo << 9 |
642                              (uint64_t)node->pkt_mode << 24);
643                 k++;
644                 break;
645         case NIX_TXSCH_LVL_TL4:
646                 /* Configure PIR, CIR */
647                 reg[k] = NIX_AF_TL4X_PIR(schq);
648                 regval[k] = (pir.rate && pir.burst) ?
649                                           (nix_tm_shaper2regval(&pir) | 1) :
650                                           0;
651                 k++;
652
653                 reg[k] = NIX_AF_TL4X_CIR(schq);
654                 regval[k] = (cir.rate && cir.burst) ?
655                                           (nix_tm_shaper2regval(&cir) | 1) :
656                                           0;
657                 k++;
658
659                 /* Configure RED algo */
660                 reg[k] = NIX_AF_TL4X_SHAPE(schq);
661                 regval[k] = (adjust | (uint64_t)node->red_algo << 9 |
662                              (uint64_t)node->pkt_mode << 24);
663                 k++;
664                 break;
665         case NIX_TXSCH_LVL_TL3:
666                 /* Configure PIR, CIR */
667                 reg[k] = NIX_AF_TL3X_PIR(schq);
668                 regval[k] = (pir.rate && pir.burst) ?
669                                           (nix_tm_shaper2regval(&pir) | 1) :
670                                           0;
671                 k++;
672
673                 reg[k] = NIX_AF_TL3X_CIR(schq);
674                 regval[k] = (cir.rate && cir.burst) ?
675                                           (nix_tm_shaper2regval(&cir) | 1) :
676                                           0;
677                 k++;
678
679                 /* Configure RED algo */
680                 reg[k] = NIX_AF_TL3X_SHAPE(schq);
681                 regval[k] = (adjust | (uint64_t)node->red_algo << 9 |
682                              (uint64_t)node->pkt_mode);
683                 k++;
684
685                 break;
686         case NIX_TXSCH_LVL_TL2:
687                 /* Configure PIR, CIR */
688                 reg[k] = NIX_AF_TL2X_PIR(schq);
689                 regval[k] = (pir.rate && pir.burst) ?
690                                           (nix_tm_shaper2regval(&pir) | 1) :
691                                           0;
692                 k++;
693
694                 reg[k] = NIX_AF_TL2X_CIR(schq);
695                 regval[k] = (cir.rate && cir.burst) ?
696                                           (nix_tm_shaper2regval(&cir) | 1) :
697                                           0;
698                 k++;
699
700                 /* Configure RED algo */
701                 reg[k] = NIX_AF_TL2X_SHAPE(schq);
702                 regval[k] = (adjust | (uint64_t)node->red_algo << 9 |
703                              (uint64_t)node->pkt_mode << 24);
704                 k++;
705
706                 break;
707         case NIX_TXSCH_LVL_TL1:
708                 /* Configure CIR */
709                 reg[k] = NIX_AF_TL1X_CIR(schq);
710                 regval[k] = (cir.rate && cir.burst) ?
711                                           (nix_tm_shaper2regval(&cir) | 1) :
712                                           0;
713                 k++;
714
715                 /* Configure length disable and adjust */
716                 reg[k] = NIX_AF_TL1X_SHAPE(schq);
717                 regval[k] = (adjust | (uint64_t)node->pkt_mode << 24);
718                 k++;
719                 break;
720         }
721
722         return k;
723 }
724
725 uint8_t
726 nix_tm_sw_xoff_prep(struct nix_tm_node *node, bool enable,
727                     volatile uint64_t *reg, volatile uint64_t *regval)
728 {
729         uint32_t hw_lvl = node->hw_lvl;
730         uint32_t schq = node->hw_id;
731         uint8_t k = 0;
732
733         plt_tm_dbg("sw xoff config node %s(%u) lvl %u id %u, enable %u (%p)",
734                    nix_tm_hwlvl2str(hw_lvl), schq, node->lvl, node->id, enable,
735                    node);
736
737         regval[k] = enable;
738
739         switch (hw_lvl) {
740         case NIX_TXSCH_LVL_MDQ:
741                 reg[k] = NIX_AF_MDQX_SW_XOFF(schq);
742                 k++;
743                 break;
744         case NIX_TXSCH_LVL_TL4:
745                 reg[k] = NIX_AF_TL4X_SW_XOFF(schq);
746                 k++;
747                 break;
748         case NIX_TXSCH_LVL_TL3:
749                 reg[k] = NIX_AF_TL3X_SW_XOFF(schq);
750                 k++;
751                 break;
752         case NIX_TXSCH_LVL_TL2:
753                 reg[k] = NIX_AF_TL2X_SW_XOFF(schq);
754                 k++;
755                 break;
756         case NIX_TXSCH_LVL_TL1:
757                 reg[k] = NIX_AF_TL1X_SW_XOFF(schq);
758                 k++;
759                 break;
760         default:
761                 break;
762         }
763
764         return k;
765 }
766
767 /* Search for min rate in topology */
768 uint64_t
769 nix_tm_shaper_profile_rate_min(struct nix *nix)
770 {
771         struct nix_tm_shaper_profile *profile;
772         uint64_t rate_min = 1E9; /* 1 Gbps */
773
774         TAILQ_FOREACH(profile, &nix->shaper_profile_list, shaper) {
775                 if (profile->peak.rate && profile->peak.rate < rate_min)
776                         rate_min = profile->peak.rate;
777
778                 if (profile->commit.rate && profile->commit.rate < rate_min)
779                         rate_min = profile->commit.rate;
780         }
781         return rate_min;
782 }
783
784 uint16_t
785 nix_tm_resource_avail(struct nix *nix, uint8_t hw_lvl, bool contig)
786 {
787         uint32_t pos = 0, start_pos = 0;
788         struct plt_bitmap *bmp;
789         uint16_t count = 0;
790         uint64_t slab = 0;
791
792         bmp = contig ? nix->schq_contig_bmp[hw_lvl] : nix->schq_bmp[hw_lvl];
793         plt_bitmap_scan_init(bmp);
794
795         if (!plt_bitmap_scan(bmp, &pos, &slab))
796                 return count;
797
798         /* Count bit set */
799         start_pos = pos;
800         do {
801                 count += __builtin_popcountll(slab);
802                 if (!plt_bitmap_scan(bmp, &pos, &slab))
803                         break;
804         } while (pos != start_pos);
805
806         return count;
807 }
808
809 uint16_t
810 nix_tm_resource_estimate(struct nix *nix, uint16_t *schq_contig, uint16_t *schq,
811                          enum roc_nix_tm_tree tree)
812 {
813         struct nix_tm_node_list *list;
814         uint8_t contig_cnt, hw_lvl;
815         struct nix_tm_node *parent;
816         uint16_t cnt = 0, avail;
817
818         list = nix_tm_node_list(nix, tree);
819         /* Walk through parents from TL1..TL4 */
820         for (hw_lvl = NIX_TXSCH_LVL_TL1; hw_lvl > 0; hw_lvl--) {
821                 TAILQ_FOREACH(parent, list, node) {
822                         if (hw_lvl != parent->hw_lvl)
823                                 continue;
824
825                         /* Skip accounting for children whose
826                          * parent does not indicate so.
827                          */
828                         if (!parent->child_realloc)
829                                 continue;
830
831                         /* Count children needed */
832                         schq[hw_lvl - 1] += parent->rr_num;
833                         if (parent->max_prio != UINT32_MAX) {
834                                 contig_cnt = parent->max_prio + 1;
835                                 schq_contig[hw_lvl - 1] += contig_cnt;
836                                 /* When we have SP + DWRR at a parent,
837                                  * we will always have a spare schq at rr prio
838                                  * location in contiguous queues. Hence reduce
839                                  * discontiguous count by 1.
840                                  */
841                                 if (parent->max_prio > 0 && parent->rr_num)
842                                         schq[hw_lvl - 1] -= 1;
843                         }
844                 }
845         }
846
847         schq[nix->tm_root_lvl] = 1;
848         if (!nix_tm_have_tl1_access(nix))
849                 schq[NIX_TXSCH_LVL_TL1] = 1;
850
851         /* Now check for existing resources */
852         for (hw_lvl = 0; hw_lvl < NIX_TXSCH_LVL_CNT; hw_lvl++) {
853                 avail = nix_tm_resource_avail(nix, hw_lvl, false);
854                 if (schq[hw_lvl] <= avail)
855                         schq[hw_lvl] = 0;
856                 else
857                         schq[hw_lvl] -= avail;
858
859                 /* For contiguous queues, realloc everything */
860                 avail = nix_tm_resource_avail(nix, hw_lvl, true);
861                 if (schq_contig[hw_lvl] <= avail)
862                         schq_contig[hw_lvl] = 0;
863
864                 cnt += schq[hw_lvl];
865                 cnt += schq_contig[hw_lvl];
866
867                 plt_tm_dbg("Estimate resources needed for %s: dis %u cont %u",
868                            nix_tm_hwlvl2str(hw_lvl), schq[hw_lvl],
869                            schq_contig[hw_lvl]);
870         }
871
872         return cnt;
873 }
874
875 uint16_t
876 roc_nix_tm_leaf_cnt(struct roc_nix *roc_nix)
877 {
878         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
879         struct nix_tm_node_list *list;
880         struct nix_tm_node *node;
881         uint16_t leaf_cnt = 0;
882
883         /* Count leafs only in user list */
884         list = nix_tm_node_list(nix, ROC_NIX_TM_USER);
885         TAILQ_FOREACH(node, list, node) {
886                 if (node->id < nix->nb_tx_queues)
887                         leaf_cnt++;
888         }
889
890         return leaf_cnt;
891 }
892
893 int
894 roc_nix_tm_node_lvl(struct roc_nix *roc_nix, uint32_t node_id)
895 {
896         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
897         struct nix_tm_node *node;
898
899         node = nix_tm_node_search(nix, node_id, ROC_NIX_TM_USER);
900         if (!node)
901                 return NIX_ERR_TM_INVALID_NODE;
902
903         return node->lvl;
904 }
905
906 struct roc_nix_tm_node *
907 roc_nix_tm_node_get(struct roc_nix *roc_nix, uint32_t node_id)
908 {
909         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
910         struct nix_tm_node *node;
911
912         node = nix_tm_node_search(nix, node_id, ROC_NIX_TM_USER);
913         return (struct roc_nix_tm_node *)node;
914 }
915
916 struct roc_nix_tm_node *
917 roc_nix_tm_node_next(struct roc_nix *roc_nix, struct roc_nix_tm_node *__prev)
918 {
919         struct nix_tm_node *prev = (struct nix_tm_node *)__prev;
920         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
921         struct nix_tm_node_list *list;
922
923         list = nix_tm_node_list(nix, ROC_NIX_TM_USER);
924
925         /* HEAD of the list */
926         if (!prev)
927                 return (struct roc_nix_tm_node *)TAILQ_FIRST(list);
928
929         /* Next entry */
930         if (prev->tree != ROC_NIX_TM_USER)
931                 return NULL;
932
933         return (struct roc_nix_tm_node *)TAILQ_NEXT(prev, node);
934 }
935
936 struct roc_nix_tm_shaper_profile *
937 roc_nix_tm_shaper_profile_get(struct roc_nix *roc_nix, uint32_t profile_id)
938 {
939         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
940         struct nix_tm_shaper_profile *profile;
941
942         profile = nix_tm_shaper_profile_search(nix, profile_id);
943         return (struct roc_nix_tm_shaper_profile *)profile;
944 }
945
946 struct roc_nix_tm_shaper_profile *
947 roc_nix_tm_shaper_profile_next(struct roc_nix *roc_nix,
948                                struct roc_nix_tm_shaper_profile *__prev)
949 {
950         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
951         struct nix_tm_shaper_profile_list *list;
952         struct nix_tm_shaper_profile *prev;
953
954         prev = (struct nix_tm_shaper_profile *)__prev;
955         list = &nix->shaper_profile_list;
956
957         /* HEAD of the list */
958         if (!prev)
959                 return (struct roc_nix_tm_shaper_profile *)TAILQ_FIRST(list);
960
961         return (struct roc_nix_tm_shaper_profile *)TAILQ_NEXT(prev, shaper);
962 }
963
964 struct nix_tm_node *
965 nix_tm_node_alloc(void)
966 {
967         struct nix_tm_node *node;
968
969         node = plt_zmalloc(sizeof(struct nix_tm_node), 0);
970         if (!node)
971                 return NULL;
972
973         node->free_fn = plt_free;
974         return node;
975 }
976
977 void
978 nix_tm_node_free(struct nix_tm_node *node)
979 {
980         if (!node || node->free_fn == NULL)
981                 return;
982
983         (node->free_fn)(node);
984 }
985
986 struct nix_tm_shaper_profile *
987 nix_tm_shaper_profile_alloc(void)
988 {
989         struct nix_tm_shaper_profile *profile;
990
991         profile = plt_zmalloc(sizeof(struct nix_tm_shaper_profile), 0);
992         if (!profile)
993                 return NULL;
994
995         profile->free_fn = plt_free;
996         return profile;
997 }
998
999 void
1000 nix_tm_shaper_profile_free(struct nix_tm_shaper_profile *profile)
1001 {
1002         if (!profile || !profile->free_fn)
1003                 return;
1004
1005         (profile->free_fn)(profile);
1006 }
1007
1008 int
1009 roc_nix_tm_node_stats_get(struct roc_nix *roc_nix, uint32_t node_id, bool clear,
1010                           struct roc_nix_tm_node_stats *n_stats)
1011 {
1012         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
1013         struct mbox *mbox = (&nix->dev)->mbox;
1014         struct nix_txschq_config *req, *rsp;
1015         struct nix_tm_node *node;
1016         uint32_t schq;
1017         int rc, i;
1018
1019         node = nix_tm_node_search(nix, node_id, ROC_NIX_TM_USER);
1020         if (!node)
1021                 return NIX_ERR_TM_INVALID_NODE;
1022
1023         if (node->hw_lvl != NIX_TXSCH_LVL_TL1)
1024                 return NIX_ERR_OP_NOTSUP;
1025
1026         schq = node->hw_id;
1027         /* Skip fetch if not requested */
1028         if (!n_stats)
1029                 goto clear_stats;
1030
1031         memset(n_stats, 0, sizeof(struct roc_nix_tm_node_stats));
1032         /* Check if node has HW resource */
1033         if (!(node->flags & NIX_TM_NODE_HWRES))
1034                 return 0;
1035
1036         req = mbox_alloc_msg_nix_txschq_cfg(mbox);
1037         req->read = 1;
1038         req->lvl = NIX_TXSCH_LVL_TL1;
1039
1040         i = 0;
1041         req->reg[i++] = NIX_AF_TL1X_DROPPED_PACKETS(schq);
1042         req->reg[i++] = NIX_AF_TL1X_DROPPED_BYTES(schq);
1043         req->reg[i++] = NIX_AF_TL1X_GREEN_PACKETS(schq);
1044         req->reg[i++] = NIX_AF_TL1X_GREEN_BYTES(schq);
1045         req->reg[i++] = NIX_AF_TL1X_YELLOW_PACKETS(schq);
1046         req->reg[i++] = NIX_AF_TL1X_YELLOW_BYTES(schq);
1047         req->reg[i++] = NIX_AF_TL1X_RED_PACKETS(schq);
1048         req->reg[i++] = NIX_AF_TL1X_RED_BYTES(schq);
1049         req->num_regs = i;
1050
1051         rc = mbox_process_msg(mbox, (void **)&rsp);
1052         if (rc)
1053                 return rc;
1054
1055         /* Return stats */
1056         n_stats->stats[ROC_NIX_TM_NODE_PKTS_DROPPED] = rsp->regval[0];
1057         n_stats->stats[ROC_NIX_TM_NODE_BYTES_DROPPED] = rsp->regval[1];
1058         n_stats->stats[ROC_NIX_TM_NODE_GREEN_PKTS] = rsp->regval[2];
1059         n_stats->stats[ROC_NIX_TM_NODE_GREEN_BYTES] = rsp->regval[3];
1060         n_stats->stats[ROC_NIX_TM_NODE_YELLOW_PKTS] = rsp->regval[4];
1061         n_stats->stats[ROC_NIX_TM_NODE_YELLOW_BYTES] = rsp->regval[5];
1062         n_stats->stats[ROC_NIX_TM_NODE_RED_PKTS] = rsp->regval[6];
1063         n_stats->stats[ROC_NIX_TM_NODE_RED_BYTES] = rsp->regval[7];
1064
1065 clear_stats:
1066         if (!clear)
1067                 return 0;
1068
1069         /* Clear all the stats */
1070         req = mbox_alloc_msg_nix_txschq_cfg(mbox);
1071         req->lvl = NIX_TXSCH_LVL_TL1;
1072         i = 0;
1073         req->reg[i++] = NIX_AF_TL1X_DROPPED_PACKETS(schq);
1074         req->reg[i++] = NIX_AF_TL1X_DROPPED_BYTES(schq);
1075         req->reg[i++] = NIX_AF_TL1X_GREEN_PACKETS(schq);
1076         req->reg[i++] = NIX_AF_TL1X_GREEN_BYTES(schq);
1077         req->reg[i++] = NIX_AF_TL1X_YELLOW_PACKETS(schq);
1078         req->reg[i++] = NIX_AF_TL1X_YELLOW_BYTES(schq);
1079         req->reg[i++] = NIX_AF_TL1X_RED_PACKETS(schq);
1080         req->reg[i++] = NIX_AF_TL1X_RED_BYTES(schq);
1081         req->num_regs = i;
1082
1083         return mbox_process_msg(mbox, (void **)&rsp);
1084 }