bus/pci: support IOVA as VA in PowerVM LPARs
[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         uint8_t k = 0, hw_lvl, parent_lvl;
413         uint64_t parent = 0, child = 0;
414         enum roc_nix_tm_tree tree;
415         uint32_t rr_prio, schq;
416         uint16_t link, relchan;
417
418         tree = node->tree;
419         schq = node->hw_id;
420         hw_lvl = node->hw_lvl;
421         parent_lvl = hw_lvl + 1;
422         rr_prio = node->rr_prio;
423
424         /* Root node will not have a parent node */
425         if (hw_lvl == nix->tm_root_lvl)
426                 parent = node->parent_hw_id;
427         else
428                 parent = node->parent->hw_id;
429
430         link = nix->tx_link;
431         relchan = nix_tm_relchan_get(nix);
432
433         if (hw_lvl != NIX_TXSCH_LVL_SMQ)
434                 child = nix_tm_find_prio_anchor(nix, node->id, tree);
435
436         /* Override default rr_prio when TL1
437          * Static Priority is disabled
438          */
439         if (hw_lvl == NIX_TXSCH_LVL_TL1 && nix->tm_flags & NIX_TM_TL1_NO_SP) {
440                 rr_prio = NIX_TM_TL1_DFLT_RR_PRIO;
441                 child = 0;
442         }
443
444         plt_tm_dbg("Topology config node %s(%u)->%s(%" PRIu64 ") lvl %u, id %u"
445                    " prio_anchor %" PRIu64 " rr_prio %u (%p)",
446                    nix_tm_hwlvl2str(hw_lvl), schq, nix_tm_hwlvl2str(parent_lvl),
447                    parent, node->lvl, node->id, child, rr_prio, node);
448
449         /* Prepare Topology and Link config */
450         switch (hw_lvl) {
451         case NIX_TXSCH_LVL_SMQ:
452
453                 /* Set xoff which will be cleared later */
454                 reg[k] = NIX_AF_SMQX_CFG(schq);
455                 regval[k] = (BIT_ULL(50) | NIX_MIN_HW_FRS |
456                              ((nix->mtu & 0xFFFF) << 8));
457                 regval_mask[k] =
458                         ~(BIT_ULL(50) | GENMASK_ULL(6, 0) | GENMASK_ULL(23, 8));
459                 k++;
460
461                 /* Parent and schedule conf */
462                 reg[k] = NIX_AF_MDQX_PARENT(schq);
463                 regval[k] = parent << 16;
464                 k++;
465
466                 break;
467         case NIX_TXSCH_LVL_TL4:
468                 /* Parent and schedule conf */
469                 reg[k] = NIX_AF_TL4X_PARENT(schq);
470                 regval[k] = parent << 16;
471                 k++;
472
473                 reg[k] = NIX_AF_TL4X_TOPOLOGY(schq);
474                 regval[k] = (child << 32) | (rr_prio << 1);
475                 k++;
476
477                 /* Configure TL4 to send to SDP channel instead of CGX/LBK */
478                 if (nix->sdp_link) {
479                         reg[k] = NIX_AF_TL4X_SDP_LINK_CFG(schq);
480                         regval[k] = BIT_ULL(12);
481                         k++;
482                 }
483                 break;
484         case NIX_TXSCH_LVL_TL3:
485                 /* Parent and schedule conf */
486                 reg[k] = NIX_AF_TL3X_PARENT(schq);
487                 regval[k] = parent << 16;
488                 k++;
489
490                 reg[k] = NIX_AF_TL3X_TOPOLOGY(schq);
491                 regval[k] = (child << 32) | (rr_prio << 1);
492                 k++;
493
494                 /* Link configuration */
495                 if (!nix->sdp_link &&
496                     nix->tm_link_cfg_lvl == NIX_TXSCH_LVL_TL3) {
497                         reg[k] = NIX_AF_TL3_TL2X_LINKX_CFG(schq, link);
498                         regval[k] = BIT_ULL(12) | relchan;
499                         k++;
500                 }
501
502                 break;
503         case NIX_TXSCH_LVL_TL2:
504                 /* Parent and schedule conf */
505                 reg[k] = NIX_AF_TL2X_PARENT(schq);
506                 regval[k] = parent << 16;
507                 k++;
508
509                 reg[k] = NIX_AF_TL2X_TOPOLOGY(schq);
510                 regval[k] = (child << 32) | (rr_prio << 1);
511                 k++;
512
513                 /* Link configuration */
514                 if (!nix->sdp_link &&
515                     nix->tm_link_cfg_lvl == NIX_TXSCH_LVL_TL2) {
516                         reg[k] = NIX_AF_TL3_TL2X_LINKX_CFG(schq, link);
517                         regval[k] = BIT_ULL(12) | relchan;
518                         k++;
519                 }
520
521                 break;
522         case NIX_TXSCH_LVL_TL1:
523                 reg[k] = NIX_AF_TL1X_TOPOLOGY(schq);
524                 regval[k] = (child << 32) | (rr_prio << 1 /*RR_PRIO*/);
525                 k++;
526
527                 break;
528         }
529
530         return k;
531 }
532
533 uint8_t
534 nix_tm_sched_reg_prep(struct nix *nix, struct nix_tm_node *node,
535                       volatile uint64_t *reg, volatile uint64_t *regval)
536 {
537         uint64_t strict_prio = node->priority;
538         uint32_t hw_lvl = node->hw_lvl;
539         uint32_t schq = node->hw_id;
540         uint64_t rr_quantum;
541         uint8_t k = 0;
542
543         rr_quantum = nix_tm_weight_to_rr_quantum(node->weight);
544
545         /* For children to root, strict prio is default if either
546          * device root is TL2 or TL1 Static Priority is disabled.
547          */
548         if (hw_lvl == NIX_TXSCH_LVL_TL2 &&
549             (!nix_tm_have_tl1_access(nix) || nix->tm_flags & NIX_TM_TL1_NO_SP))
550                 strict_prio = NIX_TM_TL1_DFLT_RR_PRIO;
551
552         plt_tm_dbg("Schedule config node %s(%u) lvl %u id %u, "
553                    "prio 0x%" PRIx64 ", rr_quantum 0x%" PRIx64 " (%p)",
554                    nix_tm_hwlvl2str(node->hw_lvl), schq, node->lvl, node->id,
555                    strict_prio, rr_quantum, node);
556
557         switch (hw_lvl) {
558         case NIX_TXSCH_LVL_SMQ:
559                 reg[k] = NIX_AF_MDQX_SCHEDULE(schq);
560                 regval[k] = (strict_prio << 24) | rr_quantum;
561                 k++;
562
563                 break;
564         case NIX_TXSCH_LVL_TL4:
565                 reg[k] = NIX_AF_TL4X_SCHEDULE(schq);
566                 regval[k] = (strict_prio << 24) | rr_quantum;
567                 k++;
568
569                 break;
570         case NIX_TXSCH_LVL_TL3:
571                 reg[k] = NIX_AF_TL3X_SCHEDULE(schq);
572                 regval[k] = (strict_prio << 24) | rr_quantum;
573                 k++;
574
575                 break;
576         case NIX_TXSCH_LVL_TL2:
577                 reg[k] = NIX_AF_TL2X_SCHEDULE(schq);
578                 regval[k] = (strict_prio << 24) | rr_quantum;
579                 k++;
580
581                 break;
582         case NIX_TXSCH_LVL_TL1:
583                 reg[k] = NIX_AF_TL1X_SCHEDULE(schq);
584                 regval[k] = rr_quantum;
585                 k++;
586
587                 break;
588         }
589
590         return k;
591 }
592
593 uint8_t
594 nix_tm_shaper_reg_prep(struct nix_tm_node *node,
595                        struct nix_tm_shaper_profile *profile,
596                        volatile uint64_t *reg, volatile uint64_t *regval)
597 {
598         struct nix_tm_shaper_data cir, pir;
599         uint32_t schq = node->hw_id;
600         uint64_t adjust = 0;
601         uint8_t k = 0;
602
603         memset(&cir, 0, sizeof(cir));
604         memset(&pir, 0, sizeof(pir));
605         nix_tm_shaper_conf_get(profile, &cir, &pir);
606
607         if (node->pkt_mode)
608                 adjust = 1;
609         else if (profile)
610                 adjust = profile->pkt_len_adj;
611
612         plt_tm_dbg("Shaper config node %s(%u) lvl %u id %u, "
613                    "pir %" PRIu64 "(%" PRIu64 "B),"
614                    " cir %" PRIu64 "(%" PRIu64 "B)"
615                    "adjust 0x%" PRIx64 "(pktmode %u) (%p)",
616                    nix_tm_hwlvl2str(node->hw_lvl), schq, node->lvl, node->id,
617                    pir.rate, pir.burst, cir.rate, cir.burst, adjust,
618                    node->pkt_mode, node);
619
620         switch (node->hw_lvl) {
621         case NIX_TXSCH_LVL_SMQ:
622                 /* Configure PIR, CIR */
623                 reg[k] = NIX_AF_MDQX_PIR(schq);
624                 regval[k] = (pir.rate && pir.burst) ?
625                                           (nix_tm_shaper2regval(&pir) | 1) :
626                                           0;
627                 k++;
628
629                 reg[k] = NIX_AF_MDQX_CIR(schq);
630                 regval[k] = (cir.rate && cir.burst) ?
631                                           (nix_tm_shaper2regval(&cir) | 1) :
632                                           0;
633                 k++;
634
635                 /* Configure RED ALG */
636                 reg[k] = NIX_AF_MDQX_SHAPE(schq);
637                 regval[k] = (adjust | (uint64_t)node->red_algo << 9 |
638                              (uint64_t)node->pkt_mode << 24);
639                 k++;
640                 break;
641         case NIX_TXSCH_LVL_TL4:
642                 /* Configure PIR, CIR */
643                 reg[k] = NIX_AF_TL4X_PIR(schq);
644                 regval[k] = (pir.rate && pir.burst) ?
645                                           (nix_tm_shaper2regval(&pir) | 1) :
646                                           0;
647                 k++;
648
649                 reg[k] = NIX_AF_TL4X_CIR(schq);
650                 regval[k] = (cir.rate && cir.burst) ?
651                                           (nix_tm_shaper2regval(&cir) | 1) :
652                                           0;
653                 k++;
654
655                 /* Configure RED algo */
656                 reg[k] = NIX_AF_TL4X_SHAPE(schq);
657                 regval[k] = (adjust | (uint64_t)node->red_algo << 9 |
658                              (uint64_t)node->pkt_mode << 24);
659                 k++;
660                 break;
661         case NIX_TXSCH_LVL_TL3:
662                 /* Configure PIR, CIR */
663                 reg[k] = NIX_AF_TL3X_PIR(schq);
664                 regval[k] = (pir.rate && pir.burst) ?
665                                           (nix_tm_shaper2regval(&pir) | 1) :
666                                           0;
667                 k++;
668
669                 reg[k] = NIX_AF_TL3X_CIR(schq);
670                 regval[k] = (cir.rate && cir.burst) ?
671                                           (nix_tm_shaper2regval(&cir) | 1) :
672                                           0;
673                 k++;
674
675                 /* Configure RED algo */
676                 reg[k] = NIX_AF_TL3X_SHAPE(schq);
677                 regval[k] = (adjust | (uint64_t)node->red_algo << 9 |
678                              (uint64_t)node->pkt_mode);
679                 k++;
680
681                 break;
682         case NIX_TXSCH_LVL_TL2:
683                 /* Configure PIR, CIR */
684                 reg[k] = NIX_AF_TL2X_PIR(schq);
685                 regval[k] = (pir.rate && pir.burst) ?
686                                           (nix_tm_shaper2regval(&pir) | 1) :
687                                           0;
688                 k++;
689
690                 reg[k] = NIX_AF_TL2X_CIR(schq);
691                 regval[k] = (cir.rate && cir.burst) ?
692                                           (nix_tm_shaper2regval(&cir) | 1) :
693                                           0;
694                 k++;
695
696                 /* Configure RED algo */
697                 reg[k] = NIX_AF_TL2X_SHAPE(schq);
698                 regval[k] = (adjust | (uint64_t)node->red_algo << 9 |
699                              (uint64_t)node->pkt_mode << 24);
700                 k++;
701
702                 break;
703         case NIX_TXSCH_LVL_TL1:
704                 /* Configure CIR */
705                 reg[k] = NIX_AF_TL1X_CIR(schq);
706                 regval[k] = (cir.rate && cir.burst) ?
707                                           (nix_tm_shaper2regval(&cir) | 1) :
708                                           0;
709                 k++;
710
711                 /* Configure length disable and adjust */
712                 reg[k] = NIX_AF_TL1X_SHAPE(schq);
713                 regval[k] = (adjust | (uint64_t)node->pkt_mode << 24);
714                 k++;
715                 break;
716         }
717
718         return k;
719 }
720
721 uint8_t
722 nix_tm_sw_xoff_prep(struct nix_tm_node *node, bool enable,
723                     volatile uint64_t *reg, volatile uint64_t *regval)
724 {
725         uint32_t hw_lvl = node->hw_lvl;
726         uint32_t schq = node->hw_id;
727         uint8_t k = 0;
728
729         plt_tm_dbg("sw xoff config node %s(%u) lvl %u id %u, enable %u (%p)",
730                    nix_tm_hwlvl2str(hw_lvl), schq, node->lvl, node->id, enable,
731                    node);
732
733         regval[k] = enable;
734
735         switch (hw_lvl) {
736         case NIX_TXSCH_LVL_MDQ:
737                 reg[k] = NIX_AF_MDQX_SW_XOFF(schq);
738                 k++;
739                 break;
740         case NIX_TXSCH_LVL_TL4:
741                 reg[k] = NIX_AF_TL4X_SW_XOFF(schq);
742                 k++;
743                 break;
744         case NIX_TXSCH_LVL_TL3:
745                 reg[k] = NIX_AF_TL3X_SW_XOFF(schq);
746                 k++;
747                 break;
748         case NIX_TXSCH_LVL_TL2:
749                 reg[k] = NIX_AF_TL2X_SW_XOFF(schq);
750                 k++;
751                 break;
752         case NIX_TXSCH_LVL_TL1:
753                 reg[k] = NIX_AF_TL1X_SW_XOFF(schq);
754                 k++;
755                 break;
756         default:
757                 break;
758         }
759
760         return k;
761 }
762
763 /* Search for min rate in topology */
764 uint64_t
765 nix_tm_shaper_profile_rate_min(struct nix *nix)
766 {
767         struct nix_tm_shaper_profile *profile;
768         uint64_t rate_min = 1E9; /* 1 Gbps */
769
770         TAILQ_FOREACH(profile, &nix->shaper_profile_list, shaper) {
771                 if (profile->peak.rate && profile->peak.rate < rate_min)
772                         rate_min = profile->peak.rate;
773
774                 if (profile->commit.rate && profile->commit.rate < rate_min)
775                         rate_min = profile->commit.rate;
776         }
777         return rate_min;
778 }
779
780 uint16_t
781 nix_tm_resource_avail(struct nix *nix, uint8_t hw_lvl, bool contig)
782 {
783         uint32_t pos = 0, start_pos = 0;
784         struct plt_bitmap *bmp;
785         uint16_t count = 0;
786         uint64_t slab = 0;
787
788         bmp = contig ? nix->schq_contig_bmp[hw_lvl] : nix->schq_bmp[hw_lvl];
789         plt_bitmap_scan_init(bmp);
790
791         if (!plt_bitmap_scan(bmp, &pos, &slab))
792                 return count;
793
794         /* Count bit set */
795         start_pos = pos;
796         do {
797                 count += __builtin_popcountll(slab);
798                 if (!plt_bitmap_scan(bmp, &pos, &slab))
799                         break;
800         } while (pos != start_pos);
801
802         return count;
803 }
804
805 uint16_t
806 nix_tm_resource_estimate(struct nix *nix, uint16_t *schq_contig, uint16_t *schq,
807                          enum roc_nix_tm_tree tree)
808 {
809         struct nix_tm_node_list *list;
810         uint8_t contig_cnt, hw_lvl;
811         struct nix_tm_node *parent;
812         uint16_t cnt = 0, avail;
813
814         list = nix_tm_node_list(nix, tree);
815         /* Walk through parents from TL1..TL4 */
816         for (hw_lvl = NIX_TXSCH_LVL_TL1; hw_lvl > 0; hw_lvl--) {
817                 TAILQ_FOREACH(parent, list, node) {
818                         if (hw_lvl != parent->hw_lvl)
819                                 continue;
820
821                         /* Skip accounting for children whose
822                          * parent does not indicate so.
823                          */
824                         if (!parent->child_realloc)
825                                 continue;
826
827                         /* Count children needed */
828                         schq[hw_lvl - 1] += parent->rr_num;
829                         if (parent->max_prio != UINT32_MAX) {
830                                 contig_cnt = parent->max_prio + 1;
831                                 schq_contig[hw_lvl - 1] += contig_cnt;
832                                 /* When we have SP + DWRR at a parent,
833                                  * we will always have a spare schq at rr prio
834                                  * location in contiguous queues. Hence reduce
835                                  * discontiguous count by 1.
836                                  */
837                                 if (parent->max_prio > 0 && parent->rr_num)
838                                         schq[hw_lvl - 1] -= 1;
839                         }
840                 }
841         }
842
843         schq[nix->tm_root_lvl] = 1;
844         if (!nix_tm_have_tl1_access(nix))
845                 schq[NIX_TXSCH_LVL_TL1] = 1;
846
847         /* Now check for existing resources */
848         for (hw_lvl = 0; hw_lvl < NIX_TXSCH_LVL_CNT; hw_lvl++) {
849                 avail = nix_tm_resource_avail(nix, hw_lvl, false);
850                 if (schq[hw_lvl] <= avail)
851                         schq[hw_lvl] = 0;
852                 else
853                         schq[hw_lvl] -= avail;
854
855                 /* For contiguous queues, realloc everything */
856                 avail = nix_tm_resource_avail(nix, hw_lvl, true);
857                 if (schq_contig[hw_lvl] <= avail)
858                         schq_contig[hw_lvl] = 0;
859
860                 cnt += schq[hw_lvl];
861                 cnt += schq_contig[hw_lvl];
862
863                 plt_tm_dbg("Estimate resources needed for %s: dis %u cont %u",
864                            nix_tm_hwlvl2str(hw_lvl), schq[hw_lvl],
865                            schq_contig[hw_lvl]);
866         }
867
868         return cnt;
869 }
870
871 uint16_t
872 roc_nix_tm_leaf_cnt(struct roc_nix *roc_nix)
873 {
874         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
875         struct nix_tm_node_list *list;
876         struct nix_tm_node *node;
877         uint16_t leaf_cnt = 0;
878
879         /* Count leafs only in user list */
880         list = nix_tm_node_list(nix, ROC_NIX_TM_USER);
881         TAILQ_FOREACH(node, list, node) {
882                 if (node->id < nix->nb_tx_queues)
883                         leaf_cnt++;
884         }
885
886         return leaf_cnt;
887 }
888
889 int
890 roc_nix_tm_node_lvl(struct roc_nix *roc_nix, uint32_t node_id)
891 {
892         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
893         struct nix_tm_node *node;
894
895         node = nix_tm_node_search(nix, node_id, ROC_NIX_TM_USER);
896         if (!node)
897                 return NIX_ERR_TM_INVALID_NODE;
898
899         return node->lvl;
900 }
901
902 struct roc_nix_tm_node *
903 roc_nix_tm_node_get(struct roc_nix *roc_nix, uint32_t node_id)
904 {
905         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
906         struct nix_tm_node *node;
907
908         node = nix_tm_node_search(nix, node_id, ROC_NIX_TM_USER);
909         return (struct roc_nix_tm_node *)node;
910 }
911
912 struct roc_nix_tm_node *
913 roc_nix_tm_node_next(struct roc_nix *roc_nix, struct roc_nix_tm_node *__prev)
914 {
915         struct nix_tm_node *prev = (struct nix_tm_node *)__prev;
916         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
917         struct nix_tm_node_list *list;
918
919         list = nix_tm_node_list(nix, ROC_NIX_TM_USER);
920
921         /* HEAD of the list */
922         if (!prev)
923                 return (struct roc_nix_tm_node *)TAILQ_FIRST(list);
924
925         /* Next entry */
926         if (prev->tree != ROC_NIX_TM_USER)
927                 return NULL;
928
929         return (struct roc_nix_tm_node *)TAILQ_NEXT(prev, node);
930 }
931
932 struct roc_nix_tm_shaper_profile *
933 roc_nix_tm_shaper_profile_get(struct roc_nix *roc_nix, uint32_t profile_id)
934 {
935         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
936         struct nix_tm_shaper_profile *profile;
937
938         profile = nix_tm_shaper_profile_search(nix, profile_id);
939         return (struct roc_nix_tm_shaper_profile *)profile;
940 }
941
942 struct roc_nix_tm_shaper_profile *
943 roc_nix_tm_shaper_profile_next(struct roc_nix *roc_nix,
944                                struct roc_nix_tm_shaper_profile *__prev)
945 {
946         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
947         struct nix_tm_shaper_profile_list *list;
948         struct nix_tm_shaper_profile *prev;
949
950         prev = (struct nix_tm_shaper_profile *)__prev;
951         list = &nix->shaper_profile_list;
952
953         /* HEAD of the list */
954         if (!prev)
955                 return (struct roc_nix_tm_shaper_profile *)TAILQ_FIRST(list);
956
957         return (struct roc_nix_tm_shaper_profile *)TAILQ_NEXT(prev, shaper);
958 }
959
960 struct nix_tm_node *
961 nix_tm_node_alloc(void)
962 {
963         struct nix_tm_node *node;
964
965         node = plt_zmalloc(sizeof(struct nix_tm_node), 0);
966         if (!node)
967                 return NULL;
968
969         node->free_fn = plt_free;
970         return node;
971 }
972
973 void
974 nix_tm_node_free(struct nix_tm_node *node)
975 {
976         if (!node || node->free_fn == NULL)
977                 return;
978
979         (node->free_fn)(node);
980 }
981
982 struct nix_tm_shaper_profile *
983 nix_tm_shaper_profile_alloc(void)
984 {
985         struct nix_tm_shaper_profile *profile;
986
987         profile = plt_zmalloc(sizeof(struct nix_tm_shaper_profile), 0);
988         if (!profile)
989                 return NULL;
990
991         profile->free_fn = plt_free;
992         return profile;
993 }
994
995 void
996 nix_tm_shaper_profile_free(struct nix_tm_shaper_profile *profile)
997 {
998         if (!profile || !profile->free_fn)
999                 return;
1000
1001         (profile->free_fn)(profile);
1002 }