common/cnxk: support add/delete NIX TM node
[dpdk.git] / drivers / common / cnxk / roc_nix_tm_utils.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4
5 #include "roc_api.h"
6 #include "roc_priv.h"
7
8 uint16_t
9 nix_tm_lvl2nix_tl1_root(uint32_t lvl)
10 {
11         switch (lvl) {
12         case ROC_TM_LVL_ROOT:
13                 return NIX_TXSCH_LVL_TL1;
14         case ROC_TM_LVL_SCH1:
15                 return NIX_TXSCH_LVL_TL2;
16         case ROC_TM_LVL_SCH2:
17                 return NIX_TXSCH_LVL_TL3;
18         case ROC_TM_LVL_SCH3:
19                 return NIX_TXSCH_LVL_TL4;
20         case ROC_TM_LVL_SCH4:
21                 return NIX_TXSCH_LVL_SMQ;
22         default:
23                 return NIX_TXSCH_LVL_CNT;
24         }
25 }
26
27 uint16_t
28 nix_tm_lvl2nix_tl2_root(uint32_t lvl)
29 {
30         switch (lvl) {
31         case ROC_TM_LVL_ROOT:
32                 return NIX_TXSCH_LVL_TL2;
33         case ROC_TM_LVL_SCH1:
34                 return NIX_TXSCH_LVL_TL3;
35         case ROC_TM_LVL_SCH2:
36                 return NIX_TXSCH_LVL_TL4;
37         case ROC_TM_LVL_SCH3:
38                 return NIX_TXSCH_LVL_SMQ;
39         default:
40                 return NIX_TXSCH_LVL_CNT;
41         }
42 }
43
44 uint16_t
45 nix_tm_lvl2nix(struct nix *nix, uint32_t lvl)
46 {
47         if (nix_tm_have_tl1_access(nix))
48                 return nix_tm_lvl2nix_tl1_root(lvl);
49         else
50                 return nix_tm_lvl2nix_tl2_root(lvl);
51 }
52
53
54 struct nix_tm_shaper_profile *
55 nix_tm_shaper_profile_search(struct nix *nix, uint32_t id)
56 {
57         struct nix_tm_shaper_profile *profile;
58
59         TAILQ_FOREACH(profile, &nix->shaper_profile_list, shaper) {
60                 if (profile->id == id)
61                         return profile;
62         }
63         return NULL;
64 }
65
66 struct nix_tm_node *
67 nix_tm_node_search(struct nix *nix, uint32_t node_id, enum roc_nix_tm_tree tree)
68 {
69         struct nix_tm_node_list *list;
70         struct nix_tm_node *node;
71
72         list = nix_tm_node_list(nix, tree);
73         TAILQ_FOREACH(node, list, node) {
74                 if (node->id == node_id)
75                         return node;
76         }
77         return NULL;
78 }
79
80 static uint16_t
81 nix_tm_max_prio(struct nix *nix, uint16_t hw_lvl)
82 {
83         if (hw_lvl >= NIX_TXSCH_LVL_CNT)
84                 return 0;
85
86         /* MDQ does not support SP */
87         if (hw_lvl == NIX_TXSCH_LVL_MDQ)
88                 return 0;
89
90         /* PF's TL1 with VF's enabled does not support SP */
91         if (hw_lvl == NIX_TXSCH_LVL_TL1 && (!nix_tm_have_tl1_access(nix) ||
92                                             (nix->tm_flags & NIX_TM_TL1_NO_SP)))
93                 return 0;
94
95         return NIX_TM_TLX_SP_PRIO_MAX - 1;
96 }
97
98 int
99 nix_tm_validate_prio(struct nix *nix, uint32_t lvl, uint32_t parent_id,
100                      uint32_t priority, enum roc_nix_tm_tree tree)
101 {
102         uint8_t priorities[NIX_TM_TLX_SP_PRIO_MAX];
103         struct nix_tm_node_list *list;
104         struct nix_tm_node *node;
105         uint32_t rr_num = 0;
106         int i;
107
108         list = nix_tm_node_list(nix, tree);
109         /* Validate priority against max */
110         if (priority > nix_tm_max_prio(nix, nix_tm_lvl2nix(nix, lvl - 1)))
111                 return NIX_ERR_TM_PRIO_EXCEEDED;
112
113         if (parent_id == ROC_NIX_TM_NODE_ID_INVALID)
114                 return 0;
115
116         memset(priorities, 0, sizeof(priorities));
117         priorities[priority] = 1;
118
119         TAILQ_FOREACH(node, list, node) {
120                 if (!node->parent)
121                         continue;
122
123                 if (node->parent->id != parent_id)
124                         continue;
125
126                 priorities[node->priority]++;
127         }
128
129         for (i = 0; i < NIX_TM_TLX_SP_PRIO_MAX; i++)
130                 if (priorities[i] > 1)
131                         rr_num++;
132
133         /* At max, one rr groups per parent */
134         if (rr_num > 1)
135                 return NIX_ERR_TM_MULTIPLE_RR_GROUPS;
136
137         /* Check for previous priority to avoid holes in priorities */
138         if (priority && !priorities[priority - 1])
139                 return NIX_ERR_TM_PRIO_ORDER;
140
141         return 0;
142 }
143
144 uint8_t
145 nix_tm_sw_xoff_prep(struct nix_tm_node *node, bool enable,
146                     volatile uint64_t *reg, volatile uint64_t *regval)
147 {
148         uint32_t hw_lvl = node->hw_lvl;
149         uint32_t schq = node->hw_id;
150         uint8_t k = 0;
151
152         plt_tm_dbg("sw xoff config node %s(%u) lvl %u id %u, enable %u (%p)",
153                    nix_tm_hwlvl2str(hw_lvl), schq, node->lvl, node->id, enable,
154                    node);
155
156         regval[k] = enable;
157
158         switch (hw_lvl) {
159         case NIX_TXSCH_LVL_MDQ:
160                 reg[k] = NIX_AF_MDQX_SW_XOFF(schq);
161                 k++;
162                 break;
163         case NIX_TXSCH_LVL_TL4:
164                 reg[k] = NIX_AF_TL4X_SW_XOFF(schq);
165                 k++;
166                 break;
167         case NIX_TXSCH_LVL_TL3:
168                 reg[k] = NIX_AF_TL3X_SW_XOFF(schq);
169                 k++;
170                 break;
171         case NIX_TXSCH_LVL_TL2:
172                 reg[k] = NIX_AF_TL2X_SW_XOFF(schq);
173                 k++;
174                 break;
175         case NIX_TXSCH_LVL_TL1:
176                 reg[k] = NIX_AF_TL1X_SW_XOFF(schq);
177                 k++;
178                 break;
179         default:
180                 break;
181         }
182
183         return k;
184 }
185
186 uint16_t
187 nix_tm_resource_avail(struct nix *nix, uint8_t hw_lvl, bool contig)
188 {
189         uint32_t pos = 0, start_pos = 0;
190         struct plt_bitmap *bmp;
191         uint16_t count = 0;
192         uint64_t slab = 0;
193
194         bmp = contig ? nix->schq_contig_bmp[hw_lvl] : nix->schq_bmp[hw_lvl];
195         plt_bitmap_scan_init(bmp);
196
197         if (!plt_bitmap_scan(bmp, &pos, &slab))
198                 return count;
199
200         /* Count bit set */
201         start_pos = pos;
202         do {
203                 count += __builtin_popcountll(slab);
204                 if (!plt_bitmap_scan(bmp, &pos, &slab))
205                         break;
206         } while (pos != start_pos);
207
208         return count;
209 }
210
211 int
212 roc_nix_tm_node_lvl(struct roc_nix *roc_nix, uint32_t node_id)
213 {
214         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
215         struct nix_tm_node *node;
216
217         node = nix_tm_node_search(nix, node_id, ROC_NIX_TM_USER);
218         if (!node)
219                 return NIX_ERR_TM_INVALID_NODE;
220
221         return node->lvl;
222 }
223
224 struct roc_nix_tm_node *
225 roc_nix_tm_node_get(struct roc_nix *roc_nix, uint32_t node_id)
226 {
227         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
228         struct nix_tm_node *node;
229
230         node = nix_tm_node_search(nix, node_id, ROC_NIX_TM_USER);
231         return (struct roc_nix_tm_node *)node;
232 }
233
234 struct roc_nix_tm_node *
235 roc_nix_tm_node_next(struct roc_nix *roc_nix, struct roc_nix_tm_node *__prev)
236 {
237         struct nix_tm_node *prev = (struct nix_tm_node *)__prev;
238         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
239         struct nix_tm_node_list *list;
240
241         list = nix_tm_node_list(nix, ROC_NIX_TM_USER);
242
243         /* HEAD of the list */
244         if (!prev)
245                 return (struct roc_nix_tm_node *)TAILQ_FIRST(list);
246
247         /* Next entry */
248         if (prev->tree != ROC_NIX_TM_USER)
249                 return NULL;
250
251         return (struct roc_nix_tm_node *)TAILQ_NEXT(prev, node);
252 }
253
254 struct nix_tm_node *
255 nix_tm_node_alloc(void)
256 {
257         struct nix_tm_node *node;
258
259         node = plt_zmalloc(sizeof(struct nix_tm_node), 0);
260         if (!node)
261                 return NULL;
262
263         node->free_fn = plt_free;
264         return node;
265 }
266
267 void
268 nix_tm_node_free(struct nix_tm_node *node)
269 {
270         if (!node || node->free_fn == NULL)
271                 return;
272
273         (node->free_fn)(node);
274 }