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