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