Branch data Line data Source code
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 : : static inline int
9 : : bitmap_ctzll(uint64_t slab)
10 : : {
11 : 0 : if (slab == 0)
12 : : return 0;
13 : :
14 : 0 : return plt_ctz64(slab);
15 : : }
16 : :
17 : : void
18 : 0 : nix_tm_clear_shaper_profiles(struct nix *nix)
19 : : {
20 : : struct nix_tm_shaper_profile *shaper_profile, *tmp;
21 : : struct nix_tm_shaper_profile_list *list;
22 : :
23 : : list = &nix->shaper_profile_list;
24 [ # # ]: 0 : PLT_TAILQ_FOREACH_SAFE(shaper_profile, list, shaper, tmp) {
25 [ # # ]: 0 : if (shaper_profile->ref_cnt)
26 : 0 : plt_warn("Shaper profile %u has non zero references",
27 : : shaper_profile->id);
28 [ # # ]: 0 : TAILQ_REMOVE(&nix->shaper_profile_list, shaper_profile, shaper);
29 : 0 : nix_tm_shaper_profile_free(shaper_profile);
30 : : }
31 : 0 : }
32 : :
33 : : static int
34 : 0 : nix_tm_node_reg_conf(struct nix *nix, struct nix_tm_node *node)
35 : : {
36 : : uint64_t regval_mask[MAX_REGS_PER_MBOX_MSG];
37 : : uint64_t regval[MAX_REGS_PER_MBOX_MSG];
38 : : struct nix_tm_shaper_profile *profile;
39 : : uint64_t reg[MAX_REGS_PER_MBOX_MSG];
40 : 0 : struct mbox *mbox = (&nix->dev)->mbox;
41 : : struct nix_txschq_config *req;
42 : : int rc = -EFAULT;
43 : : uint32_t hw_lvl;
44 : : uint8_t k = 0;
45 : :
46 : : memset(regval, 0, sizeof(regval));
47 : : memset(regval_mask, 0, sizeof(regval_mask));
48 : :
49 : 0 : profile = nix_tm_shaper_profile_search(nix, node->shaper_profile_id);
50 [ # # ]: 0 : hw_lvl = node->hw_lvl;
51 : :
52 : : /* Need this trigger to configure TL1 */
53 [ # # # # ]: 0 : if (!nix_tm_have_tl1_access(nix) && hw_lvl == NIX_TXSCH_LVL_TL2) {
54 : : /* Prepare default conf for TL1 */
55 : 0 : req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox));
56 : 0 : req->lvl = NIX_TXSCH_LVL_TL1;
57 : :
58 : 0 : k = nix_tm_tl1_default_prep(nix, node->parent_hw_id, req->reg,
59 : 0 : req->regval);
60 : 0 : req->num_regs = k;
61 : 0 : rc = mbox_process(mbox);
62 : : mbox_put(mbox);
63 [ # # ]: 0 : if (rc)
64 : 0 : goto error;
65 : : }
66 : :
67 : : /* Prepare topology config */
68 : 0 : k = nix_tm_topology_reg_prep(nix, node, reg, regval, regval_mask);
69 : :
70 : : /* Prepare schedule config */
71 : 0 : k += nix_tm_sched_reg_prep(nix, node, ®[k], ®val[k]);
72 : :
73 : : /* Prepare shaping config */
74 : 0 : k += nix_tm_shaper_reg_prep(node, profile, ®[k], ®val[k]);
75 : :
76 [ # # ]: 0 : if (!k)
77 : : return 0;
78 : :
79 : : /* Copy and send config mbox */
80 : 0 : req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox));
81 : 0 : req->lvl = hw_lvl;
82 : 0 : req->num_regs = k;
83 : :
84 : 0 : mbox_memcpy(req->reg, reg, sizeof(uint64_t) * k);
85 : 0 : mbox_memcpy(req->regval, regval, sizeof(uint64_t) * k);
86 : 0 : mbox_memcpy(req->regval_mask, regval_mask, sizeof(uint64_t) * k);
87 : :
88 : 0 : rc = mbox_process(mbox);
89 : : mbox_put(mbox);
90 [ # # ]: 0 : if (rc)
91 : 0 : goto error;
92 : :
93 : : return 0;
94 : 0 : error:
95 : 0 : plt_err("Txschq conf failed for node %p, rc=%d", node, rc);
96 : 0 : return rc;
97 : : }
98 : :
99 : : int
100 : 0 : nix_tm_txsch_reg_config(struct nix *nix, enum roc_nix_tm_tree tree)
101 : : {
102 : : struct nix_tm_node_list *list;
103 : : struct nix_tm_node *node;
104 : : uint32_t hw_lvl;
105 : : int rc = 0;
106 : :
107 : : list = nix_tm_node_list(nix, tree);
108 : :
109 [ # # ]: 0 : for (hw_lvl = 0; hw_lvl <= nix->tm_root_lvl; hw_lvl++) {
110 [ # # ]: 0 : TAILQ_FOREACH(node, list, node) {
111 [ # # ]: 0 : if (node->hw_lvl != hw_lvl)
112 : 0 : continue;
113 : :
114 : : /* Only one TL3/TL2 Link config should have BP enable
115 : : * set per channel only for PF or lbk vf.
116 : : */
117 : 0 : node->bp_capa = 0;
118 [ # # # # ]: 0 : if (!nix->sdp_link && node->hw_lvl == nix->tm_link_cfg_lvl)
119 : 0 : node->bp_capa = 1;
120 : :
121 : 0 : rc = nix_tm_node_reg_conf(nix, node);
122 [ # # ]: 0 : if (rc)
123 : 0 : goto exit;
124 : : }
125 : : }
126 : 0 : exit:
127 : 0 : return rc;
128 : : }
129 : :
130 : : int
131 : 0 : nix_tm_update_parent_info(struct nix *nix, enum roc_nix_tm_tree tree)
132 : : {
133 : : struct nix_tm_node *child, *parent;
134 : : struct nix_tm_node_list *list;
135 : : uint32_t rr_prio, max_prio;
136 : : uint32_t rr_num = 0;
137 : :
138 : : list = nix_tm_node_list(nix, tree);
139 : :
140 : : /* Release all the node hw resources locally
141 : : * if parent marked as dirty and resource exists.
142 : : */
143 [ # # ]: 0 : TAILQ_FOREACH(child, list, node) {
144 : : /* Release resource only if parent direct hierarchy changed */
145 [ # # # # ]: 0 : if (child->flags & NIX_TM_NODE_HWRES && child->parent &&
146 [ # # ]: 0 : child->parent->child_realloc) {
147 : 0 : nix_tm_free_node_resource(nix, child);
148 : : }
149 : 0 : child->max_prio = UINT32_MAX;
150 : : }
151 : :
152 [ # # ]: 0 : TAILQ_FOREACH(parent, list, node) {
153 : : /* Count group of children of same priority i.e are RR */
154 : 0 : rr_num = nix_tm_check_rr(nix, parent->id, tree, &rr_prio,
155 : : &max_prio);
156 : :
157 : : /* Assuming that multiple RR groups are
158 : : * not configured based on capability.
159 : : */
160 : 0 : parent->rr_prio = rr_prio;
161 : 0 : parent->rr_num = rr_num;
162 : 0 : parent->max_prio = max_prio;
163 : : }
164 : :
165 : 0 : return 0;
166 : : }
167 : :
168 : : static int
169 : : nix_tm_root_node_get(struct nix *nix, int tree)
170 : : {
171 : : struct nix_tm_node_list *list = nix_tm_node_list(nix, tree);
172 : : struct nix_tm_node *tm_node;
173 : :
174 [ # # ]: 0 : TAILQ_FOREACH(tm_node, list, node) {
175 [ # # ]: 0 : if (tm_node->hw_lvl == nix->tm_root_lvl)
176 : : return 1;
177 : : }
178 : :
179 : : return 0;
180 : : }
181 : :
182 : : int
183 : 0 : nix_tm_node_add(struct roc_nix *roc_nix, struct nix_tm_node *node)
184 : : {
185 : : struct nix *nix = roc_nix_to_nix_priv(roc_nix);
186 : : struct nix_tm_shaper_profile *profile;
187 : : uint32_t node_id, parent_id, lvl;
188 : : struct nix_tm_node *parent_node;
189 : : uint32_t priority, profile_id;
190 : : uint8_t hw_lvl, exp_next_lvl;
191 : : enum roc_nix_tm_tree tree;
192 : : int rc;
193 : :
194 : 0 : node_id = node->id;
195 : 0 : priority = node->priority;
196 : 0 : parent_id = node->parent_id;
197 : 0 : profile_id = node->shaper_profile_id;
198 : 0 : lvl = node->lvl;
199 : 0 : tree = node->tree;
200 : :
201 : 0 : plt_tm_dbg("Add node %s lvl %u id %u, prio 0x%x weight 0x%x "
202 : : "parent %u profile 0x%x tree %u",
203 : : nix_tm_hwlvl2str(nix_tm_lvl2nix(nix, lvl)), lvl, node_id,
204 : : priority, node->weight, parent_id, profile_id, tree);
205 : :
206 [ # # ]: 0 : if (tree >= ROC_NIX_TM_TREE_MAX)
207 : : return NIX_ERR_PARAM;
208 : :
209 : : /* Translate sw level id's to nix hw level id's */
210 : 0 : hw_lvl = nix_tm_lvl2nix(nix, lvl);
211 [ # # # # : 0 : if (hw_lvl == NIX_TXSCH_LVL_CNT && !nix_tm_is_leaf(nix, lvl))
# # ]
212 : : return NIX_ERR_TM_INVALID_LVL;
213 : :
214 : : /* Leaf nodes have to be same priority */
215 [ # # # # : 0 : if (nix_tm_is_leaf(nix, lvl) && priority != 0)
# # ]
216 : : return NIX_ERR_TM_INVALID_PRIO;
217 : :
218 : 0 : parent_node = nix_tm_node_search(nix, parent_id, tree);
219 : :
220 [ # # ]: 0 : if (node_id < nix->nb_tx_queues)
221 : : exp_next_lvl = NIX_TXSCH_LVL_SMQ;
222 : : else
223 : 0 : exp_next_lvl = hw_lvl + 1;
224 : :
225 : : /* Check if there is no parent node yet */
226 [ # # # # ]: 0 : if (hw_lvl != nix->tm_root_lvl &&
227 [ # # ]: 0 : (!parent_node || parent_node->hw_lvl != exp_next_lvl))
228 : : return NIX_ERR_TM_INVALID_PARENT;
229 : :
230 : : /* Check if a node already exists */
231 [ # # ]: 0 : if (nix_tm_node_search(nix, node_id, tree))
232 : : return NIX_ERR_TM_NODE_EXISTS;
233 : :
234 : : /* Check if root node exists */
235 [ # # # # ]: 0 : if (hw_lvl == nix->tm_root_lvl && nix_tm_root_node_get(nix, tree))
236 : : return NIX_ERR_TM_NODE_EXISTS;
237 : :
238 : 0 : profile = nix_tm_shaper_profile_search(nix, profile_id);
239 [ # # ]: 0 : if (!nix_tm_is_leaf(nix, lvl)) {
240 : : /* Check if shaper profile exists for non leaf node */
241 [ # # ]: 0 : if (!profile && profile_id != ROC_NIX_TM_SHAPER_PROFILE_NONE)
242 : : return NIX_ERR_TM_INVALID_SHAPER_PROFILE;
243 : :
244 : : /* Packet mode in profile should match with that of tm node */
245 [ # # # # ]: 0 : if (profile && profile->pkt_mode != node->pkt_mode)
246 : : return NIX_ERR_TM_PKT_MODE_MISMATCH;
247 : : }
248 : :
249 : : /* Check if there is second DWRR already in siblings or holes in prio */
250 : 0 : rc = nix_tm_validate_prio(nix, lvl, parent_id, priority, tree);
251 [ # # ]: 0 : if (rc)
252 : : return rc;
253 : :
254 [ # # # # ]: 0 : if (node->weight > roc_nix_tm_max_sched_wt_get())
255 : : return NIX_ERR_TM_WEIGHT_EXCEED;
256 : :
257 : 0 : node->hw_lvl = nix_tm_lvl2nix(nix, lvl);
258 : 0 : node->rr_prio = 0xF;
259 : 0 : node->max_prio = UINT32_MAX;
260 : 0 : node->hw_id = NIX_TM_HW_ID_INVALID;
261 : 0 : node->flags = 0;
262 : :
263 [ # # ]: 0 : if (profile)
264 : 0 : profile->ref_cnt++;
265 : :
266 : 0 : node->parent = parent_node;
267 [ # # ]: 0 : if (parent_node)
268 : 0 : parent_node->child_realloc = true;
269 : 0 : node->parent_hw_id = NIX_TM_HW_ID_INVALID;
270 : :
271 [ # # # # : 0 : TAILQ_INSERT_TAIL(&nix->trees[tree], node, node);
# # ]
272 : 0 : plt_tm_dbg("Added node %s lvl %u id %u (%p)",
273 : : nix_tm_hwlvl2str(node->hw_lvl), lvl, node_id, node);
274 : 0 : return 0;
275 : : }
276 : :
277 : : int
278 : 0 : nix_tm_clear_path_xoff(struct nix *nix, struct nix_tm_node *node)
279 : : {
280 : 0 : struct mbox *mbox = mbox_get((&nix->dev)->mbox);
281 : : struct nix_txschq_config *req;
282 : : struct nix_tm_node *p;
283 : : int rc;
284 : :
285 : : /* Enable nodes in path for flush to succeed */
286 [ # # # # ]: 0 : if (!nix_tm_is_leaf(nix, node->lvl))
287 : : p = node;
288 : : else
289 : 0 : p = node->parent;
290 [ # # ]: 0 : while (p) {
291 [ # # ]: 0 : if (!(p->flags & NIX_TM_NODE_ENABLED) &&
292 : : (p->flags & NIX_TM_NODE_HWRES)) {
293 : 0 : req = mbox_alloc_msg_nix_txschq_cfg(mbox);
294 : 0 : req->lvl = p->hw_lvl;
295 : 0 : req->num_regs = nix_tm_sw_xoff_prep(p, false, req->reg,
296 : 0 : req->regval);
297 : 0 : rc = mbox_process(mbox);
298 [ # # ]: 0 : if (rc)
299 : 0 : goto exit;
300 : :
301 : 0 : p->flags |= NIX_TM_NODE_ENABLED;
302 : : }
303 : 0 : p = p->parent;
304 : : }
305 : :
306 : : rc = 0;
307 : 0 : exit:
308 : : mbox_put(mbox);
309 : 0 : return rc;
310 : : }
311 : :
312 : : int
313 : 0 : nix_tm_bp_config_set(struct roc_nix *roc_nix, uint16_t sq, uint16_t tc,
314 : : bool enable)
315 : : {
316 : : struct nix *nix = roc_nix_to_nix_priv(roc_nix);
317 : 0 : enum roc_nix_tm_tree tree = nix->tm_tree;
318 : 0 : struct mbox *mbox = (&nix->dev)->mbox;
319 : : struct nix_txschq_config *req = NULL;
320 : : struct nix_tm_node_list *list;
321 : 0 : uint16_t link = nix->tx_link;
322 : : struct nix_tm_node *sq_node;
323 : : struct nix_tm_node *parent;
324 : : struct nix_tm_node *node;
325 : : struct roc_nix_sq *sq_s;
326 : : uint16_t rel_chan = 0;
327 : : uint8_t parent_lvl;
328 : : uint8_t k = 0;
329 : : int rc = 0, i;
330 : :
331 [ # # ]: 0 : if (roc_nix_is_sdp(roc_nix))
332 : : return 0;
333 : :
334 : 0 : sq_s = nix->sqs[sq];
335 [ # # ]: 0 : if (!sq_s)
336 : : return -ENOENT;
337 : :
338 : 0 : sq_node = nix_tm_node_search(nix, sq, nix->tm_tree);
339 [ # # ]: 0 : if (!sq_node)
340 : : return -ENOENT;
341 : :
342 [ # # ]: 0 : parent_lvl = (nix_tm_have_tl1_access(nix) ? ROC_TM_LVL_SCH2 :
343 : : ROC_TM_LVL_SCH1);
344 : :
345 : 0 : parent = sq_node->parent;
346 [ # # ]: 0 : while (parent) {
347 [ # # ]: 0 : if (parent->lvl == parent_lvl)
348 : : break;
349 : :
350 : 0 : parent = parent->parent;
351 : : }
352 [ # # ]: 0 : if (!parent)
353 : : return -ENOENT;
354 : :
355 : : list = nix_tm_node_list(nix, tree);
356 : :
357 : : /* Get relative channel if loopback */
358 [ # # ]: 0 : if (roc_nix_is_lbk(roc_nix))
359 : 0 : rel_chan = nix_tm_lbk_relchan_get(nix);
360 : : else
361 : : rel_chan = tc;
362 : :
363 : : /* Enable request, parent rel chan already configured */
364 [ # # # # : 0 : if (enable && parent->rel_chan != NIX_TM_CHAN_INVALID &&
# # ]
365 : : parent->rel_chan != rel_chan) {
366 : 0 : plt_err("SQ %d: parent node TL3 id %d already has rel_chan %d set",
367 : : sq, parent->hw_id, parent->rel_chan);
368 : : rc = -EINVAL;
369 : 0 : goto err;
370 : : }
371 : :
372 : : /* No action if enable request for a non participating SQ. This case is
373 : : * required to handle post flush where TCs should be reconfigured after
374 : : * pre flush.
375 : : */
376 [ # # # # : 0 : if (enable && sq_s->tc == ROC_NIX_PFC_CLASS_INVALID &&
# # ]
377 : : tc == ROC_NIX_PFC_CLASS_INVALID)
378 : : return 0;
379 : :
380 : : /* Find the parent TL3 */
381 [ # # ]: 0 : TAILQ_FOREACH(node, list, node) {
382 [ # # ]: 0 : if (node->hw_lvl != nix->tm_link_cfg_lvl)
383 : 0 : continue;
384 : :
385 [ # # # # ]: 0 : if (!(node->flags & NIX_TM_NODE_HWRES) || !node->bp_capa)
386 : 0 : continue;
387 : :
388 : : /* Restrict sharing of TL3 across the queues */
389 [ # # # # ]: 0 : if (enable && node != parent && node->rel_chan == rel_chan) {
390 : 0 : plt_warn("SQ %d: siblng node TL3 %d already has %d(%d) tc value set",
391 : : sq, node->hw_id, tc, rel_chan);
392 : 0 : return -EEXIST;
393 : : }
394 : : }
395 : :
396 : : /* Allocating TL3 request */
397 : 0 : req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox));
398 : 0 : req->lvl = nix->tm_link_cfg_lvl;
399 : : k = 0;
400 : :
401 : : /* Enable PFC/pause on the identified TL3 */
402 : 0 : req->reg[k] = NIX_AF_TL3_TL2X_LINKX_CFG(parent->hw_id, link);
403 [ # # ]: 0 : req->regval[k] = enable ? rel_chan : 0;
404 [ # # ]: 0 : req->regval[k] |= enable ? BIT_ULL(13) : 0;
405 : 0 : req->regval_mask[k] = ~(BIT_ULL(13) | GENMASK_ULL(7, 0));
406 : : k++;
407 : :
408 : 0 : req->num_regs = k;
409 : 0 : rc = mbox_process(mbox);
410 [ # # ]: 0 : if (rc)
411 : 0 : goto err;
412 : :
413 [ # # ]: 0 : parent->rel_chan = enable ? rel_chan : NIX_TM_CHAN_INVALID;
414 [ # # ]: 0 : sq_s->tc = enable ? tc : ROC_NIX_PFC_CLASS_INVALID;
415 : : /* Clear other SQ's with same TC i.e same parent node */
416 [ # # # # ]: 0 : for (i = 0; !enable && i < nix->nb_tx_queues; i++) {
417 [ # # # # ]: 0 : if (nix->sqs[i] && nix->sqs[i]->tc == tc)
418 : 0 : nix->sqs[i]->tc = ROC_NIX_PFC_CLASS_INVALID;
419 : : }
420 : :
421 : : rc = 0;
422 [ # # ]: 0 : plt_tm_dbg("SQ %u: TL3 %d TC %u %s",
423 : : sq, parent->hw_id, tc, enable ? "enabled" : "disabled");
424 : 0 : goto exit;
425 : 0 : err:
426 [ # # ]: 0 : plt_err("Failed to %s bp on link %u, rc=%d(%s)",
427 : : enable ? "enable" : "disable", link, rc, roc_error_msg_get(rc));
428 : 0 : exit:
429 : : mbox_put(mbox);
430 : 0 : return rc;
431 : : }
432 : :
433 : : int
434 : 0 : nix_tm_bp_config_get(struct roc_nix *roc_nix, bool *is_enabled)
435 : : {
436 : : struct nix *nix = roc_nix_to_nix_priv(roc_nix);
437 : : struct nix_txschq_config *req = NULL, *rsp;
438 : 0 : enum roc_nix_tm_tree tree = nix->tm_tree;
439 : 0 : struct mbox *mbox = mbox_get((&nix->dev)->mbox);
440 : : struct nix_tm_node_list *list;
441 : : struct nix_tm_node *node;
442 : : bool found = false;
443 : : uint8_t enable = 1;
444 : : uint8_t k = 0, i;
445 : : uint16_t link;
446 : : int rc = 0;
447 : :
448 : : list = nix_tm_node_list(nix, tree);
449 : 0 : link = nix->tx_link;
450 : :
451 [ # # ]: 0 : TAILQ_FOREACH(node, list, node) {
452 [ # # ]: 0 : if (node->hw_lvl != nix->tm_link_cfg_lvl)
453 : 0 : continue;
454 : :
455 [ # # # # ]: 0 : if (!(node->flags & NIX_TM_NODE_HWRES) || !node->bp_capa)
456 : 0 : continue;
457 : :
458 : : found = true;
459 [ # # ]: 0 : if (!req) {
460 : 0 : req = mbox_alloc_msg_nix_txschq_cfg(mbox);
461 : 0 : req->read = 1;
462 : 0 : req->lvl = nix->tm_link_cfg_lvl;
463 : : k = 0;
464 : : }
465 : :
466 : 0 : req->reg[k] = NIX_AF_TL3_TL2X_LINKX_CFG(node->hw_id, link);
467 : 0 : k++;
468 : :
469 [ # # ]: 0 : if (k >= MAX_REGS_PER_MBOX_MSG) {
470 : 0 : req->num_regs = k;
471 : : rc = mbox_process_msg(mbox, (void **)&rsp);
472 [ # # # # ]: 0 : if (rc || rsp->num_regs != k)
473 : 0 : goto err;
474 : : req = NULL;
475 : :
476 : : /* Report it as enabled only if enabled or all */
477 [ # # ]: 0 : for (i = 0; i < k; i++)
478 : 0 : enable &= !!(rsp->regval[i] & BIT_ULL(13));
479 : : }
480 : : }
481 : :
482 [ # # ]: 0 : if (req) {
483 : 0 : req->num_regs = k;
484 : : rc = mbox_process_msg(mbox, (void **)&rsp);
485 [ # # ]: 0 : if (rc)
486 : 0 : goto err;
487 : : /* Report it as enabled only if enabled or all */
488 [ # # ]: 0 : for (i = 0; i < k; i++)
489 : 0 : enable &= !!(rsp->regval[i] & BIT_ULL(13));
490 : : }
491 : :
492 : 0 : *is_enabled = found ? !!enable : false;
493 : : rc = 0;
494 : 0 : goto exit;
495 : 0 : err:
496 : 0 : plt_err("Failed to get bp status on link %u, rc=%d(%s)", link, rc,
497 : : roc_error_msg_get(rc));
498 : 0 : exit:
499 : : mbox_put(mbox);
500 : 0 : return rc;
501 : : }
502 : :
503 : : int
504 : 0 : nix_tm_smq_xoff(struct nix *nix, struct nix_tm_node *node, bool enable)
505 : : {
506 : 0 : struct mbox *mbox = (&nix->dev)->mbox;
507 : : struct nix_txschq_config *req;
508 : : uint16_t smq;
509 : : int rc;
510 : :
511 : 0 : smq = node->hw_id;
512 [ # # ]: 0 : plt_tm_dbg("Setting SMQ %u XOFF/FLUSH to %s", smq,
513 : : enable ? "enable" : "disable");
514 : :
515 : 0 : rc = nix_tm_clear_path_xoff(nix, node);
516 [ # # ]: 0 : if (rc)
517 : : return rc;
518 : :
519 : 0 : req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox));
520 : 0 : req->lvl = NIX_TXSCH_LVL_SMQ;
521 : 0 : req->num_regs = 1;
522 : :
523 : 0 : req->reg[0] = NIX_AF_SMQX_CFG(smq);
524 [ # # ]: 0 : req->regval[0] = enable ? (BIT_ULL(50) | BIT_ULL(49)) : 0;
525 : 0 : req->regval_mask[0] =
526 [ # # ]: 0 : enable ? ~(BIT_ULL(50) | BIT_ULL(49)) : ~BIT_ULL(50);
527 : :
528 : 0 : rc = mbox_process(mbox);
529 : : mbox_put(mbox);
530 : 0 : return rc;
531 : : }
532 : :
533 : : int
534 : 0 : nix_tm_leaf_data_get(struct nix *nix, uint16_t sq, uint32_t *rr_quantum,
535 : : uint16_t *smq)
536 : : {
537 : : struct nix_tm_node *node;
538 : : int rc;
539 : :
540 : 0 : node = nix_tm_node_search(nix, sq, nix->tm_tree);
541 : :
542 : : /* Check if we found a valid leaf node */
543 [ # # # # : 0 : if (!node || !nix_tm_is_leaf(nix, node->lvl) || !node->parent ||
# # # # ]
544 [ # # ]: 0 : node->parent->hw_id == NIX_TM_HW_ID_INVALID) {
545 : : return -EIO;
546 : : }
547 : :
548 : : /* Get SMQ Id of leaf node's parent */
549 : 0 : *smq = node->parent->hw_id;
550 [ # # ]: 0 : *rr_quantum = nix_tm_weight_to_rr_quantum(node->weight);
551 : :
552 : 0 : rc = nix_tm_smq_xoff(nix, node->parent, false);
553 [ # # ]: 0 : if (rc)
554 : : return rc;
555 : 0 : node->flags |= NIX_TM_NODE_ENABLED;
556 : 0 : return 0;
557 : : }
558 : :
559 : : int
560 : 0 : roc_nix_tm_sq_flush_spin(struct roc_nix_sq *sq)
561 : : {
562 : 0 : struct nix *nix = roc_nix_to_nix_priv(sq->roc_nix);
563 : : uint16_t sqb_cnt, head_off, tail_off;
564 : : uint64_t wdata, val, prev;
565 : : uint16_t qid = sq->qid;
566 : : int64_t *regaddr;
567 : : uint64_t timeout; /* 10's of usec */
568 : :
569 : : /* Wait for enough time based on shaper min rate */
570 : 0 : timeout = (sq->nb_desc * roc_nix_max_pkt_len(sq->roc_nix) * 8 * 1E5);
571 : : /* Wait for worst case scenario of this SQ being last priority
572 : : * and so have to wait for all other SQ's drain out by their own.
573 : : */
574 : 0 : timeout = timeout * nix->nb_tx_queues;
575 : 0 : timeout = timeout / nix->tm_rate_min;
576 [ # # ]: 0 : if (!timeout)
577 : : timeout = 10000;
578 : :
579 : : wdata = ((uint64_t)qid << 32);
580 : : regaddr = (int64_t *)(nix->base + NIX_LF_SQ_OP_STATUS);
581 : : val = roc_atomic64_add_nosync(wdata, regaddr);
582 : :
583 : : /* Spin multiple iterations as "sq->fc_cache_pkts" can still
584 : : * have space to send pkts even though fc_mem is disabled
585 : : */
586 : :
587 : : while (true) {
588 : : prev = val;
589 : 0 : plt_delay_us(10);
590 : : val = roc_atomic64_add_nosync(wdata, regaddr);
591 : : /* Continue on error */
592 : : if (val & BIT_ULL(63))
593 : : continue;
594 : :
595 : : if (prev != val)
596 : : continue;
597 : :
598 : : sqb_cnt = val & 0xFFFF;
599 : : head_off = (val >> 20) & 0x3F;
600 : : tail_off = (val >> 28) & 0x3F;
601 : :
602 : : /* SQ reached quiescent state */
603 : 0 : if (sqb_cnt <= 1 && head_off == tail_off &&
604 [ # # ]: 0 : (*(volatile uint64_t *)sq->fc == sq->aura_sqb_bufs)) {
605 : : break;
606 : : }
607 : :
608 : : /* Timeout */
609 [ # # ]: 0 : if (!timeout)
610 : 0 : goto exit;
611 : 0 : timeout--;
612 : : }
613 : :
614 : : return 0;
615 : : exit:
616 : 0 : return -EFAULT;
617 : : }
618 : :
619 : : void
620 : 0 : nix_tm_sq_free_sqe_buffer(uint64_t *sqe, int head_off, int end_off, int instr_sz)
621 : : {
622 : 0 : int i, j, inc = (8 * (0x2 >> instr_sz)), segs;
623 : : struct nix_send_hdr_s *send_hdr;
624 : : uint64_t *ptr, aura_handle;
625 : : struct idev_cfg *idev;
626 : :
627 [ # # ]: 0 : if (!sqe)
628 : : return;
629 : :
630 : 0 : idev = idev_get_cfg();
631 [ # # ]: 0 : if (idev == NULL)
632 : : return;
633 : :
634 : : ptr = sqe + (head_off * inc);
635 [ # # ]: 0 : for (i = head_off; i < end_off; i++) {
636 : 0 : ptr = sqe + (i * inc);
637 : : send_hdr = (struct nix_send_hdr_s *)(ptr);
638 [ # # ]: 0 : aura_handle = roc_npa_aura_handle_gen(send_hdr->w0.aura, idev->npa->base);
639 : 0 : ptr += 2;
640 [ # # ]: 0 : if (((*ptr >> 60) & 0xF) == NIX_SUBDC_EXT)
641 : 0 : ptr += 2;
642 [ # # ]: 0 : if (((*ptr >> 60) & 0xF) == NIX_SUBDC_AGE_AND_STATS)
643 : 0 : ptr += 2;
644 [ # # ]: 0 : if (((*ptr >> 60) & 0xF) == NIX_SUBDC_JUMP) {
645 : : ptr += 1;
646 : 0 : ptr = (uint64_t *)*ptr;
647 : : }
648 [ # # ]: 0 : if (((*ptr >> 60) & 0xF) == NIX_SUBDC_CRC)
649 : 0 : ptr += 2;
650 : : /* We are not parsing immediate send descriptor */
651 [ # # ]: 0 : if (((*ptr >> 60) & 0xF) == NIX_SUBDC_IMM)
652 : 0 : continue;
653 : : while (1) {
654 [ # # ]: 0 : if (((*ptr >> 60) & 0xF) == NIX_SUBDC_SG) {
655 : 0 : segs = (*ptr >> 48) & 0x3;
656 : 0 : ptr += 1;
657 [ # # ]: 0 : for (j = 0; j < segs; j++) {
658 : 0 : roc_npa_aura_op_free(aura_handle, 0, *ptr);
659 : 0 : ptr += 1;
660 : : }
661 [ # # ]: 0 : if (segs == 2)
662 : 0 : ptr += 1;
663 [ # # ]: 0 : } else if (((*ptr >> 60) & 0xF) == NIX_SUBDC_SG2) {
664 : 0 : uint64_t aura = (*ptr >> 16) & 0xFFFFF;
665 : :
666 : 0 : aura = roc_npa_aura_handle_gen(aura, idev->npa->base);
667 : : ptr += 1;
668 : 0 : roc_npa_aura_op_free(aura, 0, *ptr);
669 : 0 : ptr += 1;
670 : : } else
671 : : break;
672 : : }
673 : : }
674 : : }
675 : :
676 : : int
677 : 0 : roc_nix_tm_sq_free_pending_sqe(struct nix *nix, int q)
678 : : {
679 : : int head_off, count, rc = 0, tail_off;
680 : 0 : struct roc_nix_sq *sq = nix->sqs[q];
681 : : void *sqb_buf, *dat, *tail_sqb;
682 : 0 : struct dev *dev = &nix->dev;
683 : : struct ndc_sync_op *ndc_req;
684 : : uint16_t sqes_per_sqb;
685 : : struct mbox *mbox;
686 : :
687 : 0 : mbox = dev->mbox;
688 : : /* Sync NDC-NIX-TX for LF */
689 : 0 : ndc_req = mbox_alloc_msg_ndc_sync_op(mbox_get(mbox));
690 [ # # ]: 0 : if (ndc_req == NULL) {
691 : : mbox_put(mbox);
692 : 0 : return -EFAULT;
693 : : }
694 : :
695 : 0 : ndc_req->nix_lf_tx_sync = 1;
696 [ # # ]: 0 : if (mbox_process(mbox))
697 : : rc |= NIX_ERR_NDC_SYNC;
698 : : mbox_put(mbox);
699 : :
700 [ # # ]: 0 : if (rc)
701 : 0 : plt_err("NDC_SYNC failed rc %d", rc);
702 : :
703 : 0 : rc = nix_q_ctx_get(dev, NIX_AQ_CTYPE_SQ, q, (void *)&dat);
704 : :
705 [ # # ]: 0 : if (roc_model_is_cn9k()) {
706 : 0 : volatile struct nix_sq_ctx_s *ctx = (struct nix_sq_ctx_s *)dat;
707 : :
708 : : /* We will cleanup SQE buffers only when we received MNQ interrupt */
709 [ # # ]: 0 : if (!ctx->mnq_dis)
710 : : return -EFAULT;
711 : :
712 : 0 : count = ctx->sqb_count;
713 : 0 : sqb_buf = (void *)ctx->head_sqb;
714 : 0 : tail_sqb = (void *)ctx->tail_sqb;
715 : 0 : head_off = ctx->head_offset;
716 : 0 : tail_off = ctx->tail_offset;
717 : : } else {
718 : 0 : volatile struct nix_cn10k_sq_ctx_s *ctx = (struct nix_cn10k_sq_ctx_s *)dat;
719 : :
720 : : /* We will cleanup SQE buffers only when we received MNQ interrupt */
721 [ # # ]: 0 : if (!ctx->mnq_dis)
722 : : return -EFAULT;
723 : :
724 : 0 : count = ctx->sqb_count;
725 : : /* Free SQB's that are used */
726 : 0 : sqb_buf = (void *)ctx->head_sqb;
727 : 0 : tail_sqb = (void *)ctx->tail_sqb;
728 : 0 : head_off = ctx->head_offset;
729 : 0 : tail_off = ctx->tail_offset;
730 : : }
731 : 0 : sqes_per_sqb = 1 << sq->sqes_per_sqb_log2;
732 : : /* Free SQB's that are used */
733 [ # # ]: 0 : while (count) {
734 : : void *next_sqb;
735 : :
736 [ # # ]: 0 : if (sqb_buf == tail_sqb)
737 : 0 : nix_tm_sq_free_sqe_buffer(sqb_buf, head_off, tail_off, sq->max_sqe_sz);
738 : : else
739 : 0 : nix_tm_sq_free_sqe_buffer(sqb_buf, head_off, (sqes_per_sqb - 1),
740 : 0 : sq->max_sqe_sz);
741 : 0 : next_sqb = *(void **)((uint64_t *)sqb_buf +
742 : 0 : (uint32_t)((sqes_per_sqb - 1) * (0x2 >> sq->max_sqe_sz) * 8));
743 : 0 : roc_npa_aura_op_free(sq->aura_handle, 1, (uint64_t)sqb_buf);
744 : : sqb_buf = next_sqb;
745 : : head_off = 0;
746 : 0 : count--;
747 : : }
748 : :
749 : : return 0;
750 : : }
751 : :
752 : : static inline int
753 : 0 : nix_tm_sdp_sq_drop_pkts(struct roc_nix *roc_nix, struct roc_nix_sq *sq)
754 : : {
755 : : struct nix *nix = roc_nix_to_nix_priv(roc_nix);
756 : 0 : struct mbox *mbox = mbox_get((&nix->dev)->mbox);
757 : : struct nix_txschq_config *req = NULL, *rsp;
758 : 0 : enum roc_nix_tm_tree tree = nix->tm_tree;
759 : 0 : int rc = 0, qid = sq->qid;
760 : : struct nix_tm_node *node;
761 : : uint64_t regval;
762 : :
763 : : /* Find the node for this SQ */
764 : 0 : node = nix_tm_node_search(nix, qid, tree);
765 [ # # ]: 0 : while (node) {
766 [ # # ]: 0 : if (node->hw_lvl != NIX_TXSCH_LVL_TL4) {
767 : 0 : node = node->parent;
768 : 0 : continue;
769 : : }
770 : : break;
771 : : }
772 [ # # ]: 0 : if (!node) {
773 : 0 : plt_err("Invalid node/state for sq %u", qid);
774 : 0 : return -EFAULT;
775 : : }
776 : :
777 : : /* Get present link config */
778 : 0 : req = mbox_alloc_msg_nix_txschq_cfg(mbox);
779 : 0 : req->read = 1;
780 : 0 : req->lvl = NIX_TXSCH_LVL_TL4;
781 : 0 : req->reg[0] = NIX_AF_TL4X_SDP_LINK_CFG(node->hw_id);
782 : 0 : req->num_regs = 1;
783 : : rc = mbox_process_msg(mbox, (void **)&rsp);
784 [ # # # # ]: 0 : if (rc || rsp->num_regs != 1)
785 : 0 : goto err;
786 : 0 : regval = rsp->regval[0];
787 : : /* Disable BP_ENA in SDP link config */
788 : 0 : req = mbox_alloc_msg_nix_txschq_cfg(mbox);
789 : 0 : req->lvl = NIX_TXSCH_LVL_TL4;
790 : 0 : req->reg[0] = NIX_AF_TL4X_SDP_LINK_CFG(node->hw_id);
791 : 0 : req->regval[0] = 0x0ull;
792 : 0 : req->regval_mask[0] = ~(BIT_ULL(13));
793 : 0 : req->num_regs = 1;
794 : 0 : rc = mbox_process(mbox);
795 [ # # ]: 0 : if (rc)
796 : 0 : goto err;
797 : : mbox_put(mbox);
798 : : /* Flush SQ to drop all packets */
799 : 0 : rc = roc_nix_tm_sq_flush_spin(sq);
800 [ # # ]: 0 : if (rc)
801 : 0 : plt_nix_dbg("SQ flush failed with link reset config rc %d", rc);
802 : 0 : mbox = mbox_get((&nix->dev)->mbox);
803 : : /* Restore link config */
804 : 0 : req = mbox_alloc_msg_nix_txschq_cfg(mbox);
805 : 0 : req->reg[0] = NIX_AF_TL4X_SDP_LINK_CFG(node->hw_id);
806 : 0 : req->lvl = NIX_TXSCH_LVL_TL4;
807 : 0 : req->regval[0] = regval;
808 : 0 : req->regval_mask[0] = ~(BIT_ULL(13) | BIT_ULL(12) | GENMASK_ULL(7, 0));
809 : 0 : req->num_regs = 1;
810 : 0 : rc = mbox_process(mbox);
811 : 0 : err:
812 : : mbox_put(mbox);
813 : 0 : return rc;
814 : : }
815 : :
816 : : /* Flush and disable tx queue and its parent SMQ */
817 : : int
818 : 0 : nix_tm_sq_flush_pre(struct roc_nix_sq *sq)
819 : : {
820 [ # # ]: 0 : struct roc_nix *roc_nix = sq->roc_nix;
821 : : struct nix_tm_node *node, *sibling;
822 : : struct nix_tm_node_list *list;
823 : : enum roc_nix_tm_tree tree;
824 : : struct msg_req *req;
825 : : struct mbox *mbox;
826 : : struct nix *nix;
827 : : uint16_t qid;
828 : : int rc;
829 : :
830 : : nix = roc_nix_to_nix_priv(roc_nix);
831 : :
832 : : /* Need not do anything if tree is in disabled state */
833 [ # # ]: 0 : if (!(nix->tm_flags & NIX_TM_HIERARCHY_ENA))
834 : : return 0;
835 : :
836 : 0 : mbox = (&nix->dev)->mbox;
837 : 0 : qid = sq->qid;
838 : :
839 : 0 : tree = nix->tm_tree;
840 : : list = nix_tm_node_list(nix, tree);
841 : :
842 : : /* Find the node for this SQ */
843 : 0 : node = nix_tm_node_search(nix, qid, tree);
844 [ # # ]: 0 : if (!node) {
845 : 0 : plt_err("Invalid node/state for sq %u", qid);
846 : 0 : return -EFAULT;
847 : : }
848 : :
849 : : /* Enable CGX RXTX to drain pkts */
850 [ # # ]: 0 : if (!roc_nix->io_enabled) {
851 : : /* Though it enables both RX MCAM Entries and CGX Link
852 : : * we assume all the rx queues are stopped way back.
853 : : */
854 : 0 : mbox_alloc_msg_nix_lf_start_rx(mbox_get(mbox));
855 : 0 : rc = mbox_process(mbox);
856 [ # # ]: 0 : if (rc) {
857 : : mbox_put(mbox);
858 : 0 : plt_err("cgx start failed, rc=%d", rc);
859 : 0 : return rc;
860 : : }
861 : : mbox_put(mbox);
862 : : }
863 : :
864 : : /* Disable backpressure */
865 : 0 : rc = nix_tm_bp_config_set(roc_nix, sq->qid, 0, false);
866 [ # # ]: 0 : if (rc) {
867 : 0 : plt_err("Failed to disable backpressure for flush, rc=%d", rc);
868 : 0 : return rc;
869 : : }
870 : :
871 : : /* Disable smq xoff for case it was enabled earlier */
872 : 0 : rc = nix_tm_smq_xoff(nix, node->parent, false);
873 [ # # ]: 0 : if (rc) {
874 : 0 : plt_err("Failed to enable smq %u, rc=%d", node->parent->hw_id,
875 : : rc);
876 : 0 : return rc;
877 : : }
878 : :
879 : : /* As per HRM, to disable an SQ, all other SQ's
880 : : * that feed to same SMQ must be paused before SMQ flush.
881 : : */
882 [ # # ]: 0 : TAILQ_FOREACH(sibling, list, node) {
883 [ # # ]: 0 : if (sibling->parent != node->parent)
884 : 0 : continue;
885 [ # # ]: 0 : if (!(sibling->flags & NIX_TM_NODE_ENABLED))
886 : 0 : continue;
887 : :
888 : 0 : qid = sibling->id;
889 : 0 : sq = nix->sqs[qid];
890 [ # # ]: 0 : if (!sq)
891 : 0 : continue;
892 : :
893 [ # # ]: 0 : if (sq->enable) {
894 : 0 : rc = roc_nix_tm_sq_aura_fc(sq, false);
895 [ # # ]: 0 : if (rc) {
896 : 0 : plt_err("Failed to disable sqb aura fc, rc=%d", rc);
897 : 0 : goto cleanup;
898 : : }
899 : : }
900 : :
901 : : /* Wait for sq entries to be flushed */
902 : 0 : rc = roc_nix_tm_sq_flush_spin(sq);
903 [ # # ]: 0 : if (rc) {
904 [ # # ]: 0 : if (nix->sdp_link)
905 : 0 : rc = nix_tm_sdp_sq_drop_pkts(roc_nix, sq);
906 : : else
907 : 0 : rc = roc_nix_tm_sq_free_pending_sqe(nix, sq->qid);
908 [ # # ]: 0 : if (rc) {
909 : 0 : roc_nix_tm_dump(sq->roc_nix, NULL);
910 : 0 : roc_nix_queues_ctx_dump(sq->roc_nix, NULL);
911 : 0 : plt_err("Failed to drain sq %u, rc=%d", sq->qid, rc);
912 : 0 : return rc;
913 : : }
914 : : /* Freed all pending SQEs for this SQ, so disable this node */
915 : 0 : sibling->flags &= ~NIX_TM_NODE_ENABLED;
916 : : }
917 : : }
918 : :
919 : 0 : node->flags &= ~NIX_TM_NODE_ENABLED;
920 : :
921 : : /* Disable and flush */
922 : 0 : rc = nix_tm_smq_xoff(nix, node->parent, true);
923 [ # # ]: 0 : if (rc) {
924 : 0 : plt_err("Failed to disable smq %u, rc=%d", node->parent->hw_id,
925 : : rc);
926 : 0 : goto cleanup;
927 : : }
928 : :
929 : 0 : req = mbox_alloc_msg_nix_rx_sw_sync(mbox_get(mbox));
930 [ # # ]: 0 : if (!req) {
931 : : mbox_put(mbox);
932 : 0 : return -ENOSPC;
933 : : }
934 : :
935 : 0 : rc = mbox_process(mbox);
936 : : mbox_put(mbox);
937 : 0 : cleanup:
938 : : /* Restore cgx state */
939 [ # # ]: 0 : if (!roc_nix->io_enabled) {
940 : 0 : mbox_alloc_msg_nix_lf_stop_rx(mbox_get(mbox));
941 : 0 : rc |= mbox_process(mbox);
942 : : mbox_put(mbox);
943 : : }
944 : :
945 : : return rc;
946 : : }
947 : :
948 : : int
949 : 0 : nix_tm_sq_flush_post(struct roc_nix_sq *sq)
950 : : {
951 [ # # ]: 0 : struct roc_nix *roc_nix = sq->roc_nix;
952 : : struct nix_tm_node *node, *sibling;
953 : : struct nix_tm_node_list *list;
954 : : enum roc_nix_tm_tree tree;
955 : : struct roc_nix_sq *s_sq;
956 : : bool once = false;
957 : : uint16_t qid, s_qid;
958 : : struct nix *nix;
959 : : int rc;
960 : :
961 : : nix = roc_nix_to_nix_priv(roc_nix);
962 : :
963 : : /* Need not do anything if tree is in disabled state */
964 [ # # ]: 0 : if (!(nix->tm_flags & NIX_TM_HIERARCHY_ENA))
965 : : return 0;
966 : :
967 : 0 : qid = sq->qid;
968 : 0 : tree = nix->tm_tree;
969 : : list = nix_tm_node_list(nix, tree);
970 : :
971 : : /* Find the node for this SQ */
972 : 0 : node = nix_tm_node_search(nix, qid, tree);
973 [ # # ]: 0 : if (!node) {
974 : 0 : plt_err("Invalid node for sq %u", qid);
975 : 0 : return -EFAULT;
976 : : }
977 : :
978 : : /* Enable all the siblings back */
979 [ # # ]: 0 : TAILQ_FOREACH(sibling, list, node) {
980 [ # # ]: 0 : if (sibling->parent != node->parent)
981 : 0 : continue;
982 : :
983 [ # # ]: 0 : if (sibling->id == qid)
984 : 0 : continue;
985 : :
986 [ # # ]: 0 : if (!(sibling->flags & NIX_TM_NODE_ENABLED))
987 : 0 : continue;
988 : :
989 : 0 : s_qid = sibling->id;
990 : 0 : s_sq = nix->sqs[s_qid];
991 [ # # ]: 0 : if (!s_sq)
992 : 0 : continue;
993 : :
994 [ # # ]: 0 : if (!once) {
995 : : /* Enable back if any SQ is still present */
996 : 0 : rc = nix_tm_smq_xoff(nix, node->parent, false);
997 [ # # ]: 0 : if (rc) {
998 : 0 : plt_err("Failed to enable smq %u, rc=%d",
999 : : node->parent->hw_id, rc);
1000 : 0 : return rc;
1001 : : }
1002 : : once = true;
1003 : : }
1004 : :
1005 [ # # ]: 0 : if (s_sq->enable) {
1006 : 0 : rc = roc_nix_tm_sq_aura_fc(s_sq, true);
1007 [ # # ]: 0 : if (rc) {
1008 : 0 : plt_err("Failed to enable sqb aura fc, rc=%d", rc);
1009 : 0 : return rc;
1010 : : }
1011 : : }
1012 : : }
1013 : :
1014 : : return 0;
1015 : : }
1016 : :
1017 : : int
1018 : 0 : nix_tm_sq_sched_conf(struct nix *nix, struct nix_tm_node *node,
1019 : : bool rr_quantum_only)
1020 : : {
1021 : 0 : struct mbox *mbox = mbox_get((&nix->dev)->mbox);
1022 : 0 : uint16_t qid = node->id, smq;
1023 : : uint64_t rr_quantum;
1024 : : int rc;
1025 : :
1026 : 0 : smq = node->parent->hw_id;
1027 [ # # ]: 0 : rr_quantum = nix_tm_weight_to_rr_quantum(node->weight);
1028 : :
1029 [ # # ]: 0 : if (rr_quantum_only)
1030 : 0 : plt_tm_dbg("Update sq(%u) rr_quantum 0x%" PRIx64, qid,
1031 : : rr_quantum);
1032 : : else
1033 : 0 : plt_tm_dbg("Enabling sq(%u)->smq(%u), rr_quantum 0x%" PRIx64,
1034 : : qid, smq, rr_quantum);
1035 : :
1036 [ # # ]: 0 : if (qid > nix->nb_tx_queues) {
1037 : : rc = -EFAULT;
1038 : 0 : goto exit;
1039 : : }
1040 : :
1041 [ # # ]: 0 : if (roc_model_is_cn9k()) {
1042 : : struct nix_aq_enq_req *aq;
1043 : :
1044 : 0 : aq = mbox_alloc_msg_nix_aq_enq(mbox);
1045 [ # # ]: 0 : if (!aq) {
1046 : : rc = -ENOSPC;
1047 : 0 : goto exit;
1048 : : }
1049 : :
1050 : 0 : aq->qidx = qid;
1051 : 0 : aq->ctype = NIX_AQ_CTYPE_SQ;
1052 : 0 : aq->op = NIX_AQ_INSTOP_WRITE;
1053 : :
1054 : : /* smq update only when needed */
1055 [ # # ]: 0 : if (!rr_quantum_only) {
1056 : 0 : aq->sq.smq = smq;
1057 : 0 : aq->sq_mask.smq = ~aq->sq_mask.smq;
1058 : : }
1059 : 0 : aq->sq.smq_rr_quantum = rr_quantum;
1060 : 0 : aq->sq_mask.smq_rr_quantum = ~aq->sq_mask.smq_rr_quantum;
1061 [ # # ]: 0 : } else if (roc_model_is_cn10k()) {
1062 : : struct nix_cn10k_aq_enq_req *aq;
1063 : :
1064 : 0 : aq = mbox_alloc_msg_nix_cn10k_aq_enq(mbox);
1065 [ # # ]: 0 : if (!aq) {
1066 : : rc = -ENOSPC;
1067 : 0 : goto exit;
1068 : : }
1069 : :
1070 : 0 : aq->qidx = qid;
1071 : 0 : aq->ctype = NIX_AQ_CTYPE_SQ;
1072 : 0 : aq->op = NIX_AQ_INSTOP_WRITE;
1073 : :
1074 : : /* smq update only when needed */
1075 [ # # ]: 0 : if (!rr_quantum_only) {
1076 : 0 : aq->sq.smq = smq;
1077 : 0 : aq->sq_mask.smq = ~aq->sq_mask.smq;
1078 : : }
1079 : 0 : aq->sq.smq_rr_weight = rr_quantum;
1080 : 0 : aq->sq_mask.smq_rr_weight = ~aq->sq_mask.smq_rr_weight;
1081 : : } else {
1082 : : struct nix_cn20k_aq_enq_req *aq;
1083 : :
1084 : 0 : aq = mbox_alloc_msg_nix_cn20k_aq_enq(mbox);
1085 [ # # ]: 0 : if (!aq) {
1086 : : rc = -ENOSPC;
1087 : 0 : goto exit;
1088 : : }
1089 : :
1090 : 0 : aq->qidx = qid;
1091 : 0 : aq->ctype = NIX_AQ_CTYPE_SQ;
1092 : 0 : aq->op = NIX_AQ_INSTOP_WRITE;
1093 : :
1094 : : /* smq update only when needed */
1095 [ # # ]: 0 : if (!rr_quantum_only) {
1096 : 0 : aq->sq.smq = smq;
1097 : 0 : aq->sq_mask.smq = ~aq->sq_mask.smq;
1098 : : }
1099 : 0 : aq->sq.smq_rr_weight = rr_quantum;
1100 : 0 : aq->sq_mask.smq_rr_weight = ~aq->sq_mask.smq_rr_weight;
1101 : : }
1102 : :
1103 : 0 : rc = mbox_process(mbox);
1104 [ # # ]: 0 : if (rc)
1105 : 0 : plt_err("Failed to set smq, rc=%d", rc);
1106 : 0 : exit:
1107 : : mbox_put(mbox);
1108 : 0 : return rc;
1109 : : }
1110 : :
1111 : : int
1112 : 0 : nix_tm_release_resources(struct nix *nix, uint8_t hw_lvl, bool contig,
1113 : : bool above_thresh)
1114 : : {
1115 : : uint16_t avail, thresh, to_free = 0, schq;
1116 : 0 : struct mbox *mbox = (&nix->dev)->mbox;
1117 : : struct nix_txsch_free_req *req;
1118 : : struct plt_bitmap *bmp;
1119 : 0 : uint64_t slab = 0;
1120 : 0 : uint32_t pos = 0;
1121 : : int rc = -ENOSPC;
1122 : :
1123 [ # # ]: 0 : bmp = contig ? nix->schq_contig_bmp[hw_lvl] : nix->schq_bmp[hw_lvl];
1124 [ # # ]: 0 : thresh =
1125 : 0 : contig ? nix->contig_rsvd[hw_lvl] : nix->discontig_rsvd[hw_lvl];
1126 : : plt_bitmap_scan_init(bmp);
1127 : :
1128 : 0 : avail = nix_tm_resource_avail(nix, hw_lvl, contig);
1129 : :
1130 [ # # ]: 0 : if (above_thresh) {
1131 : : /* Release only above threshold */
1132 [ # # ]: 0 : if (avail > thresh)
1133 : 0 : to_free = avail - thresh;
1134 : : } else {
1135 : : /* Release everything */
1136 : : to_free = avail;
1137 : : }
1138 : :
1139 : : /* Now release resources to AF */
1140 [ # # ]: 0 : while (to_free) {
1141 [ # # # # ]: 0 : if (!slab && !plt_bitmap_scan(bmp, &pos, &slab))
1142 : : break;
1143 : :
1144 [ # # ]: 0 : schq = bitmap_ctzll(slab);
1145 : 0 : slab &= ~(1ULL << schq);
1146 : 0 : schq += pos;
1147 : :
1148 : : /* Free to AF */
1149 : 0 : req = mbox_alloc_msg_nix_txsch_free(mbox_get(mbox));
1150 [ # # ]: 0 : if (req == NULL) {
1151 : : mbox_put(mbox);
1152 : 0 : return rc;
1153 : : }
1154 : 0 : req->flags = 0;
1155 : 0 : req->schq_lvl = hw_lvl;
1156 : 0 : req->schq = schq;
1157 : 0 : rc = mbox_process(mbox);
1158 [ # # ]: 0 : if (rc) {
1159 [ # # # # : 0 : plt_err("failed to release hwres %s(%u) rc %d",
# # ]
1160 : : nix_tm_hwlvl2str(hw_lvl), schq, rc);
1161 : : mbox_put(mbox);
1162 : 0 : return rc;
1163 : : }
1164 : : mbox_put(mbox);
1165 [ # # # # : 0 : plt_tm_dbg("Released hwres %s(%u)", nix_tm_hwlvl2str(hw_lvl),
# # ]
1166 : : schq);
1167 : 0 : plt_bitmap_clear(bmp, schq);
1168 : 0 : to_free--;
1169 : : }
1170 : :
1171 [ # # ]: 0 : if (to_free) {
1172 : 0 : plt_err("resource inconsistency for %s(%u)",
1173 : : nix_tm_hwlvl2str(hw_lvl), contig);
1174 : 0 : return -EFAULT;
1175 : : }
1176 : : return 0;
1177 : : }
1178 : :
1179 : : int
1180 : 0 : nix_tm_free_node_resource(struct nix *nix, struct nix_tm_node *node)
1181 : : {
1182 : 0 : struct mbox *mbox = mbox_get((&nix->dev)->mbox);
1183 : : struct nix_txsch_free_req *req;
1184 : : struct plt_bitmap *bmp;
1185 : : uint16_t avail, hw_id;
1186 : : uint8_t hw_lvl;
1187 : : int rc = -ENOSPC;
1188 : :
1189 : 0 : hw_lvl = node->hw_lvl;
1190 : 0 : hw_id = node->hw_id;
1191 : 0 : bmp = nix->schq_bmp[hw_lvl];
1192 : : /* Free specific HW resource */
1193 [ # # # # : 0 : plt_tm_dbg("Free hwres %s(%u) lvl %u id %u (%p)",
# # ]
1194 : : nix_tm_hwlvl2str(node->hw_lvl), hw_id, node->lvl, node->id,
1195 : : node);
1196 : :
1197 : 0 : avail = nix_tm_resource_avail(nix, hw_lvl, false);
1198 : : /* Always for now free to discontiguous queue when avail
1199 : : * is not sufficient.
1200 : : */
1201 [ # # # # ]: 0 : if (nix->discontig_rsvd[hw_lvl] &&
1202 : : avail < nix->discontig_rsvd[hw_lvl]) {
1203 : : PLT_ASSERT(hw_id < NIX_TM_MAX_HW_TXSCHQ);
1204 : : PLT_ASSERT(plt_bitmap_get(bmp, hw_id) == 0);
1205 : 0 : plt_bitmap_set(bmp, hw_id);
1206 : 0 : node->hw_id = NIX_TM_HW_ID_INVALID;
1207 : 0 : node->flags &= ~NIX_TM_NODE_HWRES;
1208 : : rc = 0;
1209 : 0 : goto exit;
1210 : : }
1211 : :
1212 : : /* Free to AF */
1213 : 0 : req = mbox_alloc_msg_nix_txsch_free(mbox);
1214 [ # # ]: 0 : if (req == NULL)
1215 : 0 : goto exit;
1216 : 0 : req->flags = 0;
1217 : 0 : req->schq_lvl = node->hw_lvl;
1218 : 0 : req->schq = hw_id;
1219 : 0 : rc = mbox_process(mbox);
1220 [ # # ]: 0 : if (rc) {
1221 [ # # # # : 0 : plt_err("failed to release hwres %s(%u) rc %d",
# # ]
1222 : : nix_tm_hwlvl2str(node->hw_lvl), hw_id, rc);
1223 : 0 : goto exit;
1224 : : }
1225 : :
1226 : : /* Mark parent as dirty for reallocing it's children */
1227 [ # # ]: 0 : if (node->parent)
1228 : 0 : node->parent->child_realloc = true;
1229 : :
1230 : 0 : node->hw_id = NIX_TM_HW_ID_INVALID;
1231 : 0 : node->flags &= ~NIX_TM_NODE_HWRES;
1232 [ # # # # : 0 : plt_tm_dbg("Released hwres %s(%u) to af",
# # ]
1233 : : nix_tm_hwlvl2str(node->hw_lvl), hw_id);
1234 : : rc = 0;
1235 : 0 : exit:
1236 : : mbox_put(mbox);
1237 : 0 : return rc;
1238 : : }
1239 : :
1240 : : int
1241 : 0 : nix_tm_node_delete(struct roc_nix *roc_nix, uint32_t node_id,
1242 : : enum roc_nix_tm_tree tree, bool free)
1243 : : {
1244 : : struct nix *nix = roc_nix_to_nix_priv(roc_nix);
1245 : : struct nix_tm_shaper_profile *profile;
1246 : : struct nix_tm_node *node, *child;
1247 : : struct nix_tm_node_list *list;
1248 : : uint32_t profile_id;
1249 : : int rc;
1250 : :
1251 : 0 : plt_tm_dbg("Delete node id %u tree %u", node_id, tree);
1252 : :
1253 : 0 : node = nix_tm_node_search(nix, node_id, tree);
1254 [ # # ]: 0 : if (!node)
1255 : : return NIX_ERR_TM_INVALID_NODE;
1256 : :
1257 : : list = nix_tm_node_list(nix, tree);
1258 : : /* Check for any existing children */
1259 [ # # ]: 0 : TAILQ_FOREACH(child, list, node) {
1260 [ # # ]: 0 : if (child->parent == node)
1261 : : return NIX_ERR_TM_CHILD_EXISTS;
1262 : : }
1263 : :
1264 : : /* Remove shaper profile reference */
1265 : 0 : profile_id = node->shaper_profile_id;
1266 : 0 : profile = nix_tm_shaper_profile_search(nix, profile_id);
1267 : :
1268 : : /* Free hw resource locally */
1269 [ # # ]: 0 : if (node->flags & NIX_TM_NODE_HWRES) {
1270 : 0 : rc = nix_tm_free_node_resource(nix, node);
1271 [ # # ]: 0 : if (rc)
1272 : : return rc;
1273 : : }
1274 : :
1275 [ # # ]: 0 : if (profile)
1276 : 0 : profile->ref_cnt--;
1277 : :
1278 [ # # ]: 0 : TAILQ_REMOVE(list, node, node);
1279 : :
1280 [ # # # # : 0 : plt_tm_dbg("Deleted node %s lvl %u id %u, prio 0x%x weight 0x%x "
# # # # ]
1281 : : "parent %u profile 0x%x tree %u (%p)",
1282 : : nix_tm_hwlvl2str(node->hw_lvl), node->lvl, node->id,
1283 : : node->priority, node->weight,
1284 : : node->parent ? node->parent->id : UINT32_MAX,
1285 : : node->shaper_profile_id, tree, node);
1286 : : /* Free only if requested */
1287 [ # # ]: 0 : if (free)
1288 : 0 : nix_tm_node_free(node);
1289 : : return 0;
1290 : : }
1291 : :
1292 : : static int
1293 : 0 : nix_tm_assign_hw_id(struct nix *nix, struct nix_tm_node *parent,
1294 : : uint16_t *contig_id, int *contig_cnt,
1295 : : struct nix_tm_node_list *list)
1296 : : {
1297 : : struct nix_tm_node *child;
1298 : : struct plt_bitmap *bmp;
1299 : : uint8_t child_hw_lvl;
1300 : : int spare_schq = -1;
1301 : 0 : uint32_t pos = 0;
1302 : : uint64_t slab;
1303 : : uint16_t schq;
1304 : :
1305 : 0 : child_hw_lvl = parent->hw_lvl - 1;
1306 [ # # ]: 0 : bmp = nix->schq_bmp[child_hw_lvl];
1307 : : plt_bitmap_scan_init(bmp);
1308 : 0 : slab = 0;
1309 : :
1310 : : /* Save spare schq if it is case of RR + SP */
1311 [ # # # # ]: 0 : if (parent->rr_prio != 0xf && *contig_cnt > 1)
1312 : 0 : spare_schq = *contig_id + parent->rr_prio;
1313 : :
1314 [ # # ]: 0 : TAILQ_FOREACH(child, list, node) {
1315 [ # # ]: 0 : if (!child->parent)
1316 : 0 : continue;
1317 [ # # ]: 0 : if (child->parent->id != parent->id)
1318 : 0 : continue;
1319 : :
1320 : : /* Resource never expected to be present */
1321 [ # # ]: 0 : if (child->flags & NIX_TM_NODE_HWRES) {
1322 [ # # # # : 0 : plt_err("Resource exists for child (%s)%u, id %u (%p)",
# # ]
1323 : : nix_tm_hwlvl2str(child->hw_lvl), child->hw_id,
1324 : : child->id, child);
1325 : 0 : return -EFAULT;
1326 : : }
1327 : :
1328 [ # # ]: 0 : if (!slab)
1329 : 0 : plt_bitmap_scan(bmp, &pos, &slab);
1330 : :
1331 [ # # # # ]: 0 : if (child->priority == parent->rr_prio && spare_schq != -1) {
1332 : : /* Use spare schq first if present */
1333 : 0 : schq = spare_schq;
1334 : : spare_schq = -1;
1335 : 0 : *contig_cnt = *contig_cnt - 1;
1336 : :
1337 [ # # ]: 0 : } else if (child->priority == parent->rr_prio) {
1338 : : /* Assign a discontiguous queue */
1339 [ # # ]: 0 : if (!slab) {
1340 : 0 : plt_err("Schq not found for Child %u "
1341 : : "lvl %u (%p)",
1342 : : child->id, child->lvl, child);
1343 : 0 : return -ENOENT;
1344 : : }
1345 : :
1346 : 0 : schq = bitmap_ctzll(slab);
1347 : 0 : slab &= ~(1ULL << schq);
1348 : 0 : schq += pos;
1349 : 0 : plt_bitmap_clear(bmp, schq);
1350 : : } else {
1351 : : /* Assign a contiguous queue */
1352 : 0 : schq = *contig_id + child->priority;
1353 : 0 : *contig_cnt = *contig_cnt - 1;
1354 : : }
1355 : :
1356 [ # # # # : 0 : plt_tm_dbg("Resource %s(%u), for lvl %u id %u(%p)",
# # ]
1357 : : nix_tm_hwlvl2str(child->hw_lvl), schq, child->lvl,
1358 : : child->id, child);
1359 : :
1360 : 0 : child->hw_id = schq;
1361 : 0 : child->parent_hw_id = parent->hw_id;
1362 : 0 : child->flags |= NIX_TM_NODE_HWRES;
1363 : : }
1364 : :
1365 : : return 0;
1366 : : }
1367 : :
1368 : : int
1369 : 0 : nix_tm_assign_resources(struct nix *nix, enum roc_nix_tm_tree tree)
1370 : : {
1371 : : struct nix_tm_node *parent, *root = NULL;
1372 : : struct plt_bitmap *bmp, *bmp_contig;
1373 : : struct nix_tm_node_list *list;
1374 : : uint8_t child_hw_lvl, hw_lvl;
1375 : : uint16_t contig_id, j;
1376 : 0 : uint64_t slab = 0;
1377 : 0 : uint32_t pos = 0;
1378 : : int cnt, rc;
1379 : :
1380 : : list = nix_tm_node_list(nix, tree);
1381 : : /* Walk from TL1 to TL4 parents */
1382 [ # # ]: 0 : for (hw_lvl = NIX_TXSCH_LVL_TL1; hw_lvl > 0; hw_lvl--) {
1383 [ # # ]: 0 : TAILQ_FOREACH(parent, list, node) {
1384 : 0 : child_hw_lvl = parent->hw_lvl - 1;
1385 [ # # ]: 0 : if (parent->hw_lvl != hw_lvl)
1386 : 0 : continue;
1387 : :
1388 : : /* Remember root for future */
1389 [ # # ]: 0 : if (parent->hw_lvl == nix->tm_root_lvl)
1390 : : root = parent;
1391 : :
1392 [ # # ]: 0 : if (!parent->child_realloc) {
1393 : : /* Skip when parent is not dirty */
1394 [ # # ]: 0 : if (nix_tm_child_res_valid(list, parent))
1395 : 0 : continue;
1396 : 0 : plt_err("Parent not dirty but invalid "
1397 : : "child res parent id %u(lvl %u)",
1398 : : parent->id, parent->lvl);
1399 : 0 : return -EFAULT;
1400 : : }
1401 : :
1402 : 0 : bmp_contig = nix->schq_contig_bmp[child_hw_lvl];
1403 : :
1404 : : /* Prealloc contiguous indices for a parent */
1405 : 0 : contig_id = NIX_TM_MAX_HW_TXSCHQ;
1406 : 0 : cnt = (int)parent->max_prio + 1;
1407 [ # # ]: 0 : if (cnt > 0) {
1408 : : plt_bitmap_scan_init(bmp_contig);
1409 [ # # ]: 0 : if (!plt_bitmap_scan(bmp_contig, &pos, &slab)) {
1410 : 0 : plt_err("Contig schq not found");
1411 : 0 : return -ENOENT;
1412 : : }
1413 [ # # ]: 0 : contig_id = pos + bitmap_ctzll(slab);
1414 : :
1415 : : /* Check if we have enough */
1416 [ # # ]: 0 : for (j = contig_id; j < contig_id + cnt; j++) {
1417 [ # # ]: 0 : if (!plt_bitmap_get(bmp_contig, j))
1418 : : break;
1419 : : }
1420 : :
1421 [ # # ]: 0 : if (j != contig_id + cnt) {
1422 : 0 : plt_err("Contig schq not sufficient");
1423 : 0 : return -ENOENT;
1424 : : }
1425 : :
1426 [ # # ]: 0 : for (j = contig_id; j < contig_id + cnt; j++)
1427 : 0 : plt_bitmap_clear(bmp_contig, j);
1428 : : }
1429 : :
1430 : : /* Assign hw id to all children */
1431 : 0 : rc = nix_tm_assign_hw_id(nix, parent, &contig_id, &cnt,
1432 : : list);
1433 [ # # ]: 0 : if (cnt || rc) {
1434 : 0 : plt_err("Unexpected err, contig res alloc, "
1435 : : "parent %u, of %s, rc=%d, cnt=%d",
1436 : : parent->id, nix_tm_hwlvl2str(hw_lvl),
1437 : : rc, cnt);
1438 : 0 : return -EFAULT;
1439 : : }
1440 : :
1441 : : /* Clear the dirty bit as children's
1442 : : * resources are reallocated.
1443 : : */
1444 : 0 : parent->child_realloc = false;
1445 : : }
1446 : : }
1447 : :
1448 : : /* Root is always expected to be there */
1449 [ # # ]: 0 : if (!root)
1450 : : return -EFAULT;
1451 : :
1452 [ # # ]: 0 : if (root->flags & NIX_TM_NODE_HWRES)
1453 : : return 0;
1454 : :
1455 : : /* Process root node */
1456 : 0 : bmp = nix->schq_bmp[nix->tm_root_lvl];
1457 : : plt_bitmap_scan_init(bmp);
1458 [ # # ]: 0 : if (!plt_bitmap_scan(bmp, &pos, &slab)) {
1459 : 0 : plt_err("Resource not allocated for root");
1460 : 0 : return -EIO;
1461 : : }
1462 : :
1463 [ # # ]: 0 : root->hw_id = pos + bitmap_ctzll(slab);
1464 : 0 : root->flags |= NIX_TM_NODE_HWRES;
1465 : 0 : plt_bitmap_clear(bmp, root->hw_id);
1466 : :
1467 : : /* Get TL1 id as well when root is not TL1 */
1468 [ # # ]: 0 : if (!nix_tm_have_tl1_access(nix)) {
1469 : 0 : bmp = nix->schq_bmp[NIX_TXSCH_LVL_TL1];
1470 : :
1471 : : plt_bitmap_scan_init(bmp);
1472 [ # # ]: 0 : if (!plt_bitmap_scan(bmp, &pos, &slab)) {
1473 : 0 : plt_err("Resource not found for TL1");
1474 : 0 : return -EIO;
1475 : : }
1476 [ # # ]: 0 : root->parent_hw_id = pos + bitmap_ctzll(slab);
1477 : 0 : plt_bitmap_clear(bmp, root->parent_hw_id);
1478 : : }
1479 : :
1480 [ # # # # : 0 : plt_tm_dbg("Resource %s(%u) for root(id %u) (%p)",
# # ]
1481 : : nix_tm_hwlvl2str(root->hw_lvl), root->hw_id, root->id, root);
1482 : :
1483 : 0 : return 0;
1484 : : }
1485 : :
1486 : : void
1487 : 0 : nix_tm_copy_rsp_to_nix(struct nix *nix, struct nix_txsch_alloc_rsp *rsp)
1488 : : {
1489 : : uint8_t lvl;
1490 : : uint16_t i;
1491 : :
1492 [ # # ]: 0 : for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
1493 [ # # ]: 0 : for (i = 0; i < rsp->schq[lvl]; i++)
1494 : 0 : plt_bitmap_set(nix->schq_bmp[lvl],
1495 : 0 : rsp->schq_list[lvl][i]);
1496 : :
1497 [ # # ]: 0 : for (i = 0; i < rsp->schq_contig[lvl]; i++)
1498 : 0 : plt_bitmap_set(nix->schq_contig_bmp[lvl],
1499 : 0 : rsp->schq_contig_list[lvl][i]);
1500 : : }
1501 : 0 : }
1502 : :
1503 : : int
1504 : 0 : nix_tm_alloc_txschq(struct nix *nix, enum roc_nix_tm_tree tree)
1505 : : {
1506 : : uint16_t schq_contig[NIX_TXSCH_LVL_CNT];
1507 : 0 : struct mbox *mbox = (&nix->dev)->mbox;
1508 : : uint16_t schq[NIX_TXSCH_LVL_CNT];
1509 : : struct nix_txsch_alloc_req *req;
1510 : : struct nix_txsch_alloc_rsp *rsp;
1511 : : uint8_t hw_lvl, i;
1512 : : bool pend;
1513 : : int rc;
1514 : :
1515 : : memset(schq, 0, sizeof(schq));
1516 : : memset(schq_contig, 0, sizeof(schq_contig));
1517 : :
1518 : : /* Estimate requirement */
1519 : 0 : rc = nix_tm_resource_estimate(nix, schq_contig, schq, tree);
1520 [ # # ]: 0 : if (!rc)
1521 : : return 0;
1522 : :
1523 : : /* Release existing contiguous resources when realloc requested
1524 : : * as there is no way to guarantee continuity of old with new.
1525 : : */
1526 [ # # ]: 0 : for (hw_lvl = 0; hw_lvl < NIX_TXSCH_LVL_CNT; hw_lvl++) {
1527 [ # # ]: 0 : if (schq_contig[hw_lvl])
1528 : 0 : nix_tm_release_resources(nix, hw_lvl, true, false);
1529 : : }
1530 : :
1531 : : /* Alloc as needed */
1532 : : do {
1533 : : pend = false;
1534 : 0 : req = mbox_alloc_msg_nix_txsch_alloc(mbox_get(mbox));
1535 [ # # ]: 0 : if (!req) {
1536 : : mbox_put(mbox);
1537 : : rc = -ENOMEM;
1538 : 0 : goto alloc_err;
1539 : : }
1540 : 0 : mbox_memcpy(req->schq, schq, sizeof(req->schq));
1541 : 0 : mbox_memcpy(req->schq_contig, schq_contig,
1542 : : sizeof(req->schq_contig));
1543 : :
1544 : : /* Each alloc can be at max of MAX_TXSCHQ_PER_FUNC per level.
1545 : : * So split alloc to multiple requests.
1546 : : */
1547 [ # # ]: 0 : for (i = 0; i < NIX_TXSCH_LVL_CNT; i++) {
1548 [ # # ]: 0 : if (req->schq[i] > MAX_TXSCHQ_PER_FUNC)
1549 : 0 : req->schq[i] = MAX_TXSCHQ_PER_FUNC;
1550 : 0 : schq[i] -= req->schq[i];
1551 : :
1552 [ # # ]: 0 : if (req->schq_contig[i] > MAX_TXSCHQ_PER_FUNC)
1553 : 0 : req->schq_contig[i] = MAX_TXSCHQ_PER_FUNC;
1554 : 0 : schq_contig[i] -= req->schq_contig[i];
1555 : :
1556 [ # # # # ]: 0 : if (schq[i] || schq_contig[i])
1557 : : pend = true;
1558 : : }
1559 : :
1560 : : rc = mbox_process_msg(mbox, (void *)&rsp);
1561 [ # # ]: 0 : if (rc) {
1562 : : mbox_put(mbox);
1563 : 0 : goto alloc_err;
1564 : : }
1565 : :
1566 : 0 : nix_tm_copy_rsp_to_nix(nix, rsp);
1567 : : mbox_put(mbox);
1568 [ # # ]: 0 : } while (pend);
1569 : :
1570 : 0 : nix->tm_link_cfg_lvl = rsp->link_cfg_lvl;
1571 : 0 : nix->tm_aggr_lvl_rr_prio = rsp->aggr_lvl_rr_prio;
1572 : 0 : return 0;
1573 : 0 : alloc_err:
1574 [ # # ]: 0 : for (i = 0; i < NIX_TXSCH_LVL_CNT; i++) {
1575 [ # # ]: 0 : if (nix_tm_release_resources(nix, i, true, false))
1576 : 0 : plt_err("Failed to release contig resources of "
1577 : : "lvl %d on error",
1578 : : i);
1579 [ # # ]: 0 : if (nix_tm_release_resources(nix, i, false, false))
1580 : 0 : plt_err("Failed to release discontig resources of "
1581 : : "lvl %d on error",
1582 : : i);
1583 : : }
1584 : : return rc;
1585 : : }
1586 : :
1587 : : int
1588 : 0 : nix_tm_prepare_default_tree(struct roc_nix *roc_nix)
1589 : : {
1590 : : struct nix *nix = roc_nix_to_nix_priv(roc_nix);
1591 [ # # ]: 0 : uint32_t nonleaf_id = nix->nb_tx_queues;
1592 : : struct nix_tm_node *node = NULL;
1593 : : uint8_t leaf_lvl, lvl, lvl_end;
1594 : : uint32_t parent, i;
1595 : : int rc = 0;
1596 : :
1597 : : /* Add ROOT, SCH1, SCH2, SCH3, [SCH4] nodes */
1598 : : parent = ROC_NIX_TM_NODE_ID_INVALID;
1599 : : /* With TL1 access we have an extra level */
1600 [ # # ]: 0 : lvl_end = (nix_tm_have_tl1_access(nix) ? ROC_TM_LVL_SCH4 :
1601 : : ROC_TM_LVL_SCH3);
1602 : :
1603 [ # # ]: 0 : for (lvl = ROC_TM_LVL_ROOT; lvl <= lvl_end; lvl++) {
1604 : : rc = -ENOMEM;
1605 : 0 : node = nix_tm_node_alloc();
1606 [ # # ]: 0 : if (!node)
1607 : 0 : goto error;
1608 : :
1609 : 0 : node->id = nonleaf_id;
1610 : 0 : node->parent_id = parent;
1611 : 0 : node->priority = 0;
1612 : : /* Default VF root RR_QUANTUM is in sync with kernel */
1613 [ # # # # ]: 0 : if (lvl == ROC_TM_LVL_ROOT && !nix_tm_have_tl1_access(nix))
1614 : 0 : node->weight = roc_nix->root_sched_weight;
1615 : : else
1616 : 0 : node->weight = NIX_TM_DFLT_RR_WT;
1617 : 0 : node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE;
1618 : 0 : node->lvl = lvl;
1619 : 0 : node->tree = ROC_NIX_TM_DEFAULT;
1620 : 0 : node->rel_chan = NIX_TM_CHAN_INVALID;
1621 : :
1622 : 0 : rc = nix_tm_node_add(roc_nix, node);
1623 [ # # ]: 0 : if (rc)
1624 : 0 : goto error;
1625 : : parent = nonleaf_id;
1626 : 0 : nonleaf_id++;
1627 : : }
1628 : :
1629 [ # # ]: 0 : parent = nonleaf_id - 1;
1630 [ # # ]: 0 : leaf_lvl = (nix_tm_have_tl1_access(nix) ? ROC_TM_LVL_QUEUE :
1631 : : ROC_TM_LVL_SCH4);
1632 : :
1633 : : /* Add leaf nodes */
1634 [ # # ]: 0 : for (i = 0; i < nix->nb_tx_queues; i++) {
1635 : : rc = -ENOMEM;
1636 : 0 : node = nix_tm_node_alloc();
1637 [ # # ]: 0 : if (!node)
1638 : 0 : goto error;
1639 : :
1640 : 0 : node->id = i;
1641 : 0 : node->parent_id = parent;
1642 : 0 : node->priority = 0;
1643 : 0 : node->weight = NIX_TM_DFLT_RR_WT;
1644 : 0 : node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE;
1645 : 0 : node->lvl = leaf_lvl;
1646 : 0 : node->tree = ROC_NIX_TM_DEFAULT;
1647 : 0 : node->rel_chan = NIX_TM_CHAN_INVALID;
1648 : :
1649 : 0 : rc = nix_tm_node_add(roc_nix, node);
1650 [ # # ]: 0 : if (rc)
1651 : 0 : goto error;
1652 : : }
1653 : :
1654 : : return 0;
1655 : 0 : error:
1656 : 0 : nix_tm_node_free(node);
1657 : 0 : return rc;
1658 : : }
1659 : :
1660 : : int
1661 : 0 : roc_nix_tm_prepare_rate_limited_tree(struct roc_nix *roc_nix)
1662 : : {
1663 : : struct nix *nix = roc_nix_to_nix_priv(roc_nix);
1664 [ # # ]: 0 : uint32_t nonleaf_id = nix->nb_tx_queues;
1665 : : struct nix_tm_node *node = NULL;
1666 : : uint8_t leaf_lvl, lvl, lvl_end;
1667 : : uint32_t parent, i;
1668 : : int rc = 0;
1669 : :
1670 : : /* Add ROOT, SCH1, SCH2 nodes */
1671 : : parent = ROC_NIX_TM_NODE_ID_INVALID;
1672 [ # # ]: 0 : lvl_end = (nix_tm_have_tl1_access(nix) ? ROC_TM_LVL_SCH3 :
1673 : : ROC_TM_LVL_SCH2);
1674 : :
1675 [ # # ]: 0 : for (lvl = ROC_TM_LVL_ROOT; lvl <= lvl_end; lvl++) {
1676 : : rc = -ENOMEM;
1677 : 0 : node = nix_tm_node_alloc();
1678 [ # # ]: 0 : if (!node)
1679 : 0 : goto error;
1680 : :
1681 : 0 : node->id = nonleaf_id;
1682 : 0 : node->parent_id = parent;
1683 : 0 : node->priority = 0;
1684 : 0 : node->weight = NIX_TM_DFLT_RR_WT;
1685 : 0 : node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE;
1686 : 0 : node->lvl = lvl;
1687 : 0 : node->tree = ROC_NIX_TM_RLIMIT;
1688 : 0 : node->rel_chan = NIX_TM_CHAN_INVALID;
1689 : :
1690 : 0 : rc = nix_tm_node_add(roc_nix, node);
1691 [ # # ]: 0 : if (rc)
1692 : 0 : goto error;
1693 : : parent = nonleaf_id;
1694 : 0 : nonleaf_id++;
1695 : : }
1696 : :
1697 : : /* SMQ is mapped to SCH4 when we have TL1 access and SCH3 otherwise */
1698 [ # # ]: 0 : lvl = (nix_tm_have_tl1_access(nix) ? ROC_TM_LVL_SCH4 : ROC_TM_LVL_SCH3);
1699 : :
1700 : : /* Add per queue SMQ nodes i.e SCH4 / SCH3 */
1701 [ # # ]: 0 : for (i = 0; i < nix->nb_tx_queues; i++) {
1702 : : rc = -ENOMEM;
1703 : 0 : node = nix_tm_node_alloc();
1704 [ # # ]: 0 : if (!node)
1705 : 0 : goto error;
1706 : :
1707 : 0 : node->id = nonleaf_id + i;
1708 : 0 : node->parent_id = parent;
1709 : 0 : node->priority = 0;
1710 : 0 : node->weight = NIX_TM_DFLT_RR_WT;
1711 : 0 : node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE;
1712 : 0 : node->lvl = lvl;
1713 : 0 : node->tree = ROC_NIX_TM_RLIMIT;
1714 : 0 : node->rel_chan = NIX_TM_CHAN_INVALID;
1715 : :
1716 : 0 : rc = nix_tm_node_add(roc_nix, node);
1717 [ # # ]: 0 : if (rc)
1718 : 0 : goto error;
1719 : : }
1720 : :
1721 : : parent = nonleaf_id;
1722 [ # # ]: 0 : leaf_lvl = (nix_tm_have_tl1_access(nix) ? ROC_TM_LVL_QUEUE :
1723 : : ROC_TM_LVL_SCH4);
1724 : :
1725 : : /* Add leaf nodes */
1726 [ # # ]: 0 : for (i = 0; i < nix->nb_tx_queues; i++) {
1727 : : rc = -ENOMEM;
1728 : 0 : node = nix_tm_node_alloc();
1729 [ # # ]: 0 : if (!node)
1730 : 0 : goto error;
1731 : :
1732 : 0 : node->id = i;
1733 : 0 : node->parent_id = parent + i;
1734 : 0 : node->priority = 0;
1735 : 0 : node->weight = NIX_TM_DFLT_RR_WT;
1736 : 0 : node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE;
1737 : 0 : node->lvl = leaf_lvl;
1738 : 0 : node->tree = ROC_NIX_TM_RLIMIT;
1739 : 0 : node->rel_chan = NIX_TM_CHAN_INVALID;
1740 : :
1741 : 0 : rc = nix_tm_node_add(roc_nix, node);
1742 [ # # ]: 0 : if (rc)
1743 : 0 : goto error;
1744 : : }
1745 : :
1746 : : return 0;
1747 : 0 : error:
1748 : 0 : nix_tm_node_free(node);
1749 : 0 : return rc;
1750 : : }
1751 : :
1752 : : int
1753 : 0 : roc_nix_tm_pfc_prepare_tree(struct roc_nix *roc_nix)
1754 : : {
1755 : : struct nix *nix = roc_nix_to_nix_priv(roc_nix);
1756 : : uint8_t leaf_lvl, lvl, lvl_start, lvl_end;
1757 [ # # ]: 0 : uint32_t nonleaf_id = nix->nb_tx_queues;
1758 : : struct nix_tm_node *node = NULL;
1759 : : uint32_t tl2_node_id;
1760 : : uint32_t parent, i;
1761 : : int rc = -ENOMEM;
1762 : :
1763 : : parent = ROC_NIX_TM_NODE_ID_INVALID;
1764 [ # # ]: 0 : lvl_end = (nix_tm_have_tl1_access(nix) ? ROC_TM_LVL_SCH3 :
1765 : : ROC_TM_LVL_SCH2);
1766 [ # # ]: 0 : leaf_lvl = (nix_tm_have_tl1_access(nix) ? ROC_TM_LVL_QUEUE :
1767 : : ROC_TM_LVL_SCH4);
1768 : :
1769 : : /* TL1 node */
1770 : 0 : node = nix_tm_node_alloc();
1771 [ # # ]: 0 : if (!node)
1772 : 0 : goto error;
1773 : :
1774 : 0 : node->id = nonleaf_id;
1775 : 0 : node->parent_id = parent;
1776 : 0 : node->priority = 0;
1777 : 0 : node->weight = NIX_TM_DFLT_RR_WT;
1778 : 0 : node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE;
1779 : 0 : node->lvl = ROC_TM_LVL_ROOT;
1780 : 0 : node->tree = ROC_NIX_TM_PFC;
1781 : 0 : node->rel_chan = NIX_TM_CHAN_INVALID;
1782 : :
1783 : 0 : rc = nix_tm_node_add(roc_nix, node);
1784 [ # # ]: 0 : if (rc)
1785 : 0 : goto error;
1786 : :
1787 : : parent = nonleaf_id;
1788 : 0 : nonleaf_id++;
1789 : :
1790 : : lvl_start = ROC_TM_LVL_SCH1;
1791 [ # # ]: 0 : if (roc_nix_is_pf(roc_nix)) {
1792 : : /* TL2 node */
1793 : : rc = -ENOMEM;
1794 : 0 : node = nix_tm_node_alloc();
1795 [ # # ]: 0 : if (!node)
1796 : 0 : goto error;
1797 : :
1798 : 0 : node->id = nonleaf_id;
1799 : 0 : node->parent_id = parent;
1800 : 0 : node->priority = 0;
1801 : 0 : node->weight = NIX_TM_DFLT_RR_WT;
1802 : 0 : node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE;
1803 : 0 : node->lvl = ROC_TM_LVL_SCH1;
1804 : 0 : node->tree = ROC_NIX_TM_PFC;
1805 : 0 : node->rel_chan = NIX_TM_CHAN_INVALID;
1806 : :
1807 : 0 : rc = nix_tm_node_add(roc_nix, node);
1808 [ # # ]: 0 : if (rc)
1809 : 0 : goto error;
1810 : :
1811 : : lvl_start = ROC_TM_LVL_SCH2;
1812 : : tl2_node_id = nonleaf_id;
1813 : 0 : nonleaf_id++;
1814 : : } else {
1815 : : tl2_node_id = parent;
1816 : : }
1817 : :
1818 [ # # ]: 0 : for (i = 0; i < nix->nb_tx_queues; i++) {
1819 : : parent = tl2_node_id;
1820 [ # # ]: 0 : for (lvl = lvl_start; lvl <= lvl_end; lvl++) {
1821 : : rc = -ENOMEM;
1822 : 0 : node = nix_tm_node_alloc();
1823 [ # # ]: 0 : if (!node)
1824 : 0 : goto error;
1825 : :
1826 : 0 : node->id = nonleaf_id;
1827 : 0 : node->parent_id = parent;
1828 : 0 : node->priority = 0;
1829 : 0 : node->weight = NIX_TM_DFLT_RR_WT;
1830 : 0 : node->shaper_profile_id =
1831 : : ROC_NIX_TM_SHAPER_PROFILE_NONE;
1832 : 0 : node->lvl = lvl;
1833 : 0 : node->tree = ROC_NIX_TM_PFC;
1834 : 0 : node->rel_chan = NIX_TM_CHAN_INVALID;
1835 : :
1836 : 0 : rc = nix_tm_node_add(roc_nix, node);
1837 [ # # ]: 0 : if (rc)
1838 : 0 : goto error;
1839 : :
1840 : : parent = nonleaf_id;
1841 : 0 : nonleaf_id++;
1842 : : }
1843 : :
1844 [ # # ]: 0 : lvl = (nix_tm_have_tl1_access(nix) ? ROC_TM_LVL_SCH4 :
1845 : : ROC_TM_LVL_SCH3);
1846 : :
1847 : : rc = -ENOMEM;
1848 : 0 : node = nix_tm_node_alloc();
1849 [ # # ]: 0 : if (!node)
1850 : 0 : goto error;
1851 : :
1852 : 0 : node->id = nonleaf_id;
1853 : 0 : node->parent_id = parent;
1854 : 0 : node->priority = 0;
1855 : 0 : node->weight = NIX_TM_DFLT_RR_WT;
1856 : 0 : node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE;
1857 : 0 : node->lvl = lvl;
1858 : 0 : node->tree = ROC_NIX_TM_PFC;
1859 : 0 : node->rel_chan = NIX_TM_CHAN_INVALID;
1860 : :
1861 : 0 : rc = nix_tm_node_add(roc_nix, node);
1862 [ # # ]: 0 : if (rc)
1863 : 0 : goto error;
1864 : :
1865 : : parent = nonleaf_id;
1866 : 0 : nonleaf_id++;
1867 : :
1868 : : rc = -ENOMEM;
1869 : 0 : node = nix_tm_node_alloc();
1870 [ # # ]: 0 : if (!node)
1871 : 0 : goto error;
1872 : :
1873 : 0 : node->id = i;
1874 : 0 : node->parent_id = parent;
1875 : 0 : node->priority = 0;
1876 : 0 : node->weight = NIX_TM_DFLT_RR_WT;
1877 : 0 : node->shaper_profile_id = ROC_NIX_TM_SHAPER_PROFILE_NONE;
1878 : 0 : node->lvl = leaf_lvl;
1879 : 0 : node->tree = ROC_NIX_TM_PFC;
1880 : 0 : node->rel_chan = NIX_TM_CHAN_INVALID;
1881 : :
1882 : 0 : rc = nix_tm_node_add(roc_nix, node);
1883 [ # # ]: 0 : if (rc)
1884 : 0 : goto error;
1885 : : }
1886 : :
1887 : : return 0;
1888 : 0 : error:
1889 : 0 : nix_tm_node_free(node);
1890 : 0 : return rc;
1891 : : }
1892 : :
1893 : : int
1894 : 0 : nix_tm_free_resources(struct roc_nix *roc_nix, uint32_t tree_mask, bool hw_only)
1895 : : {
1896 : : struct nix *nix = roc_nix_to_nix_priv(roc_nix);
1897 : : struct nix_tm_shaper_profile *profile;
1898 : : struct nix_tm_node *node, *next_node;
1899 : : struct nix_tm_node_list *list;
1900 : : enum roc_nix_tm_tree tree;
1901 : : uint32_t profile_id;
1902 : : int rc = 0;
1903 : : int hw_lvl;
1904 : :
1905 [ # # ]: 0 : for (tree = 0; tree < ROC_NIX_TM_TREE_MAX; tree++) {
1906 [ # # ]: 0 : if (!(tree_mask & BIT(tree)))
1907 : 0 : continue;
1908 : :
1909 : 0 : plt_tm_dbg("Freeing resources of tree %u", tree);
1910 : :
1911 : : list = nix_tm_node_list(nix, tree);
1912 : : /* Flush and free resources from leaf */
1913 [ # # ]: 0 : for (hw_lvl = NIX_TXSCH_LVL_SMQ; hw_lvl < NIX_TXSCH_LVL_CNT; hw_lvl++) {
1914 : 0 : next_node = TAILQ_FIRST(list);
1915 [ # # ]: 0 : while (next_node) {
1916 : : node = next_node;
1917 : 0 : next_node = TAILQ_NEXT(node, node);
1918 [ # # ]: 0 : if (node->hw_lvl != hw_lvl)
1919 : 0 : continue;
1920 : :
1921 [ # # # # ]: 0 : if (!nix_tm_is_leaf(nix, node->lvl) &&
1922 [ # # ]: 0 : node->flags & NIX_TM_NODE_HWRES) {
1923 : : /* Clear xoff in path for flush to succeed */
1924 : 0 : rc = nix_tm_clear_path_xoff(nix, node);
1925 [ # # ]: 0 : if (rc)
1926 : 0 : return rc;
1927 : 0 : rc = nix_tm_free_node_resource(nix, node);
1928 [ # # ]: 0 : if (rc)
1929 : 0 : return rc;
1930 : : }
1931 : : }
1932 : : }
1933 : :
1934 : : /* Leave software elements if needed */
1935 [ # # ]: 0 : if (hw_only)
1936 : 0 : continue;
1937 : :
1938 : 0 : next_node = TAILQ_FIRST(list);
1939 [ # # ]: 0 : while (next_node) {
1940 : : node = next_node;
1941 : 0 : next_node = TAILQ_NEXT(node, node);
1942 : :
1943 : 0 : plt_tm_dbg("Free node lvl %u id %u (%p)", node->lvl,
1944 : : node->id, node);
1945 : :
1946 : 0 : profile_id = node->shaper_profile_id;
1947 : 0 : profile = nix_tm_shaper_profile_search(nix, profile_id);
1948 [ # # ]: 0 : if (profile)
1949 : 0 : profile->ref_cnt--;
1950 : :
1951 [ # # ]: 0 : TAILQ_REMOVE(list, node, node);
1952 : 0 : nix_tm_node_free(node);
1953 : : }
1954 : : }
1955 : : return rc;
1956 : : }
1957 : :
1958 : : int
1959 : 0 : nix_tm_conf_init(struct roc_nix *roc_nix)
1960 : : {
1961 : : struct nix *nix = roc_nix_to_nix_priv(roc_nix);
1962 : : uint32_t bmp_sz, hw_lvl;
1963 : : void *bmp_mem;
1964 : : int rc, i;
1965 : :
1966 : : PLT_STATIC_ASSERT(sizeof(struct nix_tm_node) <= ROC_NIX_TM_NODE_SZ);
1967 : : PLT_STATIC_ASSERT(sizeof(struct nix_tm_shaper_profile) <=
1968 : : ROC_NIX_TM_SHAPER_PROFILE_SZ);
1969 : :
1970 : 0 : nix->tm_flags = 0;
1971 [ # # ]: 0 : for (i = 0; i < ROC_NIX_TM_TREE_MAX; i++)
1972 : 0 : TAILQ_INIT(&nix->trees[i]);
1973 : :
1974 : 0 : TAILQ_INIT(&nix->shaper_profile_list);
1975 : 0 : nix->tm_rate_min = 1E9; /* 1Gbps */
1976 : :
1977 : : rc = -ENOMEM;
1978 : : bmp_sz = plt_bitmap_get_memory_footprint(NIX_TM_MAX_HW_TXSCHQ);
1979 : 0 : bmp_mem = plt_zmalloc(bmp_sz * NIX_TXSCH_LVL_CNT * 2, 0);
1980 [ # # ]: 0 : if (!bmp_mem)
1981 : : return rc;
1982 : 0 : nix->schq_bmp_mem = bmp_mem;
1983 : :
1984 : : /* Init contiguous and discontiguous bitmap per lvl */
1985 : : rc = -EIO;
1986 [ # # ]: 0 : for (hw_lvl = 0; hw_lvl < NIX_TXSCH_LVL_CNT; hw_lvl++) {
1987 : : /* Bitmap for discontiguous resource */
1988 : 0 : nix->schq_bmp[hw_lvl] =
1989 : 0 : plt_bitmap_init(NIX_TM_MAX_HW_TXSCHQ, bmp_mem, bmp_sz);
1990 [ # # ]: 0 : if (!nix->schq_bmp[hw_lvl])
1991 : 0 : goto exit;
1992 : :
1993 : 0 : bmp_mem = PLT_PTR_ADD(bmp_mem, bmp_sz);
1994 : :
1995 : : /* Bitmap for contiguous resource */
1996 : 0 : nix->schq_contig_bmp[hw_lvl] =
1997 : 0 : plt_bitmap_init(NIX_TM_MAX_HW_TXSCHQ, bmp_mem, bmp_sz);
1998 [ # # ]: 0 : if (!nix->schq_contig_bmp[hw_lvl])
1999 : 0 : goto exit;
2000 : :
2001 : 0 : bmp_mem = PLT_PTR_ADD(bmp_mem, bmp_sz);
2002 : : }
2003 : :
2004 : 0 : rc = nix_tm_mark_init(nix);
2005 [ # # ]: 0 : if (rc)
2006 : 0 : goto exit;
2007 : :
2008 : : /* Disable TL1 Static Priority when VF's are enabled
2009 : : * as otherwise VF's TL2 reallocation will be needed
2010 : : * runtime to support a specific topology of PF.
2011 : : */
2012 [ # # ]: 0 : if (nix->pci_dev->max_vfs)
2013 : 0 : nix->tm_flags |= NIX_TM_TL1_NO_SP;
2014 : :
2015 : : /* TL1 access is only for PF's */
2016 [ # # ]: 0 : if (roc_nix_is_pf(roc_nix)) {
2017 : 0 : nix->tm_flags |= NIX_TM_TL1_ACCESS;
2018 : 0 : nix->tm_root_lvl = NIX_TXSCH_LVL_TL1;
2019 : : } else {
2020 : 0 : nix->tm_root_lvl = NIX_TXSCH_LVL_TL2;
2021 : : }
2022 : :
2023 : : return 0;
2024 : 0 : exit:
2025 : 0 : nix_tm_conf_fini(roc_nix);
2026 : 0 : return rc;
2027 : : }
2028 : :
2029 : : void
2030 : 0 : nix_tm_conf_fini(struct roc_nix *roc_nix)
2031 : : {
2032 : : struct nix *nix = roc_nix_to_nix_priv(roc_nix);
2033 : : uint16_t hw_lvl;
2034 : :
2035 : : for (hw_lvl = 0; hw_lvl < NIX_TXSCH_LVL_CNT; hw_lvl++) {
2036 : : plt_bitmap_free(nix->schq_bmp[hw_lvl]);
2037 : : plt_bitmap_free(nix->schq_contig_bmp[hw_lvl]);
2038 : : }
2039 : 0 : plt_free(nix->schq_bmp_mem);
2040 : 0 : }
|