net/mlx5: remove redundant flag in device config
[dpdk.git] / drivers / common / cnxk / roc_nix_tm_ops.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 int
9 roc_nix_tm_sq_aura_fc(struct roc_nix_sq *sq, bool enable)
10 {
11         struct npa_aq_enq_req *req;
12         struct npa_aq_enq_rsp *rsp;
13         uint64_t aura_handle;
14         struct npa_lf *lf;
15         struct mbox *mbox;
16         int rc = -ENOSPC;
17
18         plt_tm_dbg("Setting SQ %u SQB aura FC to %s", sq->qid,
19                    enable ? "enable" : "disable");
20
21         lf = idev_npa_obj_get();
22         if (!lf)
23                 return NPA_ERR_DEVICE_NOT_BOUNDED;
24
25         mbox = lf->mbox;
26         /* Set/clear sqb aura fc_ena */
27         aura_handle = sq->aura_handle;
28         req = mbox_alloc_msg_npa_aq_enq(mbox);
29         if (req == NULL)
30                 return rc;
31
32         req->aura_id = roc_npa_aura_handle_to_aura(aura_handle);
33         req->ctype = NPA_AQ_CTYPE_AURA;
34         req->op = NPA_AQ_INSTOP_WRITE;
35         /* Below is not needed for aura writes but AF driver needs it */
36         /* AF will translate to associated poolctx */
37         req->aura.pool_addr = req->aura_id;
38
39         req->aura.fc_ena = enable;
40         req->aura_mask.fc_ena = 1;
41         if (roc_model_is_cn9k() || roc_model_is_cn10ka_a0()) {
42                 req->aura.fc_stype = 0x0;      /* STF */
43                 req->aura_mask.fc_stype = 0x0; /* STF */
44         } else {
45                 req->aura.fc_stype = 0x3;      /* STSTP */
46                 req->aura_mask.fc_stype = 0x3; /* STSTP */
47         }
48
49         rc = mbox_process(mbox);
50         if (rc)
51                 return rc;
52
53         /* Read back npa aura ctx */
54         req = mbox_alloc_msg_npa_aq_enq(mbox);
55         if (req == NULL)
56                 return -ENOSPC;
57
58         req->aura_id = roc_npa_aura_handle_to_aura(aura_handle);
59         req->ctype = NPA_AQ_CTYPE_AURA;
60         req->op = NPA_AQ_INSTOP_READ;
61
62         rc = mbox_process_msg(mbox, (void *)&rsp);
63         if (rc)
64                 return rc;
65
66         /* Init when enabled as there might be no triggers */
67         if (enable)
68                 *(volatile uint64_t *)sq->fc = rsp->aura.count;
69         else
70                 *(volatile uint64_t *)sq->fc = sq->nb_sqb_bufs;
71         /* Sync write barrier */
72         plt_wmb();
73         return 0;
74 }
75
76 int
77 roc_nix_tm_free_resources(struct roc_nix *roc_nix, bool hw_only)
78 {
79         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
80
81         if (nix->tm_flags & NIX_TM_HIERARCHY_ENA)
82                 return -EBUSY;
83
84         return nix_tm_free_resources(roc_nix, BIT(ROC_NIX_TM_USER), hw_only);
85 }
86
87 static int
88 nix_tm_adjust_shaper_pps_rate(struct nix_tm_shaper_profile *profile)
89 {
90         uint64_t min_rate = profile->commit.rate;
91
92         if (!profile->pkt_mode)
93                 return 0;
94
95         profile->pkt_mode_adj = 1;
96
97         if (profile->commit.rate &&
98             (profile->commit.rate < NIX_TM_MIN_SHAPER_PPS_RATE ||
99              profile->commit.rate > NIX_TM_MAX_SHAPER_PPS_RATE))
100                 return NIX_ERR_TM_INVALID_COMMIT_RATE;
101
102         if (profile->peak.rate &&
103             (profile->peak.rate < NIX_TM_MIN_SHAPER_PPS_RATE ||
104              profile->peak.rate > NIX_TM_MAX_SHAPER_PPS_RATE))
105                 return NIX_ERR_TM_INVALID_PEAK_RATE;
106
107         if (profile->peak.rate && min_rate > profile->peak.rate)
108                 min_rate = profile->peak.rate;
109
110         /* Each packet accomulate single count, whereas HW
111          * considers each unit as Byte, so we need convert
112          * user pps to bps
113          */
114         profile->commit.rate = profile->commit.rate * 8;
115         profile->peak.rate = profile->peak.rate * 8;
116         min_rate = min_rate * 8;
117
118         if (min_rate && (min_rate < NIX_TM_MIN_SHAPER_RATE)) {
119                 int adjust = NIX_TM_MIN_SHAPER_RATE / min_rate;
120
121                 if (adjust > NIX_TM_LENGTH_ADJUST_MAX)
122                         return NIX_ERR_TM_SHAPER_PKT_LEN_ADJUST;
123
124                 profile->pkt_mode_adj += adjust;
125                 profile->commit.rate += (adjust * profile->commit.rate);
126                 profile->peak.rate += (adjust * profile->peak.rate);
127         }
128
129         return 0;
130 }
131
132 static int
133 nix_tm_shaper_profile_add(struct roc_nix *roc_nix,
134                           struct nix_tm_shaper_profile *profile, int skip_ins)
135 {
136         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
137         uint64_t commit_rate, commit_sz;
138         uint64_t min_burst, max_burst;
139         uint64_t peak_rate, peak_sz;
140         uint32_t id;
141         int rc;
142
143         id = profile->id;
144         rc = nix_tm_adjust_shaper_pps_rate(profile);
145         if (rc)
146                 return rc;
147
148         commit_rate = profile->commit.rate;
149         commit_sz = profile->commit.size;
150         peak_rate = profile->peak.rate;
151         peak_sz = profile->peak.size;
152
153         min_burst = NIX_TM_MIN_SHAPER_BURST;
154         max_burst = roc_nix_tm_max_shaper_burst_get();
155
156         if (nix_tm_shaper_profile_search(nix, id) && !skip_ins)
157                 return NIX_ERR_TM_SHAPER_PROFILE_EXISTS;
158
159         if (profile->pkt_len_adj < NIX_TM_LENGTH_ADJUST_MIN ||
160             profile->pkt_len_adj > NIX_TM_LENGTH_ADJUST_MAX)
161                 return NIX_ERR_TM_SHAPER_PKT_LEN_ADJUST;
162
163         /* We cannot support both pkt length adjust and pkt mode */
164         if (profile->pkt_mode && profile->pkt_len_adj)
165                 return NIX_ERR_TM_SHAPER_PKT_LEN_ADJUST;
166
167         /* commit rate and burst size can be enabled/disabled */
168         if (commit_rate || commit_sz) {
169                 if (commit_sz < min_burst || commit_sz > max_burst)
170                         return NIX_ERR_TM_INVALID_COMMIT_SZ;
171                 else if (!nix_tm_shaper_rate_conv(commit_rate, NULL, NULL,
172                                                   NULL))
173                         return NIX_ERR_TM_INVALID_COMMIT_RATE;
174         }
175
176         /* Peak rate and burst size can be enabled/disabled */
177         if (peak_sz || peak_rate) {
178                 if (peak_sz < min_burst || peak_sz > max_burst)
179                         return NIX_ERR_TM_INVALID_PEAK_SZ;
180                 else if (!nix_tm_shaper_rate_conv(peak_rate, NULL, NULL, NULL))
181                         return NIX_ERR_TM_INVALID_PEAK_RATE;
182         }
183
184         if (!skip_ins)
185                 TAILQ_INSERT_TAIL(&nix->shaper_profile_list, profile, shaper);
186
187         plt_tm_dbg("Added TM shaper profile %u, "
188                    " pir %" PRIu64 " , pbs %" PRIu64 ", cir %" PRIu64
189                    ", cbs %" PRIu64 " , adj %u, pkt_mode %u",
190                    id, profile->peak.rate, profile->peak.size,
191                    profile->commit.rate, profile->commit.size,
192                    profile->pkt_len_adj, profile->pkt_mode);
193
194         /* Always use PIR for single rate shaping */
195         if (!peak_rate && commit_rate) {
196                 profile->peak.rate = profile->commit.rate;
197                 profile->peak.size = profile->commit.size;
198                 profile->commit.rate = 0;
199                 profile->commit.size = 0;
200         }
201
202         /* update min rate */
203         nix->tm_rate_min = nix_tm_shaper_profile_rate_min(nix);
204         return 0;
205 }
206
207 int
208 roc_nix_tm_shaper_profile_add(struct roc_nix *roc_nix,
209                               struct roc_nix_tm_shaper_profile *roc_profile)
210 {
211         struct nix_tm_shaper_profile *profile;
212
213         profile = (struct nix_tm_shaper_profile *)roc_profile->reserved;
214
215         profile->ref_cnt = 0;
216         profile->id = roc_profile->id;
217         profile->commit.rate = roc_profile->commit_rate;
218         profile->peak.rate = roc_profile->peak_rate;
219         profile->commit.size = roc_profile->commit_sz;
220         profile->peak.size = roc_profile->peak_sz;
221         profile->pkt_len_adj = roc_profile->pkt_len_adj;
222         profile->pkt_mode = roc_profile->pkt_mode;
223         profile->free_fn = roc_profile->free_fn;
224
225         return nix_tm_shaper_profile_add(roc_nix, profile, 0);
226 }
227
228 int
229 roc_nix_tm_shaper_profile_update(struct roc_nix *roc_nix,
230                                  struct roc_nix_tm_shaper_profile *roc_profile)
231 {
232         struct nix_tm_shaper_profile *profile;
233
234         profile = (struct nix_tm_shaper_profile *)roc_profile->reserved;
235
236         profile->commit.rate = roc_profile->commit_rate;
237         profile->peak.rate = roc_profile->peak_rate;
238         profile->commit.size = roc_profile->commit_sz;
239         profile->peak.size = roc_profile->peak_sz;
240
241         return nix_tm_shaper_profile_add(roc_nix, profile, 1);
242 }
243
244 int
245 roc_nix_tm_shaper_profile_delete(struct roc_nix *roc_nix, uint32_t id)
246 {
247         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
248         struct nix_tm_shaper_profile *profile;
249
250         profile = nix_tm_shaper_profile_search(nix, id);
251         if (!profile)
252                 return NIX_ERR_TM_INVALID_SHAPER_PROFILE;
253
254         if (profile->ref_cnt)
255                 return NIX_ERR_TM_SHAPER_PROFILE_IN_USE;
256
257         plt_tm_dbg("Removing TM shaper profile %u", id);
258         TAILQ_REMOVE(&nix->shaper_profile_list, profile, shaper);
259         nix_tm_shaper_profile_free(profile);
260
261         /* update min rate */
262         nix->tm_rate_min = nix_tm_shaper_profile_rate_min(nix);
263         return 0;
264 }
265
266 int
267 roc_nix_tm_node_add(struct roc_nix *roc_nix, struct roc_nix_tm_node *roc_node)
268 {
269         struct nix_tm_node *node;
270
271         node = (struct nix_tm_node *)&roc_node->reserved;
272         node->id = roc_node->id;
273         node->priority = roc_node->priority;
274         node->weight = roc_node->weight;
275         node->lvl = roc_node->lvl;
276         node->parent_id = roc_node->parent_id;
277         node->shaper_profile_id = roc_node->shaper_profile_id;
278         node->pkt_mode = roc_node->pkt_mode;
279         node->pkt_mode_set = roc_node->pkt_mode_set;
280         node->free_fn = roc_node->free_fn;
281         node->tree = ROC_NIX_TM_USER;
282
283         return nix_tm_node_add(roc_nix, node);
284 }
285
286 int
287 roc_nix_tm_node_pkt_mode_update(struct roc_nix *roc_nix, uint32_t node_id,
288                                 bool pkt_mode)
289 {
290         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
291         struct nix_tm_node *node, *child;
292         struct nix_tm_node_list *list;
293         int num_children = 0;
294
295         node = nix_tm_node_search(nix, node_id, ROC_NIX_TM_USER);
296         if (!node)
297                 return NIX_ERR_TM_INVALID_NODE;
298
299         if (node->pkt_mode == pkt_mode) {
300                 node->pkt_mode_set = true;
301                 return 0;
302         }
303
304         /* Check for any existing children, if there are any,
305          * then we cannot update the pkt mode as children's quantum
306          * are already taken in.
307          */
308         list = nix_tm_node_list(nix, ROC_NIX_TM_USER);
309         TAILQ_FOREACH(child, list, node) {
310                 if (child->parent == node)
311                         num_children++;
312         }
313
314         /* Cannot update mode if it has children or tree is enabled */
315         if ((nix->tm_flags & NIX_TM_HIERARCHY_ENA) && num_children)
316                 return -EBUSY;
317
318         if (node->pkt_mode_set && num_children)
319                 return NIX_ERR_TM_PKT_MODE_MISMATCH;
320
321         node->pkt_mode = pkt_mode;
322         node->pkt_mode_set = true;
323
324         return 0;
325 }
326
327 int
328 roc_nix_tm_node_name_get(struct roc_nix *roc_nix, uint32_t node_id, char *buf,
329                          size_t buflen)
330 {
331         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
332         struct nix_tm_node *node;
333
334         node = nix_tm_node_search(nix, node_id, ROC_NIX_TM_USER);
335         if (!node) {
336                 plt_strlcpy(buf, "???", buflen);
337                 return NIX_ERR_TM_INVALID_NODE;
338         }
339
340         if (node->hw_lvl == NIX_TXSCH_LVL_CNT)
341                 snprintf(buf, buflen, "SQ_%d", node->id);
342         else
343                 snprintf(buf, buflen, "%s_%d", nix_tm_hwlvl2str(node->hw_lvl),
344                          node->hw_id);
345         return 0;
346 }
347
348 int
349 roc_nix_tm_node_delete(struct roc_nix *roc_nix, uint32_t node_id, bool free)
350 {
351         return nix_tm_node_delete(roc_nix, node_id, ROC_NIX_TM_USER, free);
352 }
353
354 int
355 roc_nix_smq_flush(struct roc_nix *roc_nix)
356 {
357         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
358         struct nix_tm_node_list *list;
359         enum roc_nix_tm_tree tree;
360         struct nix_tm_node *node;
361         int rc = 0;
362
363         if (!(nix->tm_flags & NIX_TM_HIERARCHY_ENA))
364                 return 0;
365
366         tree = nix->tm_tree;
367         list = nix_tm_node_list(nix, tree);
368
369         /* XOFF & Flush all SMQ's. HRM mandates
370          * all SQ's empty before SMQ flush is issued.
371          */
372         TAILQ_FOREACH(node, list, node) {
373                 if (node->hw_lvl != NIX_TXSCH_LVL_SMQ)
374                         continue;
375                 if (!(node->flags & NIX_TM_NODE_HWRES))
376                         continue;
377
378                 rc = nix_tm_smq_xoff(nix, node, true);
379                 if (rc) {
380                         plt_err("Failed to enable smq %u, rc=%d", node->hw_id,
381                                 rc);
382                         goto exit;
383                 }
384         }
385
386         /* XON all SMQ's */
387         TAILQ_FOREACH(node, list, node) {
388                 if (node->hw_lvl != NIX_TXSCH_LVL_SMQ)
389                         continue;
390                 if (!(node->flags & NIX_TM_NODE_HWRES))
391                         continue;
392
393                 rc = nix_tm_smq_xoff(nix, node, false);
394                 if (rc) {
395                         plt_err("Failed to enable smq %u, rc=%d", node->hw_id,
396                                 rc);
397                         goto exit;
398                 }
399         }
400 exit:
401         return rc;
402 }
403
404 int
405 roc_nix_tm_hierarchy_disable(struct roc_nix *roc_nix)
406 {
407         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
408         uint16_t sqb_cnt, head_off, tail_off;
409         uint16_t sq_cnt = nix->nb_tx_queues;
410         struct mbox *mbox = (&nix->dev)->mbox;
411         struct nix_tm_node_list *list;
412         enum roc_nix_tm_tree tree;
413         struct nix_tm_node *node;
414         struct roc_nix_sq *sq;
415         uint64_t wdata, val;
416         uintptr_t regaddr;
417         int rc = -1, i;
418
419         if (!(nix->tm_flags & NIX_TM_HIERARCHY_ENA))
420                 return 0;
421
422         plt_tm_dbg("Disabling hierarchy on %s", nix->pci_dev->name);
423
424         tree = nix->tm_tree;
425         list = nix_tm_node_list(nix, tree);
426
427         /* Enable CGX RXTX to drain pkts */
428         if (!roc_nix->io_enabled) {
429                 /* Though it enables both RX MCAM Entries and CGX Link
430                  * we assume all the rx queues are stopped way back.
431                  */
432                 mbox_alloc_msg_nix_lf_start_rx(mbox);
433                 rc = mbox_process(mbox);
434                 if (rc) {
435                         plt_err("cgx start failed, rc=%d", rc);
436                         return rc;
437                 }
438         }
439
440         /* XON all SMQ's */
441         TAILQ_FOREACH(node, list, node) {
442                 if (node->hw_lvl != NIX_TXSCH_LVL_SMQ)
443                         continue;
444                 if (!(node->flags & NIX_TM_NODE_HWRES))
445                         continue;
446
447                 rc = nix_tm_smq_xoff(nix, node, false);
448                 if (rc) {
449                         plt_err("Failed to enable smq %u, rc=%d", node->hw_id,
450                                 rc);
451                         goto cleanup;
452                 }
453         }
454
455         /* Flush all tx queues */
456         for (i = 0; i < sq_cnt; i++) {
457                 sq = nix->sqs[i];
458                 if (!sq)
459                         continue;
460
461                 rc = roc_nix_tm_sq_aura_fc(sq, false);
462                 if (rc) {
463                         plt_err("Failed to disable sqb aura fc, rc=%d", rc);
464                         goto cleanup;
465                 }
466
467                 /* Wait for sq entries to be flushed */
468                 rc = roc_nix_tm_sq_flush_spin(sq);
469                 if (rc) {
470                         plt_err("Failed to drain sq, rc=%d\n", rc);
471                         goto cleanup;
472                 }
473         }
474
475         /* XOFF & Flush all SMQ's. HRM mandates
476          * all SQ's empty before SMQ flush is issued.
477          */
478         TAILQ_FOREACH(node, list, node) {
479                 if (node->hw_lvl != NIX_TXSCH_LVL_SMQ)
480                         continue;
481                 if (!(node->flags & NIX_TM_NODE_HWRES))
482                         continue;
483
484                 rc = nix_tm_smq_xoff(nix, node, true);
485                 if (rc) {
486                         plt_err("Failed to enable smq %u, rc=%d", node->hw_id,
487                                 rc);
488                         goto cleanup;
489                 }
490
491                 node->flags &= ~NIX_TM_NODE_ENABLED;
492         }
493
494         /* Verify sanity of all tx queues */
495         for (i = 0; i < sq_cnt; i++) {
496                 sq = nix->sqs[i];
497                 if (!sq)
498                         continue;
499
500                 wdata = ((uint64_t)sq->qid << 32);
501                 regaddr = nix->base + NIX_LF_SQ_OP_STATUS;
502                 val = roc_atomic64_add_nosync(wdata, (int64_t *)regaddr);
503
504                 sqb_cnt = val & 0xFFFF;
505                 head_off = (val >> 20) & 0x3F;
506                 tail_off = (val >> 28) & 0x3F;
507
508                 if (sqb_cnt > 1 || head_off != tail_off ||
509                     (*(uint64_t *)sq->fc != sq->nb_sqb_bufs))
510                         plt_err("Failed to gracefully flush sq %u", sq->qid);
511         }
512
513         nix->tm_flags &= ~NIX_TM_HIERARCHY_ENA;
514 cleanup:
515         /* Restore cgx state */
516         if (!roc_nix->io_enabled) {
517                 mbox_alloc_msg_nix_lf_stop_rx(mbox);
518                 rc |= mbox_process(mbox);
519         }
520         return rc;
521 }
522
523 int
524 roc_nix_tm_hierarchy_enable(struct roc_nix *roc_nix, enum roc_nix_tm_tree tree,
525                             bool xmit_enable)
526 {
527         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
528         struct nix_tm_node_list *list;
529         struct nix_tm_node *node;
530         struct roc_nix_sq *sq;
531         uint32_t tree_mask;
532         uint16_t sq_id;
533         int rc;
534
535         if (tree >= ROC_NIX_TM_TREE_MAX)
536                 return NIX_ERR_PARAM;
537
538         if (nix->tm_flags & NIX_TM_HIERARCHY_ENA) {
539                 if (nix->tm_tree != tree)
540                         return -EBUSY;
541                 return 0;
542         }
543
544         plt_tm_dbg("Enabling hierarchy on %s, xmit_ena %u, tree %u",
545                    nix->pci_dev->name, xmit_enable, tree);
546
547         /* Free hw resources of other trees */
548         tree_mask = NIX_TM_TREE_MASK_ALL;
549         tree_mask &= ~BIT(tree);
550
551         rc = nix_tm_free_resources(roc_nix, tree_mask, true);
552         if (rc) {
553                 plt_err("failed to free resources of other trees, rc=%d", rc);
554                 return rc;
555         }
556
557         /* Update active tree before starting to do anything */
558         nix->tm_tree = tree;
559
560         nix_tm_update_parent_info(nix, tree);
561
562         rc = nix_tm_alloc_txschq(nix, tree);
563         if (rc) {
564                 plt_err("TM failed to alloc tm resources=%d", rc);
565                 return rc;
566         }
567
568         rc = nix_tm_assign_resources(nix, tree);
569         if (rc) {
570                 plt_err("TM failed to assign tm resources=%d", rc);
571                 return rc;
572         }
573
574         rc = nix_tm_txsch_reg_config(nix, tree);
575         if (rc) {
576                 plt_err("TM failed to configure sched registers=%d", rc);
577                 return rc;
578         }
579
580         list = nix_tm_node_list(nix, tree);
581         /* Mark all non-leaf's as enabled */
582         TAILQ_FOREACH(node, list, node) {
583                 if (!nix_tm_is_leaf(nix, node->lvl))
584                         node->flags |= NIX_TM_NODE_ENABLED;
585         }
586
587         if (!xmit_enable)
588                 goto skip_sq_update;
589
590         /* Update SQ Sched Data while SQ is idle */
591         TAILQ_FOREACH(node, list, node) {
592                 if (!nix_tm_is_leaf(nix, node->lvl))
593                         continue;
594
595                 rc = nix_tm_sq_sched_conf(nix, node, false);
596                 if (rc) {
597                         plt_err("SQ %u sched update failed, rc=%d", node->id,
598                                 rc);
599                         return rc;
600                 }
601         }
602
603         /* Finally XON all SMQ's */
604         TAILQ_FOREACH(node, list, node) {
605                 if (node->hw_lvl != NIX_TXSCH_LVL_SMQ)
606                         continue;
607
608                 rc = nix_tm_smq_xoff(nix, node, false);
609                 if (rc) {
610                         plt_err("Failed to enable smq %u, rc=%d", node->hw_id,
611                                 rc);
612                         return rc;
613                 }
614         }
615
616         /* Enable xmit as all the topology is ready */
617         TAILQ_FOREACH(node, list, node) {
618                 if (!nix_tm_is_leaf(nix, node->lvl))
619                         continue;
620
621                 sq_id = node->id;
622                 sq = nix->sqs[sq_id];
623
624                 rc = roc_nix_tm_sq_aura_fc(sq, true);
625                 if (rc) {
626                         plt_err("TM sw xon failed on SQ %u, rc=%d", node->id,
627                                 rc);
628                         return rc;
629                 }
630                 node->flags |= NIX_TM_NODE_ENABLED;
631         }
632
633 skip_sq_update:
634         nix->tm_flags |= NIX_TM_HIERARCHY_ENA;
635         return 0;
636 }
637
638 int
639 roc_nix_tm_node_suspend_resume(struct roc_nix *roc_nix, uint32_t node_id,
640                                bool suspend)
641 {
642         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
643         struct mbox *mbox = (&nix->dev)->mbox;
644         struct nix_txschq_config *req;
645         struct nix_tm_node *node;
646         uint16_t flags;
647         int rc;
648
649         node = nix_tm_node_search(nix, node_id, ROC_NIX_TM_USER);
650         if (!node)
651                 return NIX_ERR_TM_INVALID_NODE;
652
653         flags = node->flags;
654         flags = suspend ? (flags & ~NIX_TM_NODE_ENABLED) :
655                                 (flags | NIX_TM_NODE_ENABLED);
656
657         if (node->flags == flags)
658                 return 0;
659
660         /* send mbox for state change */
661         req = mbox_alloc_msg_nix_txschq_cfg(mbox);
662
663         req->lvl = node->hw_lvl;
664         req->num_regs =
665                 nix_tm_sw_xoff_prep(node, suspend, req->reg, req->regval);
666         rc = mbox_process(mbox);
667         if (!rc)
668                 node->flags = flags;
669         return rc;
670 }
671
672 int
673 roc_nix_tm_prealloc_res(struct roc_nix *roc_nix, uint8_t lvl,
674                         uint16_t discontig, uint16_t contig)
675 {
676         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
677         struct mbox *mbox = (&nix->dev)->mbox;
678         struct nix_txsch_alloc_req *req;
679         struct nix_txsch_alloc_rsp *rsp;
680         uint8_t hw_lvl;
681         int rc = -ENOSPC;
682
683         hw_lvl = nix_tm_lvl2nix(nix, lvl);
684         if (hw_lvl == NIX_TXSCH_LVL_CNT)
685                 return -EINVAL;
686
687         /* Preallocate contiguous */
688         if (nix->contig_rsvd[hw_lvl] < contig) {
689                 req = mbox_alloc_msg_nix_txsch_alloc(mbox);
690                 if (req == NULL)
691                         return rc;
692                 req->schq_contig[hw_lvl] = contig - nix->contig_rsvd[hw_lvl];
693
694                 rc = mbox_process_msg(mbox, (void *)&rsp);
695                 if (rc)
696                         return rc;
697
698                 nix_tm_copy_rsp_to_nix(nix, rsp);
699         }
700
701         /* Preallocate contiguous */
702         if (nix->discontig_rsvd[hw_lvl] < discontig) {
703                 req = mbox_alloc_msg_nix_txsch_alloc(mbox);
704                 if (req == NULL)
705                         return -ENOSPC;
706                 req->schq[hw_lvl] = discontig - nix->discontig_rsvd[hw_lvl];
707
708                 rc = mbox_process_msg(mbox, (void *)&rsp);
709                 if (rc)
710                         return rc;
711
712                 nix_tm_copy_rsp_to_nix(nix, rsp);
713         }
714
715         /* Save thresholds */
716         nix->contig_rsvd[hw_lvl] = contig;
717         nix->discontig_rsvd[hw_lvl] = discontig;
718         /* Release anything present above thresholds */
719         nix_tm_release_resources(nix, hw_lvl, true, true);
720         nix_tm_release_resources(nix, hw_lvl, false, true);
721         return 0;
722 }
723
724 int
725 roc_nix_tm_node_shaper_update(struct roc_nix *roc_nix, uint32_t node_id,
726                               uint32_t profile_id, bool force_update)
727 {
728         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
729         struct nix_tm_shaper_profile *profile = NULL;
730         struct mbox *mbox = (&nix->dev)->mbox;
731         struct nix_txschq_config *req;
732         struct nix_tm_node *node;
733         uint8_t k;
734         int rc;
735
736         /* Shaper updates valid only for user nodes */
737         node = nix_tm_node_search(nix, node_id, ROC_NIX_TM_USER);
738         if (!node || nix_tm_is_leaf(nix, node->lvl))
739                 return NIX_ERR_TM_INVALID_NODE;
740
741         if (profile_id != ROC_NIX_TM_SHAPER_PROFILE_NONE) {
742                 profile = nix_tm_shaper_profile_search(nix, profile_id);
743                 if (!profile)
744                         return NIX_ERR_TM_INVALID_SHAPER_PROFILE;
745         }
746
747         /* Pkt mode should match existing node's pkt mode */
748         if (profile && profile->pkt_mode != node->pkt_mode)
749                 return NIX_ERR_TM_PKT_MODE_MISMATCH;
750
751         if ((profile_id == node->shaper_profile_id) && !force_update) {
752                 return 0;
753         } else if (profile_id != node->shaper_profile_id) {
754                 struct nix_tm_shaper_profile *old;
755
756                 /* Find old shaper profile and reduce ref count */
757                 old = nix_tm_shaper_profile_search(nix,
758                                                    node->shaper_profile_id);
759                 if (old)
760                         old->ref_cnt--;
761
762                 if (profile)
763                         profile->ref_cnt++;
764
765                 /* Reduce older shaper ref count and increase new one */
766                 node->shaper_profile_id = profile_id;
767         }
768
769         /* Nothing to do if hierarchy not yet enabled */
770         if (!(nix->tm_flags & NIX_TM_HIERARCHY_ENA))
771                 return 0;
772
773         node->flags &= ~NIX_TM_NODE_ENABLED;
774
775         /* Flush the specific node with SW_XOFF */
776         req = mbox_alloc_msg_nix_txschq_cfg(mbox);
777         req->lvl = node->hw_lvl;
778         k = nix_tm_sw_xoff_prep(node, true, req->reg, req->regval);
779         req->num_regs = k;
780
781         rc = mbox_process(mbox);
782         if (rc)
783                 return rc;
784
785         /* Update the PIR/CIR and clear SW XOFF */
786         req = mbox_alloc_msg_nix_txschq_cfg(mbox);
787         req->lvl = node->hw_lvl;
788
789         k = nix_tm_shaper_reg_prep(node, profile, req->reg, req->regval);
790
791         k += nix_tm_sw_xoff_prep(node, false, &req->reg[k], &req->regval[k]);
792
793         req->num_regs = k;
794         rc = mbox_process(mbox);
795         if (!rc)
796                 node->flags |= NIX_TM_NODE_ENABLED;
797         return rc;
798 }
799
800 int
801 roc_nix_tm_node_parent_update(struct roc_nix *roc_nix, uint32_t node_id,
802                               uint32_t new_parent_id, uint32_t priority,
803                               uint32_t weight)
804 {
805         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
806         struct mbox *mbox = (&nix->dev)->mbox;
807         struct nix_tm_node *node, *sibling;
808         struct nix_tm_node *new_parent;
809         struct nix_txschq_config *req;
810         struct nix_tm_node_list *list;
811         uint8_t k;
812         int rc;
813
814         node = nix_tm_node_search(nix, node_id, ROC_NIX_TM_USER);
815         if (!node)
816                 return NIX_ERR_TM_INVALID_NODE;
817
818         /* Parent id valid only for non root nodes */
819         if (node->hw_lvl != nix->tm_root_lvl) {
820                 new_parent =
821                         nix_tm_node_search(nix, new_parent_id, ROC_NIX_TM_USER);
822                 if (!new_parent)
823                         return NIX_ERR_TM_INVALID_PARENT;
824
825                 /* Current support is only for dynamic weight update */
826                 if (node->parent != new_parent || node->priority != priority)
827                         return NIX_ERR_TM_PARENT_PRIO_UPDATE;
828         }
829
830         list = nix_tm_node_list(nix, ROC_NIX_TM_USER);
831         /* Skip if no change */
832         if (node->weight == weight)
833                 return 0;
834
835         node->weight = weight;
836
837         /* Nothing to do if hierarchy not yet enabled */
838         if (!(nix->tm_flags & NIX_TM_HIERARCHY_ENA))
839                 return 0;
840
841         /* For leaf nodes, SQ CTX needs update */
842         if (nix_tm_is_leaf(nix, node->lvl)) {
843                 /* Update SQ quantum data on the fly */
844                 rc = nix_tm_sq_sched_conf(nix, node, true);
845                 if (rc)
846                         return NIX_ERR_TM_SQ_UPDATE_FAIL;
847         } else {
848                 /* XOFF Parent node */
849                 req = mbox_alloc_msg_nix_txschq_cfg(mbox);
850                 req->lvl = node->parent->hw_lvl;
851                 req->num_regs = nix_tm_sw_xoff_prep(node->parent, true,
852                                                     req->reg, req->regval);
853                 rc = mbox_process(mbox);
854                 if (rc)
855                         return rc;
856
857                 /* XOFF this node and all other siblings */
858                 req = mbox_alloc_msg_nix_txschq_cfg(mbox);
859                 req->lvl = node->hw_lvl;
860
861                 k = 0;
862                 TAILQ_FOREACH(sibling, list, node) {
863                         if (sibling->parent != node->parent)
864                                 continue;
865                         k += nix_tm_sw_xoff_prep(sibling, true, &req->reg[k],
866                                                  &req->regval[k]);
867                 }
868                 req->num_regs = k;
869                 rc = mbox_process(mbox);
870                 if (rc)
871                         return rc;
872
873                 /* Update new weight for current node */
874                 req = mbox_alloc_msg_nix_txschq_cfg(mbox);
875                 req->lvl = node->hw_lvl;
876                 req->num_regs =
877                         nix_tm_sched_reg_prep(nix, node, req->reg, req->regval);
878                 rc = mbox_process(mbox);
879                 if (rc)
880                         return rc;
881
882                 /* XON this node and all other siblings */
883                 req = mbox_alloc_msg_nix_txschq_cfg(mbox);
884                 req->lvl = node->hw_lvl;
885
886                 k = 0;
887                 TAILQ_FOREACH(sibling, list, node) {
888                         if (sibling->parent != node->parent)
889                                 continue;
890                         k += nix_tm_sw_xoff_prep(sibling, false, &req->reg[k],
891                                                  &req->regval[k]);
892                 }
893                 req->num_regs = k;
894                 rc = mbox_process(mbox);
895                 if (rc)
896                         return rc;
897
898                 /* XON Parent node */
899                 req = mbox_alloc_msg_nix_txschq_cfg(mbox);
900                 req->lvl = node->parent->hw_lvl;
901                 req->num_regs = nix_tm_sw_xoff_prep(node->parent, false,
902                                                     req->reg, req->regval);
903                 rc = mbox_process(mbox);
904                 if (rc)
905                         return rc;
906         }
907         return 0;
908 }
909
910 int
911 roc_nix_tm_init(struct roc_nix *roc_nix)
912 {
913         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
914         uint32_t tree_mask;
915         int rc;
916
917         if (nix->tm_flags & NIX_TM_HIERARCHY_ENA) {
918                 plt_err("Cannot init while existing hierarchy is enabled");
919                 return -EBUSY;
920         }
921
922         /* Free up all user resources already held */
923         tree_mask = NIX_TM_TREE_MASK_ALL;
924         rc = nix_tm_free_resources(roc_nix, tree_mask, false);
925         if (rc) {
926                 plt_err("Failed to freeup all nodes and resources, rc=%d", rc);
927                 return rc;
928         }
929
930         /* Prepare default tree */
931         rc = nix_tm_prepare_default_tree(roc_nix);
932         if (rc) {
933                 plt_err("failed to prepare default tm tree, rc=%d", rc);
934                 return rc;
935         }
936
937         return rc;
938 }
939
940 int
941 roc_nix_tm_rlimit_sq(struct roc_nix *roc_nix, uint16_t qid, uint64_t rate)
942 {
943         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
944         struct nix_tm_shaper_profile profile;
945         struct mbox *mbox = (&nix->dev)->mbox;
946         struct nix_tm_node *node, *parent;
947
948         volatile uint64_t *reg, *regval;
949         struct nix_txschq_config *req;
950         uint16_t flags;
951         uint8_t k = 0;
952         int rc;
953
954         if ((nix->tm_tree == ROC_NIX_TM_USER) ||
955             !(nix->tm_flags & NIX_TM_HIERARCHY_ENA))
956                 return NIX_ERR_TM_INVALID_TREE;
957
958         node = nix_tm_node_search(nix, qid, nix->tm_tree);
959
960         /* check if we found a valid leaf node */
961         if (!node || !nix_tm_is_leaf(nix, node->lvl) || !node->parent ||
962             node->parent->hw_id == NIX_TM_HW_ID_INVALID)
963                 return NIX_ERR_TM_INVALID_NODE;
964
965         parent = node->parent;
966         flags = parent->flags;
967
968         req = mbox_alloc_msg_nix_txschq_cfg(mbox);
969         req->lvl = NIX_TXSCH_LVL_MDQ;
970         reg = req->reg;
971         regval = req->regval;
972
973         if (rate == 0) {
974                 k += nix_tm_sw_xoff_prep(parent, true, &reg[k], &regval[k]);
975                 flags &= ~NIX_TM_NODE_ENABLED;
976                 goto exit;
977         }
978
979         if (!(flags & NIX_TM_NODE_ENABLED)) {
980                 k += nix_tm_sw_xoff_prep(parent, false, &reg[k], &regval[k]);
981                 flags |= NIX_TM_NODE_ENABLED;
982         }
983
984         /* Use only PIR for rate limit */
985         memset(&profile, 0, sizeof(profile));
986         profile.peak.rate = rate;
987         /* Minimum burst of ~4us Bytes of Tx */
988         profile.peak.size = PLT_MAX((uint64_t)roc_nix_max_pkt_len(roc_nix),
989                                     (4ul * rate) / ((uint64_t)1E6 * 8));
990         if (!nix->tm_rate_min || nix->tm_rate_min > rate)
991                 nix->tm_rate_min = rate;
992
993         k += nix_tm_shaper_reg_prep(parent, &profile, &reg[k], &regval[k]);
994 exit:
995         req->num_regs = k;
996         rc = mbox_process(mbox);
997         if (rc)
998                 return rc;
999
1000         parent->flags = flags;
1001         return 0;
1002 }
1003
1004 void
1005 roc_nix_tm_fini(struct roc_nix *roc_nix)
1006 {
1007         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
1008         struct mbox *mbox = (&nix->dev)->mbox;
1009         struct nix_txsch_free_req *req;
1010         uint32_t tree_mask;
1011         uint8_t hw_lvl;
1012         int rc;
1013
1014         /* Xmit is assumed to be disabled */
1015         /* Free up resources already held */
1016         tree_mask = NIX_TM_TREE_MASK_ALL;
1017         rc = nix_tm_free_resources(roc_nix, tree_mask, false);
1018         if (rc)
1019                 plt_err("Failed to freeup existing nodes or rsrcs, rc=%d", rc);
1020
1021         /* Free all other hw resources */
1022         req = mbox_alloc_msg_nix_txsch_free(mbox);
1023         if (req == NULL)
1024                 return;
1025
1026         req->flags = TXSCHQ_FREE_ALL;
1027         rc = mbox_process(mbox);
1028         if (rc)
1029                 plt_err("Failed to freeup all res, rc=%d", rc);
1030
1031         for (hw_lvl = 0; hw_lvl < NIX_TXSCH_LVL_CNT; hw_lvl++) {
1032                 plt_bitmap_reset(nix->schq_bmp[hw_lvl]);
1033                 plt_bitmap_reset(nix->schq_contig_bmp[hw_lvl]);
1034                 nix->contig_rsvd[hw_lvl] = 0;
1035                 nix->discontig_rsvd[hw_lvl] = 0;
1036         }
1037
1038         /* Clear shaper profiles */
1039         nix_tm_clear_shaper_profiles(nix);
1040         nix->tm_tree = 0;
1041         nix->tm_flags &= ~NIX_TM_HIERARCHY_ENA;
1042 }
1043
1044 int
1045 roc_nix_tm_rsrc_count(struct roc_nix *roc_nix, uint16_t schq[ROC_TM_LVL_MAX])
1046 {
1047         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
1048         struct mbox *mbox = (&nix->dev)->mbox;
1049         struct free_rsrcs_rsp *rsp;
1050         uint8_t hw_lvl;
1051         int rc, i;
1052
1053         /* Get the current free resources */
1054         mbox_alloc_msg_free_rsrc_cnt(mbox);
1055         rc = mbox_process_msg(mbox, (void *)&rsp);
1056         if (rc)
1057                 return rc;
1058
1059         for (i = 0; i < ROC_TM_LVL_MAX; i++) {
1060                 hw_lvl = nix_tm_lvl2nix(nix, i);
1061                 if (hw_lvl == NIX_TXSCH_LVL_CNT)
1062                         continue;
1063
1064                 schq[i] = (nix->is_nix1 ? rsp->schq_nix1[hw_lvl] :
1065                                                 rsp->schq[hw_lvl]);
1066         }
1067
1068         return 0;
1069 }
1070
1071 void
1072 roc_nix_tm_rsrc_max(bool pf, uint16_t schq[ROC_TM_LVL_MAX])
1073 {
1074         uint8_t hw_lvl, i;
1075         uint16_t max;
1076
1077         for (i = 0; i < ROC_TM_LVL_MAX; i++) {
1078                 hw_lvl = pf ? nix_tm_lvl2nix_tl1_root(i) :
1079                                     nix_tm_lvl2nix_tl2_root(i);
1080
1081                 switch (hw_lvl) {
1082                 case NIX_TXSCH_LVL_SMQ:
1083                         max = (roc_model_is_cn9k() ?
1084                                              NIX_CN9K_TXSCH_LVL_SMQ_MAX :
1085                                              NIX_TXSCH_LVL_SMQ_MAX);
1086                         break;
1087                 case NIX_TXSCH_LVL_TL4:
1088                         max = NIX_TXSCH_LVL_TL4_MAX;
1089                         break;
1090                 case NIX_TXSCH_LVL_TL3:
1091                         max = NIX_TXSCH_LVL_TL3_MAX;
1092                         break;
1093                 case NIX_TXSCH_LVL_TL2:
1094                         max = pf ? NIX_TXSCH_LVL_TL2_MAX : 1;
1095                         break;
1096                 case NIX_TXSCH_LVL_TL1:
1097                         max = pf ? 1 : 0;
1098                         break;
1099                 default:
1100                         max = 0;
1101                         break;
1102                 }
1103                 schq[i] = max;
1104         }
1105 }
1106
1107 bool
1108 roc_nix_tm_root_has_sp(struct roc_nix *roc_nix)
1109 {
1110         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
1111
1112         if (nix->tm_flags & NIX_TM_TL1_NO_SP)
1113                 return false;
1114         return true;
1115 }