45de9f63477cc481a7d82052b484f26c5a622722
[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 uint16_t
9 nix_tm_lvl2nix_tl1_root(uint32_t lvl)
10 {
11         switch (lvl) {
12         case ROC_TM_LVL_ROOT:
13                 return NIX_TXSCH_LVL_TL1;
14         case ROC_TM_LVL_SCH1:
15                 return NIX_TXSCH_LVL_TL2;
16         case ROC_TM_LVL_SCH2:
17                 return NIX_TXSCH_LVL_TL3;
18         case ROC_TM_LVL_SCH3:
19                 return NIX_TXSCH_LVL_TL4;
20         case ROC_TM_LVL_SCH4:
21                 return NIX_TXSCH_LVL_SMQ;
22         default:
23                 return NIX_TXSCH_LVL_CNT;
24         }
25 }
26
27 uint16_t
28 nix_tm_lvl2nix_tl2_root(uint32_t lvl)
29 {
30         switch (lvl) {
31         case ROC_TM_LVL_ROOT:
32                 return NIX_TXSCH_LVL_TL2;
33         case ROC_TM_LVL_SCH1:
34                 return NIX_TXSCH_LVL_TL3;
35         case ROC_TM_LVL_SCH2:
36                 return NIX_TXSCH_LVL_TL4;
37         case ROC_TM_LVL_SCH3:
38                 return NIX_TXSCH_LVL_SMQ;
39         default:
40                 return NIX_TXSCH_LVL_CNT;
41         }
42 }
43
44 uint16_t
45 nix_tm_lvl2nix(struct nix *nix, uint32_t lvl)
46 {
47         if (nix_tm_have_tl1_access(nix))
48                 return nix_tm_lvl2nix_tl1_root(lvl);
49         else
50                 return nix_tm_lvl2nix_tl2_root(lvl);
51 }
52
53
54 struct nix_tm_shaper_profile *
55 nix_tm_shaper_profile_search(struct nix *nix, uint32_t id)
56 {
57         struct nix_tm_shaper_profile *profile;
58
59         TAILQ_FOREACH(profile, &nix->shaper_profile_list, shaper) {
60                 if (profile->id == id)
61                         return profile;
62         }
63         return NULL;
64 }
65
66 struct nix_tm_node *
67 nix_tm_node_search(struct nix *nix, uint32_t node_id, enum roc_nix_tm_tree tree)
68 {
69         struct nix_tm_node_list *list;
70         struct nix_tm_node *node;
71
72         list = nix_tm_node_list(nix, tree);
73         TAILQ_FOREACH(node, list, node) {
74                 if (node->id == node_id)
75                         return node;
76         }
77         return NULL;
78 }
79
80 uint64_t
81 nix_tm_shaper_rate_conv(uint64_t value, uint64_t *exponent_p,
82                         uint64_t *mantissa_p, uint64_t *div_exp_p)
83 {
84         uint64_t div_exp, exponent, mantissa;
85
86         /* Boundary checks */
87         if (value < NIX_TM_MIN_SHAPER_RATE || value > NIX_TM_MAX_SHAPER_RATE)
88                 return 0;
89
90         if (value <= NIX_TM_SHAPER_RATE(0, 0, 0)) {
91                 /* Calculate rate div_exp and mantissa using
92                  * the following formula:
93                  *
94                  * value = (2E6 * (256 + mantissa)
95                  *              / ((1 << div_exp) * 256))
96                  */
97                 div_exp = 0;
98                 exponent = 0;
99                 mantissa = NIX_TM_MAX_RATE_MANTISSA;
100
101                 while (value < (NIX_TM_SHAPER_RATE_CONST / (1 << div_exp)))
102                         div_exp += 1;
103
104                 while (value < ((NIX_TM_SHAPER_RATE_CONST * (256 + mantissa)) /
105                                 ((1 << div_exp) * 256)))
106                         mantissa -= 1;
107         } else {
108                 /* Calculate rate exponent and mantissa using
109                  * the following formula:
110                  *
111                  * value = (2E6 * ((256 + mantissa) << exponent)) / 256
112                  *
113                  */
114                 div_exp = 0;
115                 exponent = NIX_TM_MAX_RATE_EXPONENT;
116                 mantissa = NIX_TM_MAX_RATE_MANTISSA;
117
118                 while (value < (NIX_TM_SHAPER_RATE_CONST * (1 << exponent)))
119                         exponent -= 1;
120
121                 while (value < ((NIX_TM_SHAPER_RATE_CONST *
122                                  ((256 + mantissa) << exponent)) /
123                                 256))
124                         mantissa -= 1;
125         }
126
127         if (div_exp > NIX_TM_MAX_RATE_DIV_EXP ||
128             exponent > NIX_TM_MAX_RATE_EXPONENT ||
129             mantissa > NIX_TM_MAX_RATE_MANTISSA)
130                 return 0;
131
132         if (div_exp_p)
133                 *div_exp_p = div_exp;
134         if (exponent_p)
135                 *exponent_p = exponent;
136         if (mantissa_p)
137                 *mantissa_p = mantissa;
138
139         /* Calculate real rate value */
140         return NIX_TM_SHAPER_RATE(exponent, mantissa, div_exp);
141 }
142
143 uint64_t
144 nix_tm_shaper_burst_conv(uint64_t value, uint64_t *exponent_p,
145                          uint64_t *mantissa_p)
146 {
147         uint64_t exponent, mantissa;
148
149         if (value < NIX_TM_MIN_SHAPER_BURST || value > NIX_TM_MAX_SHAPER_BURST)
150                 return 0;
151
152         /* Calculate burst exponent and mantissa using
153          * the following formula:
154          *
155          * value = (((256 + mantissa) << (exponent + 1)
156          / 256)
157          *
158          */
159         exponent = NIX_TM_MAX_BURST_EXPONENT;
160         mantissa = NIX_TM_MAX_BURST_MANTISSA;
161
162         while (value < (1ull << (exponent + 1)))
163                 exponent -= 1;
164
165         while (value < ((256 + mantissa) << (exponent + 1)) / 256)
166                 mantissa -= 1;
167
168         if (exponent > NIX_TM_MAX_BURST_EXPONENT ||
169             mantissa > NIX_TM_MAX_BURST_MANTISSA)
170                 return 0;
171
172         if (exponent_p)
173                 *exponent_p = exponent;
174         if (mantissa_p)
175                 *mantissa_p = mantissa;
176
177         return NIX_TM_SHAPER_BURST(exponent, mantissa);
178 }
179
180 uint32_t
181 nix_tm_check_rr(struct nix *nix, uint32_t parent_id, enum roc_nix_tm_tree tree,
182                 uint32_t *rr_prio, uint32_t *max_prio)
183 {
184         uint32_t node_cnt[NIX_TM_TLX_SP_PRIO_MAX];
185         struct nix_tm_node_list *list;
186         struct nix_tm_node *node;
187         uint32_t rr_num = 0, i;
188         uint32_t children = 0;
189         uint32_t priority;
190
191         memset(node_cnt, 0, sizeof(node_cnt));
192         *rr_prio = 0xF;
193         *max_prio = UINT32_MAX;
194
195         list = nix_tm_node_list(nix, tree);
196         TAILQ_FOREACH(node, list, node) {
197                 if (!node->parent)
198                         continue;
199
200                 if (!(node->parent->id == parent_id))
201                         continue;
202
203                 priority = node->priority;
204                 node_cnt[priority]++;
205                 children++;
206         }
207
208         for (i = 0; i < NIX_TM_TLX_SP_PRIO_MAX; i++) {
209                 if (!node_cnt[i])
210                         break;
211
212                 if (node_cnt[i] > rr_num) {
213                         *rr_prio = i;
214                         rr_num = node_cnt[i];
215                 }
216         }
217
218         /* RR group of single RR child is considered as SP */
219         if (rr_num == 1) {
220                 *rr_prio = 0xF;
221                 rr_num = 0;
222         }
223
224         /* Max prio will be returned only when we have non zero prio
225          * or if a parent has single child.
226          */
227         if (i > 1 || (children == 1))
228                 *max_prio = i - 1;
229         return rr_num;
230 }
231
232 static uint16_t
233 nix_tm_max_prio(struct nix *nix, uint16_t hw_lvl)
234 {
235         if (hw_lvl >= NIX_TXSCH_LVL_CNT)
236                 return 0;
237
238         /* MDQ does not support SP */
239         if (hw_lvl == NIX_TXSCH_LVL_MDQ)
240                 return 0;
241
242         /* PF's TL1 with VF's enabled does not support SP */
243         if (hw_lvl == NIX_TXSCH_LVL_TL1 && (!nix_tm_have_tl1_access(nix) ||
244                                             (nix->tm_flags & NIX_TM_TL1_NO_SP)))
245                 return 0;
246
247         return NIX_TM_TLX_SP_PRIO_MAX - 1;
248 }
249
250 int
251 nix_tm_validate_prio(struct nix *nix, uint32_t lvl, uint32_t parent_id,
252                      uint32_t priority, enum roc_nix_tm_tree tree)
253 {
254         uint8_t priorities[NIX_TM_TLX_SP_PRIO_MAX];
255         struct nix_tm_node_list *list;
256         struct nix_tm_node *node;
257         uint32_t rr_num = 0;
258         int i;
259
260         list = nix_tm_node_list(nix, tree);
261         /* Validate priority against max */
262         if (priority > nix_tm_max_prio(nix, nix_tm_lvl2nix(nix, lvl - 1)))
263                 return NIX_ERR_TM_PRIO_EXCEEDED;
264
265         if (parent_id == ROC_NIX_TM_NODE_ID_INVALID)
266                 return 0;
267
268         memset(priorities, 0, sizeof(priorities));
269         priorities[priority] = 1;
270
271         TAILQ_FOREACH(node, list, node) {
272                 if (!node->parent)
273                         continue;
274
275                 if (node->parent->id != parent_id)
276                         continue;
277
278                 priorities[node->priority]++;
279         }
280
281         for (i = 0; i < NIX_TM_TLX_SP_PRIO_MAX; i++)
282                 if (priorities[i] > 1)
283                         rr_num++;
284
285         /* At max, one rr groups per parent */
286         if (rr_num > 1)
287                 return NIX_ERR_TM_MULTIPLE_RR_GROUPS;
288
289         /* Check for previous priority to avoid holes in priorities */
290         if (priority && !priorities[priority - 1])
291                 return NIX_ERR_TM_PRIO_ORDER;
292
293         return 0;
294 }
295
296 bool
297 nix_tm_child_res_valid(struct nix_tm_node_list *list,
298                        struct nix_tm_node *parent)
299 {
300         struct nix_tm_node *child;
301
302         TAILQ_FOREACH(child, list, node) {
303                 if (child->parent != parent)
304                         continue;
305                 if (!(child->flags & NIX_TM_NODE_HWRES))
306                         return false;
307         }
308         return true;
309 }
310
311 uint8_t
312 nix_tm_sw_xoff_prep(struct nix_tm_node *node, bool enable,
313                     volatile uint64_t *reg, volatile uint64_t *regval)
314 {
315         uint32_t hw_lvl = node->hw_lvl;
316         uint32_t schq = node->hw_id;
317         uint8_t k = 0;
318
319         plt_tm_dbg("sw xoff config node %s(%u) lvl %u id %u, enable %u (%p)",
320                    nix_tm_hwlvl2str(hw_lvl), schq, node->lvl, node->id, enable,
321                    node);
322
323         regval[k] = enable;
324
325         switch (hw_lvl) {
326         case NIX_TXSCH_LVL_MDQ:
327                 reg[k] = NIX_AF_MDQX_SW_XOFF(schq);
328                 k++;
329                 break;
330         case NIX_TXSCH_LVL_TL4:
331                 reg[k] = NIX_AF_TL4X_SW_XOFF(schq);
332                 k++;
333                 break;
334         case NIX_TXSCH_LVL_TL3:
335                 reg[k] = NIX_AF_TL3X_SW_XOFF(schq);
336                 k++;
337                 break;
338         case NIX_TXSCH_LVL_TL2:
339                 reg[k] = NIX_AF_TL2X_SW_XOFF(schq);
340                 k++;
341                 break;
342         case NIX_TXSCH_LVL_TL1:
343                 reg[k] = NIX_AF_TL1X_SW_XOFF(schq);
344                 k++;
345                 break;
346         default:
347                 break;
348         }
349
350         return k;
351 }
352
353 /* Search for min rate in topology */
354 uint64_t
355 nix_tm_shaper_profile_rate_min(struct nix *nix)
356 {
357         struct nix_tm_shaper_profile *profile;
358         uint64_t rate_min = 1E9; /* 1 Gbps */
359
360         TAILQ_FOREACH(profile, &nix->shaper_profile_list, shaper) {
361                 if (profile->peak.rate && profile->peak.rate < rate_min)
362                         rate_min = profile->peak.rate;
363
364                 if (profile->commit.rate && profile->commit.rate < rate_min)
365                         rate_min = profile->commit.rate;
366         }
367         return rate_min;
368 }
369
370 uint16_t
371 nix_tm_resource_avail(struct nix *nix, uint8_t hw_lvl, bool contig)
372 {
373         uint32_t pos = 0, start_pos = 0;
374         struct plt_bitmap *bmp;
375         uint16_t count = 0;
376         uint64_t slab = 0;
377
378         bmp = contig ? nix->schq_contig_bmp[hw_lvl] : nix->schq_bmp[hw_lvl];
379         plt_bitmap_scan_init(bmp);
380
381         if (!plt_bitmap_scan(bmp, &pos, &slab))
382                 return count;
383
384         /* Count bit set */
385         start_pos = pos;
386         do {
387                 count += __builtin_popcountll(slab);
388                 if (!plt_bitmap_scan(bmp, &pos, &slab))
389                         break;
390         } while (pos != start_pos);
391
392         return count;
393 }
394
395 uint16_t
396 nix_tm_resource_estimate(struct nix *nix, uint16_t *schq_contig, uint16_t *schq,
397                          enum roc_nix_tm_tree tree)
398 {
399         struct nix_tm_node_list *list;
400         uint8_t contig_cnt, hw_lvl;
401         struct nix_tm_node *parent;
402         uint16_t cnt = 0, avail;
403
404         list = nix_tm_node_list(nix, tree);
405         /* Walk through parents from TL1..TL4 */
406         for (hw_lvl = NIX_TXSCH_LVL_TL1; hw_lvl > 0; hw_lvl--) {
407                 TAILQ_FOREACH(parent, list, node) {
408                         if (hw_lvl != parent->hw_lvl)
409                                 continue;
410
411                         /* Skip accounting for children whose
412                          * parent does not indicate so.
413                          */
414                         if (!parent->child_realloc)
415                                 continue;
416
417                         /* Count children needed */
418                         schq[hw_lvl - 1] += parent->rr_num;
419                         if (parent->max_prio != UINT32_MAX) {
420                                 contig_cnt = parent->max_prio + 1;
421                                 schq_contig[hw_lvl - 1] += contig_cnt;
422                                 /* When we have SP + DWRR at a parent,
423                                  * we will always have a spare schq at rr prio
424                                  * location in contiguous queues. Hence reduce
425                                  * discontiguous count by 1.
426                                  */
427                                 if (parent->max_prio > 0 && parent->rr_num)
428                                         schq[hw_lvl - 1] -= 1;
429                         }
430                 }
431         }
432
433         schq[nix->tm_root_lvl] = 1;
434         if (!nix_tm_have_tl1_access(nix))
435                 schq[NIX_TXSCH_LVL_TL1] = 1;
436
437         /* Now check for existing resources */
438         for (hw_lvl = 0; hw_lvl < NIX_TXSCH_LVL_CNT; hw_lvl++) {
439                 avail = nix_tm_resource_avail(nix, hw_lvl, false);
440                 if (schq[hw_lvl] <= avail)
441                         schq[hw_lvl] = 0;
442                 else
443                         schq[hw_lvl] -= avail;
444
445                 /* For contiguous queues, realloc everything */
446                 avail = nix_tm_resource_avail(nix, hw_lvl, true);
447                 if (schq_contig[hw_lvl] <= avail)
448                         schq_contig[hw_lvl] = 0;
449
450                 cnt += schq[hw_lvl];
451                 cnt += schq_contig[hw_lvl];
452
453                 plt_tm_dbg("Estimate resources needed for %s: dis %u cont %u",
454                            nix_tm_hwlvl2str(hw_lvl), schq[hw_lvl],
455                            schq_contig[hw_lvl]);
456         }
457
458         return cnt;
459 }
460
461 int
462 roc_nix_tm_node_lvl(struct roc_nix *roc_nix, uint32_t node_id)
463 {
464         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
465         struct nix_tm_node *node;
466
467         node = nix_tm_node_search(nix, node_id, ROC_NIX_TM_USER);
468         if (!node)
469                 return NIX_ERR_TM_INVALID_NODE;
470
471         return node->lvl;
472 }
473
474 struct roc_nix_tm_node *
475 roc_nix_tm_node_get(struct roc_nix *roc_nix, uint32_t node_id)
476 {
477         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
478         struct nix_tm_node *node;
479
480         node = nix_tm_node_search(nix, node_id, ROC_NIX_TM_USER);
481         return (struct roc_nix_tm_node *)node;
482 }
483
484 struct roc_nix_tm_node *
485 roc_nix_tm_node_next(struct roc_nix *roc_nix, struct roc_nix_tm_node *__prev)
486 {
487         struct nix_tm_node *prev = (struct nix_tm_node *)__prev;
488         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
489         struct nix_tm_node_list *list;
490
491         list = nix_tm_node_list(nix, ROC_NIX_TM_USER);
492
493         /* HEAD of the list */
494         if (!prev)
495                 return (struct roc_nix_tm_node *)TAILQ_FIRST(list);
496
497         /* Next entry */
498         if (prev->tree != ROC_NIX_TM_USER)
499                 return NULL;
500
501         return (struct roc_nix_tm_node *)TAILQ_NEXT(prev, node);
502 }
503
504 struct roc_nix_tm_shaper_profile *
505 roc_nix_tm_shaper_profile_get(struct roc_nix *roc_nix, uint32_t profile_id)
506 {
507         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
508         struct nix_tm_shaper_profile *profile;
509
510         profile = nix_tm_shaper_profile_search(nix, profile_id);
511         return (struct roc_nix_tm_shaper_profile *)profile;
512 }
513
514 struct roc_nix_tm_shaper_profile *
515 roc_nix_tm_shaper_profile_next(struct roc_nix *roc_nix,
516                                struct roc_nix_tm_shaper_profile *__prev)
517 {
518         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
519         struct nix_tm_shaper_profile_list *list;
520         struct nix_tm_shaper_profile *prev;
521
522         prev = (struct nix_tm_shaper_profile *)__prev;
523         list = &nix->shaper_profile_list;
524
525         /* HEAD of the list */
526         if (!prev)
527                 return (struct roc_nix_tm_shaper_profile *)TAILQ_FIRST(list);
528
529         return (struct roc_nix_tm_shaper_profile *)TAILQ_NEXT(prev, shaper);
530 }
531
532 struct nix_tm_node *
533 nix_tm_node_alloc(void)
534 {
535         struct nix_tm_node *node;
536
537         node = plt_zmalloc(sizeof(struct nix_tm_node), 0);
538         if (!node)
539                 return NULL;
540
541         node->free_fn = plt_free;
542         return node;
543 }
544
545 void
546 nix_tm_node_free(struct nix_tm_node *node)
547 {
548         if (!node || node->free_fn == NULL)
549                 return;
550
551         (node->free_fn)(node);
552 }
553
554 struct nix_tm_shaper_profile *
555 nix_tm_shaper_profile_alloc(void)
556 {
557         struct nix_tm_shaper_profile *profile;
558
559         profile = plt_zmalloc(sizeof(struct nix_tm_shaper_profile), 0);
560         if (!profile)
561                 return NULL;
562
563         profile->free_fn = plt_free;
564         return profile;
565 }
566
567 void
568 nix_tm_shaper_profile_free(struct nix_tm_shaper_profile *profile)
569 {
570         if (!profile || !profile->free_fn)
571                 return;
572
573         (profile->free_fn)(profile);
574 }