Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2022 Intel Corporation
3 : : */
4 : : #include <rte_tm_driver.h>
5 : :
6 : : #include "ice_ethdev.h"
7 : : #include "ice_rxtx.h"
8 : :
9 : : #define MAX_CHILDREN_PER_SCHED_NODE 8
10 : : #define MAX_CHILDREN_PER_TM_NODE 256
11 : :
12 : : static int ice_hierarchy_commit(struct rte_eth_dev *dev,
13 : : int clear_on_fail,
14 : : __rte_unused struct rte_tm_error *error);
15 : : static int ice_tm_node_add(struct rte_eth_dev *dev, uint32_t node_id,
16 : : uint32_t parent_node_id, uint32_t priority,
17 : : uint32_t weight, uint32_t level_id,
18 : : struct rte_tm_node_params *params,
19 : : struct rte_tm_error *error);
20 : : static int ice_tm_node_delete(struct rte_eth_dev *dev, uint32_t node_id,
21 : : struct rte_tm_error *error);
22 : : static int ice_node_type_get(struct rte_eth_dev *dev, uint32_t node_id,
23 : : int *is_leaf, struct rte_tm_error *error);
24 : : static int ice_shaper_profile_add(struct rte_eth_dev *dev,
25 : : uint32_t shaper_profile_id,
26 : : struct rte_tm_shaper_params *profile,
27 : : struct rte_tm_error *error);
28 : : static int ice_shaper_profile_del(struct rte_eth_dev *dev,
29 : : uint32_t shaper_profile_id,
30 : : struct rte_tm_error *error);
31 : :
32 : : const struct rte_tm_ops ice_tm_ops = {
33 : : .shaper_profile_add = ice_shaper_profile_add,
34 : : .shaper_profile_delete = ice_shaper_profile_del,
35 : : .node_add = ice_tm_node_add,
36 : : .node_delete = ice_tm_node_delete,
37 : : .node_type_get = ice_node_type_get,
38 : : .hierarchy_commit = ice_hierarchy_commit,
39 : : };
40 : :
41 : : void
42 : 0 : ice_tm_conf_init(struct rte_eth_dev *dev)
43 : : {
44 : 0 : struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private);
45 : :
46 : : /* initialize node configuration */
47 : 0 : TAILQ_INIT(&pf->tm_conf.shaper_profile_list);
48 : 0 : pf->tm_conf.root = NULL;
49 : 0 : pf->tm_conf.committed = false;
50 : 0 : pf->tm_conf.clear_on_fail = false;
51 : 0 : }
52 : :
53 : 0 : static void free_node(struct ice_tm_node *root)
54 : : {
55 : : uint32_t i;
56 : :
57 [ # # ]: 0 : if (root == NULL)
58 : : return;
59 : :
60 [ # # ]: 0 : for (i = 0; i < root->reference_count; i++)
61 : 0 : free_node(root->children[i]);
62 : :
63 : 0 : rte_free(root);
64 : : }
65 : :
66 : : void
67 : 0 : ice_tm_conf_uninit(struct rte_eth_dev *dev)
68 : : {
69 : 0 : struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private);
70 : : struct ice_tm_shaper_profile *shaper_profile;
71 : :
72 : : /* clear profile */
73 [ # # ]: 0 : while ((shaper_profile = TAILQ_FIRST(&pf->tm_conf.shaper_profile_list))) {
74 [ # # ]: 0 : TAILQ_REMOVE(&pf->tm_conf.shaper_profile_list, shaper_profile, node);
75 : 0 : rte_free(shaper_profile);
76 : : }
77 : :
78 : 0 : free_node(pf->tm_conf.root);
79 : 0 : pf->tm_conf.root = NULL;
80 : 0 : }
81 : :
82 : : static int
83 : 0 : ice_node_param_check(struct ice_pf *pf, uint32_t node_id,
84 : : uint32_t priority, uint32_t weight,
85 : : struct rte_tm_node_params *params,
86 : : struct rte_tm_error *error)
87 : : {
88 : : /* checked all the unsupported parameter */
89 [ # # ]: 0 : if (node_id == RTE_TM_NODE_ID_NULL) {
90 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
91 : 0 : error->message = "invalid node id";
92 : 0 : return -EINVAL;
93 : : }
94 : :
95 [ # # ]: 0 : if (priority >= 8) {
96 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PRIORITY;
97 : 0 : error->message = "priority should be less than 8";
98 : 0 : return -EINVAL;
99 : : }
100 : :
101 [ # # ]: 0 : if (weight > 200 || weight < 1) {
102 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_WEIGHT;
103 : 0 : error->message = "weight must be between 1 and 200";
104 : 0 : return -EINVAL;
105 : : }
106 : :
107 : : /* not support shared shaper */
108 [ # # ]: 0 : if (params->shared_shaper_id) {
109 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_SHAPER_ID;
110 : 0 : error->message = "shared shaper not supported";
111 : 0 : return -EINVAL;
112 : : }
113 [ # # ]: 0 : if (params->n_shared_shapers) {
114 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS;
115 : 0 : error->message = "shared shaper not supported";
116 : 0 : return -EINVAL;
117 : : }
118 : :
119 : : /* for non-leaf node */
120 [ # # ]: 0 : if (node_id >= pf->dev_data->nb_tx_queues) {
121 [ # # ]: 0 : if (params->nonleaf.wfq_weight_mode) {
122 : 0 : error->type =
123 : : RTE_TM_ERROR_TYPE_NODE_PARAMS_WFQ_WEIGHT_MODE;
124 : 0 : error->message = "WFQ not supported";
125 : 0 : return -EINVAL;
126 : : }
127 [ # # ]: 0 : if (params->nonleaf.n_sp_priorities != 1) {
128 : 0 : error->type =
129 : : RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SP_PRIORITIES;
130 : 0 : error->message = "SP priority not supported";
131 : 0 : return -EINVAL;
132 : : } else if (params->nonleaf.wfq_weight_mode &&
133 : : !(*params->nonleaf.wfq_weight_mode)) {
134 : : error->type =
135 : : RTE_TM_ERROR_TYPE_NODE_PARAMS_WFQ_WEIGHT_MODE;
136 : : error->message = "WFP should be byte mode";
137 : : return -EINVAL;
138 : : }
139 : :
140 : : return 0;
141 : : }
142 : :
143 : : /* for leaf node */
144 [ # # ]: 0 : if (params->leaf.cman) {
145 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_CMAN;
146 : 0 : error->message = "Congestion management not supported";
147 : 0 : return -EINVAL;
148 : : }
149 [ # # ]: 0 : if (params->leaf.wred.wred_profile_id !=
150 : : RTE_TM_WRED_PROFILE_ID_NONE) {
151 : 0 : error->type =
152 : : RTE_TM_ERROR_TYPE_NODE_PARAMS_WRED_PROFILE_ID;
153 : 0 : error->message = "WRED not supported";
154 : 0 : return -EINVAL;
155 : : }
156 [ # # ]: 0 : if (params->leaf.wred.shared_wred_context_id) {
157 : 0 : error->type =
158 : : RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_WRED_CONTEXT_ID;
159 : 0 : error->message = "WRED not supported";
160 : 0 : return -EINVAL;
161 : : }
162 [ # # ]: 0 : if (params->leaf.wred.n_shared_wred_contexts) {
163 : 0 : error->type =
164 : : RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_WRED_CONTEXTS;
165 : 0 : error->message = "WRED not supported";
166 : 0 : return -EINVAL;
167 : : }
168 : :
169 : : return 0;
170 : : }
171 : :
172 : : static struct ice_tm_node *
173 : 0 : find_node(struct ice_tm_node *root, uint32_t id)
174 : : {
175 : : uint32_t i;
176 : :
177 [ # # # # ]: 0 : if (root == NULL || root->id == id)
178 : : return root;
179 : :
180 [ # # ]: 0 : for (i = 0; i < root->reference_count; i++) {
181 : 0 : struct ice_tm_node *node = find_node(root->children[i], id);
182 : :
183 [ # # ]: 0 : if (node)
184 : 0 : return node;
185 : : }
186 : :
187 : : return NULL;
188 : : }
189 : :
190 : : static int
191 : 0 : ice_node_type_get(struct rte_eth_dev *dev, uint32_t node_id,
192 : : int *is_leaf, struct rte_tm_error *error)
193 : : {
194 : 0 : struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private);
195 : : struct ice_tm_node *tm_node;
196 : :
197 [ # # ]: 0 : if (!is_leaf || !error)
198 : : return -EINVAL;
199 : :
200 [ # # ]: 0 : if (node_id == RTE_TM_NODE_ID_NULL) {
201 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
202 : 0 : error->message = "invalid node id";
203 : 0 : return -EINVAL;
204 : : }
205 : :
206 : : /* check if the node id exists */
207 : 0 : tm_node = find_node(pf->tm_conf.root, node_id);
208 [ # # ]: 0 : if (!tm_node) {
209 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
210 : 0 : error->message = "no such node";
211 : 0 : return -EINVAL;
212 : : }
213 : :
214 [ # # ]: 0 : if (tm_node->level == ICE_TM_NODE_TYPE_QUEUE)
215 : 0 : *is_leaf = true;
216 : : else
217 : 0 : *is_leaf = false;
218 : :
219 : : return 0;
220 : : }
221 : :
222 : : static inline struct ice_tm_shaper_profile *
223 : : ice_shaper_profile_search(struct rte_eth_dev *dev,
224 : : uint32_t shaper_profile_id)
225 : : {
226 : : struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private);
227 : : struct ice_shaper_profile_list *shaper_profile_list =
228 : : &pf->tm_conf.shaper_profile_list;
229 : : struct ice_tm_shaper_profile *shaper_profile;
230 : :
231 [ # # # # : 0 : TAILQ_FOREACH(shaper_profile, shaper_profile_list, node) {
# # ]
232 [ # # # # : 0 : if (shaper_profile_id == shaper_profile->shaper_profile_id)
# # ]
233 : : return shaper_profile;
234 : : }
235 : :
236 : : return NULL;
237 : : }
238 : :
239 : : static int
240 : : ice_shaper_profile_param_check(struct rte_tm_shaper_params *profile,
241 : : struct rte_tm_error *error)
242 : : {
243 : : /* min bucket size not supported */
244 [ # # ]: 0 : if (profile->committed.size) {
245 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_SIZE;
246 : 0 : error->message = "committed bucket size not supported";
247 : : return -EINVAL;
248 : : }
249 : : /* max bucket size not supported */
250 [ # # ]: 0 : if (profile->peak.size) {
251 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE;
252 : 0 : error->message = "peak bucket size not supported";
253 : : return -EINVAL;
254 : : }
255 : : /* length adjustment not supported */
256 [ # # ]: 0 : if (profile->pkt_length_adjust) {
257 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PKT_ADJUST_LEN;
258 : 0 : error->message = "packet length adjustment not supported";
259 : : return -EINVAL;
260 : : }
261 : :
262 : : return 0;
263 : : }
264 : :
265 : : static int
266 : 0 : ice_shaper_profile_add(struct rte_eth_dev *dev,
267 : : uint32_t shaper_profile_id,
268 : : struct rte_tm_shaper_params *profile,
269 : : struct rte_tm_error *error)
270 : : {
271 : 0 : struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private);
272 : : struct ice_tm_shaper_profile *shaper_profile;
273 : : int ret;
274 : :
275 [ # # ]: 0 : if (!profile || !error)
276 : : return -EINVAL;
277 : :
278 : : ret = ice_shaper_profile_param_check(profile, error);
279 : : if (ret)
280 : 0 : return ret;
281 : :
282 : : shaper_profile = ice_shaper_profile_search(dev, shaper_profile_id);
283 : :
284 [ # # ]: 0 : if (shaper_profile) {
285 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID;
286 : 0 : error->message = "profile ID exist";
287 : 0 : return -EINVAL;
288 : : }
289 : :
290 : 0 : shaper_profile = rte_zmalloc("ice_tm_shaper_profile",
291 : : sizeof(struct ice_tm_shaper_profile),
292 : : 0);
293 [ # # ]: 0 : if (!shaper_profile)
294 : : return -ENOMEM;
295 : 0 : shaper_profile->shaper_profile_id = shaper_profile_id;
296 [ # # ]: 0 : rte_memcpy(&shaper_profile->profile, profile,
297 : : sizeof(struct rte_tm_shaper_params));
298 : 0 : TAILQ_INSERT_TAIL(&pf->tm_conf.shaper_profile_list,
299 : : shaper_profile, node);
300 : :
301 : 0 : return 0;
302 : : }
303 : :
304 : : static int
305 : 0 : ice_shaper_profile_del(struct rte_eth_dev *dev,
306 : : uint32_t shaper_profile_id,
307 : : struct rte_tm_error *error)
308 : : {
309 : 0 : struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private);
310 : : struct ice_tm_shaper_profile *shaper_profile;
311 : :
312 [ # # ]: 0 : if (!error)
313 : : return -EINVAL;
314 : :
315 : : shaper_profile = ice_shaper_profile_search(dev, shaper_profile_id);
316 : :
317 [ # # ]: 0 : if (!shaper_profile) {
318 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID;
319 : 0 : error->message = "profile ID not exist";
320 : 0 : return -EINVAL;
321 : : }
322 : :
323 : : /* don't delete a profile if it's used by one or several nodes */
324 [ # # ]: 0 : if (shaper_profile->reference_count) {
325 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE;
326 : 0 : error->message = "profile in use";
327 : 0 : return -EINVAL;
328 : : }
329 : :
330 [ # # ]: 0 : TAILQ_REMOVE(&pf->tm_conf.shaper_profile_list, shaper_profile, node);
331 : 0 : rte_free(shaper_profile);
332 : :
333 : 0 : return 0;
334 : : }
335 : :
336 : : static int
337 : 0 : ice_tm_node_add(struct rte_eth_dev *dev, uint32_t node_id,
338 : : uint32_t parent_node_id, uint32_t priority,
339 : : uint32_t weight, uint32_t level_id,
340 : : struct rte_tm_node_params *params,
341 : : struct rte_tm_error *error)
342 : : {
343 : 0 : struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private);
344 : : struct ice_tm_shaper_profile *shaper_profile = NULL;
345 : : struct ice_tm_node *tm_node;
346 : : struct ice_tm_node *parent_node;
347 : : int ret;
348 : :
349 [ # # ]: 0 : if (!params || !error)
350 : : return -EINVAL;
351 : :
352 : 0 : ret = ice_node_param_check(pf, node_id, priority, weight,
353 : : params, error);
354 [ # # ]: 0 : if (ret)
355 : : return ret;
356 : :
357 : : /* check if the node is already existed */
358 [ # # ]: 0 : if (find_node(pf->tm_conf.root, node_id)) {
359 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
360 : 0 : error->message = "node id already used";
361 : 0 : return -EINVAL;
362 : : }
363 : :
364 : : /* check the shaper profile id */
365 [ # # ]: 0 : if (params->shaper_profile_id != RTE_TM_SHAPER_PROFILE_ID_NONE) {
366 : : shaper_profile = ice_shaper_profile_search(dev,
367 : : params->shaper_profile_id);
368 [ # # ]: 0 : if (!shaper_profile) {
369 : 0 : error->type =
370 : : RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID;
371 : 0 : error->message = "shaper profile not exist";
372 : 0 : return -EINVAL;
373 : : }
374 : : }
375 : :
376 : : /* root node if not have a parent */
377 [ # # ]: 0 : if (parent_node_id == RTE_TM_NODE_ID_NULL) {
378 : : /* check level */
379 [ # # ]: 0 : if (level_id != ICE_TM_NODE_TYPE_PORT) {
380 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;
381 : 0 : error->message = "Wrong level";
382 : 0 : return -EINVAL;
383 : : }
384 : :
385 : : /* obviously no more than one root */
386 [ # # ]: 0 : if (pf->tm_conf.root) {
387 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;
388 : 0 : error->message = "already have a root";
389 : 0 : return -EINVAL;
390 : : }
391 : :
392 : : /* add the root node */
393 : 0 : tm_node = rte_zmalloc(NULL,
394 : : sizeof(struct ice_tm_node) +
395 : : sizeof(struct ice_tm_node *) * MAX_CHILDREN_PER_TM_NODE,
396 : : 0);
397 [ # # ]: 0 : if (!tm_node)
398 : : return -ENOMEM;
399 : 0 : tm_node->id = node_id;
400 : 0 : tm_node->level = ICE_TM_NODE_TYPE_PORT;
401 : 0 : tm_node->parent = NULL;
402 : 0 : tm_node->reference_count = 0;
403 : 0 : tm_node->shaper_profile = shaper_profile;
404 : 0 : tm_node->children =
405 : 0 : (void *)((uint8_t *)tm_node + sizeof(struct ice_tm_node));
406 [ # # ]: 0 : rte_memcpy(&tm_node->params, params,
407 : : sizeof(struct rte_tm_node_params));
408 : 0 : pf->tm_conf.root = tm_node;
409 : 0 : return 0;
410 : : }
411 : :
412 : : /* check the parent node */
413 : 0 : parent_node = find_node(pf->tm_conf.root, parent_node_id);
414 [ # # ]: 0 : if (!parent_node) {
415 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;
416 : 0 : error->message = "parent not exist";
417 : 0 : return -EINVAL;
418 : : }
419 [ # # ]: 0 : if (parent_node->level != ICE_TM_NODE_TYPE_PORT &&
420 : : parent_node->level != ICE_TM_NODE_TYPE_QGROUP) {
421 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;
422 : 0 : error->message = "parent is not valid";
423 : 0 : return -EINVAL;
424 : : }
425 : : /* check level */
426 [ # # ]: 0 : if (level_id != RTE_TM_NODE_LEVEL_ID_ANY &&
427 [ # # ]: 0 : level_id != parent_node->level + 1) {
428 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;
429 : 0 : error->message = "Wrong level";
430 : 0 : return -EINVAL;
431 : : }
432 : :
433 : : /* check the node number */
434 [ # # ]: 0 : if (parent_node->level == ICE_TM_NODE_TYPE_PORT) {
435 : : /* check the queue group number */
436 [ # # ]: 0 : if (parent_node->reference_count >= pf->dev_data->nb_tx_queues) {
437 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
438 : 0 : error->message = "too many queue groups";
439 : 0 : return -EINVAL;
440 : : }
441 : : } else {
442 : : /* check the queue number */
443 [ # # ]: 0 : if (parent_node->reference_count >=
444 : : MAX_CHILDREN_PER_SCHED_NODE) {
445 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
446 : 0 : error->message = "too many queues";
447 : 0 : return -EINVAL;
448 : : }
449 [ # # ]: 0 : if (node_id >= pf->dev_data->nb_tx_queues) {
450 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
451 : 0 : error->message = "too large queue id";
452 : 0 : return -EINVAL;
453 : : }
454 : : }
455 : :
456 : 0 : tm_node = rte_zmalloc(NULL,
457 : : sizeof(struct ice_tm_node) +
458 : : sizeof(struct ice_tm_node *) * MAX_CHILDREN_PER_TM_NODE,
459 : : 0);
460 [ # # ]: 0 : if (!tm_node)
461 : : return -ENOMEM;
462 : 0 : tm_node->id = node_id;
463 : 0 : tm_node->priority = priority;
464 : 0 : tm_node->weight = weight;
465 : 0 : tm_node->reference_count = 0;
466 : 0 : tm_node->parent = parent_node;
467 : 0 : tm_node->level = parent_node->level + 1;
468 : 0 : tm_node->shaper_profile = shaper_profile;
469 : 0 : tm_node->children =
470 : 0 : (void *)((uint8_t *)tm_node + sizeof(struct ice_tm_node));
471 : 0 : tm_node->parent->children[tm_node->parent->reference_count] = tm_node;
472 : :
473 [ # # # # ]: 0 : if (tm_node->priority != 0 && level_id != ICE_TM_NODE_TYPE_QUEUE &&
474 : : level_id != ICE_TM_NODE_TYPE_QGROUP)
475 : 0 : PMD_DRV_LOG(WARNING, "priority != 0 not supported in level %d",
476 : : level_id);
477 : :
478 [ # # ]: 0 : if (tm_node->weight != 1 &&
479 [ # # ]: 0 : level_id != ICE_TM_NODE_TYPE_QUEUE && level_id != ICE_TM_NODE_TYPE_QGROUP)
480 : 0 : PMD_DRV_LOG(WARNING, "weight != 1 not supported in level %d",
481 : : level_id);
482 : :
483 [ # # ]: 0 : rte_memcpy(&tm_node->params, params,
484 : : sizeof(struct rte_tm_node_params));
485 : 0 : tm_node->parent->reference_count++;
486 : :
487 : 0 : return 0;
488 : : }
489 : :
490 : : static int
491 : 0 : ice_tm_node_delete(struct rte_eth_dev *dev, uint32_t node_id,
492 : : struct rte_tm_error *error)
493 : : {
494 : 0 : struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private);
495 : : struct ice_tm_node *tm_node;
496 : : uint32_t i, j;
497 : :
498 [ # # ]: 0 : if (!error)
499 : : return -EINVAL;
500 : :
501 [ # # ]: 0 : if (node_id == RTE_TM_NODE_ID_NULL) {
502 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
503 : 0 : error->message = "invalid node id";
504 : 0 : return -EINVAL;
505 : : }
506 : :
507 : : /* check if the node id exists */
508 : 0 : tm_node = find_node(pf->tm_conf.root, node_id);
509 [ # # ]: 0 : if (!tm_node) {
510 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
511 : 0 : error->message = "no such node";
512 : 0 : return -EINVAL;
513 : : }
514 : :
515 : : /* the node should have no child */
516 [ # # ]: 0 : if (tm_node->reference_count) {
517 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
518 : 0 : error->message =
519 : : "cannot delete a node which has children";
520 : 0 : return -EINVAL;
521 : : }
522 : :
523 : : /* root node */
524 [ # # ]: 0 : if (tm_node->level == ICE_TM_NODE_TYPE_PORT) {
525 : 0 : rte_free(tm_node);
526 : 0 : pf->tm_conf.root = NULL;
527 : 0 : return 0;
528 : : }
529 : :
530 : : /* queue group or queue node */
531 [ # # ]: 0 : for (i = 0; i < tm_node->parent->reference_count; i++)
532 [ # # ]: 0 : if (tm_node->parent->children[i] == tm_node)
533 : : break;
534 : :
535 [ # # ]: 0 : for (j = i ; j < tm_node->parent->reference_count - 1; j++)
536 : 0 : tm_node->parent->children[j] = tm_node->parent->children[j + 1];
537 : :
538 : 0 : tm_node->parent->reference_count--;
539 : 0 : rte_free(tm_node);
540 : :
541 : 0 : return 0;
542 : : }
543 : :
544 : 0 : static int ice_move_recfg_lan_txq(struct rte_eth_dev *dev,
545 : : struct ice_sched_node *queue_sched_node,
546 : : struct ice_sched_node *dst_node,
547 : : uint16_t queue_id)
548 : : {
549 : 0 : struct ice_hw *hw = ICE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
550 : : struct ice_aqc_move_txqs_data *buf;
551 : : struct ice_sched_node *queue_parent_node;
552 : : uint8_t txqs_moved;
553 : : int ret = ICE_SUCCESS;
554 : : uint16_t buf_size = ice_struct_size(buf, txqs, 1);
555 : :
556 : 0 : buf = (struct ice_aqc_move_txqs_data *)ice_malloc(hw, sizeof(*buf));
557 [ # # ]: 0 : if (buf == NULL)
558 : : return -ENOMEM;
559 : :
560 : 0 : queue_parent_node = queue_sched_node->parent;
561 : 0 : buf->src_teid = queue_parent_node->info.node_teid;
562 : 0 : buf->dest_teid = dst_node->info.node_teid;
563 : 0 : buf->txqs[0].q_teid = queue_sched_node->info.node_teid;
564 : 0 : buf->txqs[0].txq_id = queue_id;
565 : :
566 : 0 : ret = ice_aq_move_recfg_lan_txq(hw, 1, true, false, false, false, 50,
567 : : NULL, buf, buf_size, &txqs_moved, NULL);
568 [ # # # # ]: 0 : if (ret || txqs_moved == 0) {
569 : 0 : PMD_DRV_LOG(ERR, "move lan queue %u failed", queue_id);
570 : 0 : rte_free(buf);
571 : 0 : return ICE_ERR_PARAM;
572 : : }
573 : :
574 [ # # ]: 0 : if (queue_parent_node->num_children > 0) {
575 : 0 : queue_parent_node->num_children--;
576 : 0 : queue_parent_node->children[queue_parent_node->num_children] = NULL;
577 : : } else {
578 : 0 : PMD_DRV_LOG(ERR, "invalid children number %d for queue %u",
579 : : queue_parent_node->num_children, queue_id);
580 : 0 : rte_free(buf);
581 : 0 : return ICE_ERR_PARAM;
582 : : }
583 : 0 : dst_node->children[dst_node->num_children++] = queue_sched_node;
584 : 0 : queue_sched_node->parent = dst_node;
585 : 0 : ice_sched_query_elem(hw, queue_sched_node->info.node_teid, &queue_sched_node->info);
586 : :
587 : 0 : rte_free(buf);
588 : 0 : return ret;
589 : : }
590 : :
591 : 0 : static int ice_set_node_rate(struct ice_hw *hw,
592 : : struct ice_tm_node *tm_node,
593 : : struct ice_sched_node *sched_node)
594 : : {
595 : : enum ice_status status;
596 : : bool reset = false;
597 : : uint32_t peak = 0;
598 : : uint32_t committed = 0;
599 : : uint32_t rate;
600 : :
601 [ # # # # ]: 0 : if (tm_node == NULL || tm_node->shaper_profile == NULL) {
602 : : reset = true;
603 : : } else {
604 : 0 : peak = (uint32_t)tm_node->shaper_profile->profile.peak.rate;
605 : 0 : committed = (uint32_t)tm_node->shaper_profile->profile.committed.rate;
606 : : }
607 : :
608 [ # # ]: 0 : if (reset || peak == 0)
609 : : rate = ICE_SCHED_DFLT_BW;
610 : : else
611 : 0 : rate = peak / 1000 * BITS_PER_BYTE;
612 : :
613 : :
614 : 0 : status = ice_sched_set_node_bw_lmt(hw->port_info,
615 : : sched_node,
616 : : ICE_MAX_BW,
617 : : rate);
618 [ # # ]: 0 : if (status)
619 : : return -EINVAL;
620 : :
621 [ # # ]: 0 : if (reset || committed == 0)
622 : : rate = ICE_SCHED_DFLT_BW;
623 : : else
624 : 0 : rate = committed / 1000 * BITS_PER_BYTE;
625 : :
626 : 0 : status = ice_sched_set_node_bw_lmt(hw->port_info,
627 : : sched_node,
628 : : ICE_MIN_BW,
629 : : rate);
630 [ # # ]: 0 : if (status)
631 : 0 : return -EINVAL;
632 : :
633 : : return 0;
634 : : }
635 : :
636 : 0 : static int ice_cfg_hw_node(struct ice_hw *hw,
637 : : struct ice_tm_node *tm_node,
638 : : struct ice_sched_node *sched_node)
639 : : {
640 : : enum ice_status status;
641 : : uint8_t priority;
642 : : uint16_t weight;
643 : : int ret;
644 : :
645 : 0 : ret = ice_set_node_rate(hw, tm_node, sched_node);
646 [ # # ]: 0 : if (ret) {
647 : 0 : PMD_DRV_LOG(ERR,
648 : : "configure queue group %u bandwidth failed",
649 : : sched_node->info.node_teid);
650 : 0 : return ret;
651 : : }
652 : :
653 [ # # ]: 0 : priority = tm_node ? (7 - tm_node->priority) : 0;
654 : 0 : status = ice_sched_cfg_sibl_node_prio(hw->port_info,
655 : : sched_node,
656 : : priority);
657 [ # # ]: 0 : if (status) {
658 : 0 : PMD_DRV_LOG(ERR, "configure node %u priority %u failed",
659 : : sched_node->info.node_teid,
660 : : priority);
661 : 0 : return -EINVAL;
662 : : }
663 : :
664 [ # # ]: 0 : weight = tm_node ? (uint16_t)tm_node->weight : 4;
665 : :
666 : 0 : status = ice_sched_cfg_node_bw_alloc(hw, sched_node,
667 : : ICE_MAX_BW,
668 : : weight);
669 [ # # ]: 0 : if (status) {
670 : 0 : PMD_DRV_LOG(ERR, "configure node %u weight %u failed",
671 : : sched_node->info.node_teid,
672 : : weight);
673 : 0 : return -EINVAL;
674 : : }
675 : :
676 : : return 0;
677 : : }
678 : :
679 : : static struct ice_sched_node *ice_get_vsi_node(struct ice_hw *hw)
680 : : {
681 : 0 : struct ice_sched_node *node = hw->port_info->root;
682 : 0 : uint32_t vsi_layer = hw->num_tx_sched_layers - ICE_VSI_LAYER_OFFSET;
683 : : uint32_t i;
684 : :
685 [ # # # # ]: 0 : for (i = 0; i < vsi_layer; i++)
686 : 0 : node = node->children[0];
687 : :
688 : : return node;
689 : : }
690 : :
691 : 0 : static int ice_reset_noleaf_nodes(struct rte_eth_dev *dev)
692 : : {
693 : 0 : struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private);
694 : 0 : struct ice_hw *hw = ICE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
695 : : struct ice_sched_node *vsi_node = ice_get_vsi_node(hw);
696 : 0 : struct ice_tm_node *root = pf->tm_conf.root;
697 : : uint32_t i;
698 : : int ret;
699 : :
700 : : /* reset vsi_node */
701 : 0 : ret = ice_set_node_rate(hw, NULL, vsi_node);
702 [ # # ]: 0 : if (ret) {
703 : 0 : PMD_DRV_LOG(ERR, "reset vsi node failed");
704 : 0 : return ret;
705 : : }
706 : :
707 [ # # ]: 0 : if (root == NULL)
708 : : return 0;
709 : :
710 [ # # ]: 0 : for (i = 0; i < root->reference_count; i++) {
711 : 0 : struct ice_tm_node *tm_node = root->children[i];
712 : :
713 [ # # ]: 0 : if (tm_node->sched_node == NULL)
714 : 0 : continue;
715 : :
716 : 0 : ret = ice_cfg_hw_node(hw, NULL, tm_node->sched_node);
717 [ # # ]: 0 : if (ret) {
718 : 0 : PMD_DRV_LOG(ERR, "reset queue group node %u failed", tm_node->id);
719 : 0 : return ret;
720 : : }
721 : 0 : tm_node->sched_node = NULL;
722 : : }
723 : :
724 : : return 0;
725 : : }
726 : :
727 : 0 : static int ice_remove_leaf_nodes(struct rte_eth_dev *dev)
728 : : {
729 : : int ret = 0;
730 : : int i;
731 : :
732 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
733 : 0 : ret = ice_tx_queue_stop(dev, i);
734 [ # # ]: 0 : if (ret) {
735 : 0 : PMD_DRV_LOG(ERR, "stop queue %u failed", i);
736 : 0 : break;
737 : : }
738 : : }
739 : :
740 : 0 : return ret;
741 : : }
742 : :
743 : 0 : static int ice_add_leaf_nodes(struct rte_eth_dev *dev)
744 : : {
745 : : int ret = 0;
746 : : int i;
747 : :
748 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
749 : 0 : ret = ice_tx_queue_start(dev, i);
750 [ # # ]: 0 : if (ret) {
751 : 0 : PMD_DRV_LOG(ERR, "start queue %u failed", i);
752 : 0 : break;
753 : : }
754 : : }
755 : :
756 : 0 : return ret;
757 : : }
758 : :
759 : 0 : int ice_do_hierarchy_commit(struct rte_eth_dev *dev,
760 : : int clear_on_fail,
761 : : struct rte_tm_error *error)
762 : : {
763 : 0 : struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private);
764 : 0 : struct ice_hw *hw = ICE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
765 : : struct ice_tm_node *root;
766 : : struct ice_sched_node *vsi_node = NULL;
767 : : struct ice_sched_node *queue_node;
768 : : struct ice_tx_queue *txq;
769 : : int ret_val = 0;
770 : : uint32_t i;
771 : : uint32_t idx_vsi_child;
772 : : uint32_t idx_qg;
773 : : uint32_t nb_vsi_child;
774 : : uint32_t nb_qg;
775 : : uint32_t qid;
776 : : uint32_t q_teid;
777 : :
778 : : /* remove leaf nodes */
779 : 0 : ret_val = ice_remove_leaf_nodes(dev);
780 [ # # ]: 0 : if (ret_val) {
781 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
782 : 0 : PMD_DRV_LOG(ERR, "reset no-leaf nodes failed");
783 : 0 : goto fail_clear;
784 : : }
785 : :
786 : : /* reset no-leaf nodes. */
787 : 0 : ret_val = ice_reset_noleaf_nodes(dev);
788 [ # # ]: 0 : if (ret_val) {
789 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
790 : 0 : PMD_DRV_LOG(ERR, "reset leaf nodes failed");
791 : 0 : goto add_leaf;
792 : : }
793 : :
794 : : /* config vsi node */
795 : : vsi_node = ice_get_vsi_node(hw);
796 : 0 : root = pf->tm_conf.root;
797 : :
798 : 0 : ret_val = ice_set_node_rate(hw, root, vsi_node);
799 [ # # ]: 0 : if (ret_val) {
800 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
801 : 0 : PMD_DRV_LOG(ERR,
802 : : "configure vsi node %u bandwidth failed",
803 : : root->id);
804 : 0 : goto add_leaf;
805 : : }
806 : :
807 : : /* config queue group nodes */
808 : 0 : nb_vsi_child = vsi_node->num_children;
809 : 0 : nb_qg = vsi_node->children[0]->num_children;
810 : :
811 : : idx_vsi_child = 0;
812 : : idx_qg = 0;
813 : :
814 [ # # ]: 0 : if (root == NULL)
815 : 0 : goto commit;
816 : :
817 [ # # ]: 0 : for (i = 0; i < root->reference_count; i++) {
818 : 0 : struct ice_tm_node *tm_node = root->children[i];
819 : : struct ice_tm_node *tm_child_node;
820 : 0 : struct ice_sched_node *qgroup_sched_node =
821 : 0 : vsi_node->children[idx_vsi_child]->children[idx_qg];
822 : : uint32_t j;
823 : :
824 : 0 : ret_val = ice_cfg_hw_node(hw, tm_node, qgroup_sched_node);
825 [ # # ]: 0 : if (ret_val) {
826 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
827 : 0 : PMD_DRV_LOG(ERR,
828 : : "configure queue group node %u failed",
829 : : tm_node->id);
830 : 0 : goto reset_leaf;
831 : : }
832 : :
833 [ # # ]: 0 : for (j = 0; j < tm_node->reference_count; j++) {
834 : 0 : tm_child_node = tm_node->children[j];
835 : 0 : qid = tm_child_node->id;
836 : 0 : ret_val = ice_tx_queue_start(dev, qid);
837 [ # # ]: 0 : if (ret_val) {
838 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
839 : 0 : PMD_DRV_LOG(ERR, "start queue %u failed", qid);
840 : 0 : goto reset_leaf;
841 : : }
842 : 0 : txq = dev->data->tx_queues[qid];
843 : 0 : q_teid = txq->q_teid;
844 : 0 : queue_node = ice_sched_get_node(hw->port_info, q_teid);
845 [ # # ]: 0 : if (queue_node == NULL) {
846 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
847 : 0 : PMD_DRV_LOG(ERR, "get queue %u node failed", qid);
848 : 0 : goto reset_leaf;
849 : : }
850 [ # # ]: 0 : if (queue_node->info.parent_teid != qgroup_sched_node->info.node_teid) {
851 : 0 : ret_val = ice_move_recfg_lan_txq(dev, queue_node,
852 : : qgroup_sched_node, qid);
853 [ # # ]: 0 : if (ret_val) {
854 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
855 : 0 : PMD_DRV_LOG(ERR, "move queue %u failed", qid);
856 : 0 : goto reset_leaf;
857 : : }
858 : : }
859 : 0 : ret_val = ice_cfg_hw_node(hw, tm_child_node, queue_node);
860 [ # # ]: 0 : if (ret_val) {
861 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
862 : 0 : PMD_DRV_LOG(ERR,
863 : : "configure queue group node %u failed",
864 : : tm_node->id);
865 : 0 : goto reset_leaf;
866 : : }
867 : : }
868 : :
869 : 0 : idx_qg++;
870 [ # # ]: 0 : if (idx_qg >= nb_qg) {
871 : : idx_qg = 0;
872 : 0 : idx_vsi_child++;
873 : : }
874 [ # # ]: 0 : if (idx_vsi_child >= nb_vsi_child) {
875 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
876 : 0 : PMD_DRV_LOG(ERR, "too many queues");
877 : 0 : goto reset_leaf;
878 : : }
879 : : }
880 : :
881 : 0 : commit:
882 : 0 : pf->tm_conf.committed = true;
883 : 0 : pf->tm_conf.clear_on_fail = clear_on_fail;
884 : :
885 : 0 : return ret_val;
886 : :
887 : 0 : reset_leaf:
888 : 0 : ice_remove_leaf_nodes(dev);
889 : 0 : add_leaf:
890 : 0 : ice_add_leaf_nodes(dev);
891 : 0 : ice_reset_noleaf_nodes(dev);
892 : 0 : fail_clear:
893 : : /* clear all the traffic manager configuration */
894 [ # # ]: 0 : if (clear_on_fail) {
895 : 0 : ice_tm_conf_uninit(dev);
896 : 0 : ice_tm_conf_init(dev);
897 : : }
898 : : return ret_val;
899 : : }
900 : :
901 : 0 : static int ice_hierarchy_commit(struct rte_eth_dev *dev,
902 : : int clear_on_fail,
903 : : struct rte_tm_error *error)
904 : : {
905 : 0 : struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private);
906 : :
907 : : /* if device not started, simply set committed flag and return. */
908 [ # # ]: 0 : if (!dev->data->dev_started) {
909 : 0 : pf->tm_conf.committed = true;
910 : 0 : pf->tm_conf.clear_on_fail = clear_on_fail;
911 : 0 : return 0;
912 : : }
913 : :
914 : 0 : return ice_do_hierarchy_commit(dev, clear_on_fail, error);
915 : : }
|