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