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