xref: /f-stack/dpdk/drivers/net/i40e/i40e_tm.c (revision 031be553)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include <rte_malloc.h>
35 
36 #include "base/i40e_prototype.h"
37 #include "i40e_ethdev.h"
38 
39 static int i40e_tm_capabilities_get(struct rte_eth_dev *dev,
40 				    struct rte_tm_capabilities *cap,
41 				    struct rte_tm_error *error);
42 static int i40e_shaper_profile_add(struct rte_eth_dev *dev,
43 				   uint32_t shaper_profile_id,
44 				   struct rte_tm_shaper_params *profile,
45 				   struct rte_tm_error *error);
46 static int i40e_shaper_profile_del(struct rte_eth_dev *dev,
47 				   uint32_t shaper_profile_id,
48 				   struct rte_tm_error *error);
49 static int i40e_node_add(struct rte_eth_dev *dev, uint32_t node_id,
50 			 uint32_t parent_node_id, uint32_t priority,
51 			 uint32_t weight, uint32_t level_id,
52 			 struct rte_tm_node_params *params,
53 			 struct rte_tm_error *error);
54 static int i40e_node_delete(struct rte_eth_dev *dev, uint32_t node_id,
55 			    struct rte_tm_error *error);
56 static int i40e_node_type_get(struct rte_eth_dev *dev, uint32_t node_id,
57 			      int *is_leaf, struct rte_tm_error *error);
58 static int i40e_level_capabilities_get(struct rte_eth_dev *dev,
59 				       uint32_t level_id,
60 				       struct rte_tm_level_capabilities *cap,
61 				       struct rte_tm_error *error);
62 static int i40e_node_capabilities_get(struct rte_eth_dev *dev,
63 				      uint32_t node_id,
64 				      struct rte_tm_node_capabilities *cap,
65 				      struct rte_tm_error *error);
66 static int i40e_hierarchy_commit(struct rte_eth_dev *dev,
67 				 int clear_on_fail,
68 				 struct rte_tm_error *error);
69 
70 const struct rte_tm_ops i40e_tm_ops = {
71 	.capabilities_get = i40e_tm_capabilities_get,
72 	.shaper_profile_add = i40e_shaper_profile_add,
73 	.shaper_profile_delete = i40e_shaper_profile_del,
74 	.node_add = i40e_node_add,
75 	.node_delete = i40e_node_delete,
76 	.node_type_get = i40e_node_type_get,
77 	.level_capabilities_get = i40e_level_capabilities_get,
78 	.node_capabilities_get = i40e_node_capabilities_get,
79 	.hierarchy_commit = i40e_hierarchy_commit,
80 };
81 
82 int
83 i40e_tm_ops_get(struct rte_eth_dev *dev __rte_unused,
84 		void *arg)
85 {
86 	if (!arg)
87 		return -EINVAL;
88 
89 	*(const void **)arg = &i40e_tm_ops;
90 
91 	return 0;
92 }
93 
94 void
95 i40e_tm_conf_init(struct rte_eth_dev *dev)
96 {
97 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
98 
99 	/* initialize shaper profile list */
100 	TAILQ_INIT(&pf->tm_conf.shaper_profile_list);
101 
102 	/* initialize node configuration */
103 	pf->tm_conf.root = NULL;
104 	TAILQ_INIT(&pf->tm_conf.tc_list);
105 	TAILQ_INIT(&pf->tm_conf.queue_list);
106 	pf->tm_conf.nb_tc_node = 0;
107 	pf->tm_conf.nb_queue_node = 0;
108 	pf->tm_conf.committed = false;
109 }
110 
111 void
112 i40e_tm_conf_uninit(struct rte_eth_dev *dev)
113 {
114 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
115 	struct i40e_tm_shaper_profile *shaper_profile;
116 	struct i40e_tm_node *tm_node;
117 
118 	/* clear node configuration */
119 	while ((tm_node = TAILQ_FIRST(&pf->tm_conf.queue_list))) {
120 		TAILQ_REMOVE(&pf->tm_conf.queue_list, tm_node, node);
121 		rte_free(tm_node);
122 	}
123 	pf->tm_conf.nb_queue_node = 0;
124 	while ((tm_node = TAILQ_FIRST(&pf->tm_conf.tc_list))) {
125 		TAILQ_REMOVE(&pf->tm_conf.tc_list, tm_node, node);
126 		rte_free(tm_node);
127 	}
128 	pf->tm_conf.nb_tc_node = 0;
129 	if (pf->tm_conf.root) {
130 		rte_free(pf->tm_conf.root);
131 		pf->tm_conf.root = NULL;
132 	}
133 
134 	/* Remove all shaper profiles */
135 	while ((shaper_profile =
136 	       TAILQ_FIRST(&pf->tm_conf.shaper_profile_list))) {
137 		TAILQ_REMOVE(&pf->tm_conf.shaper_profile_list,
138 			     shaper_profile, node);
139 		rte_free(shaper_profile);
140 	}
141 }
142 
143 static inline uint16_t
144 i40e_tc_nb_get(struct rte_eth_dev *dev)
145 {
146 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
147 	struct i40e_vsi *main_vsi = pf->main_vsi;
148 	uint16_t sum = 0;
149 	int i;
150 
151 	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
152 		if (main_vsi->enabled_tc & BIT_ULL(i))
153 			sum++;
154 	}
155 
156 	return sum;
157 }
158 
159 static int
160 i40e_tm_capabilities_get(struct rte_eth_dev *dev,
161 			 struct rte_tm_capabilities *cap,
162 			 struct rte_tm_error *error)
163 {
164 	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
165 	uint16_t tc_nb = i40e_tc_nb_get(dev);
166 
167 	if (!cap || !error)
168 		return -EINVAL;
169 
170 	if (tc_nb > hw->func_caps.num_tx_qp)
171 		return -EINVAL;
172 
173 	error->type = RTE_TM_ERROR_TYPE_NONE;
174 
175 	/* set all the parameters to 0 first. */
176 	memset(cap, 0, sizeof(struct rte_tm_capabilities));
177 
178 	/**
179 	 * support port + TCs + queues
180 	 * here shows the max capability not the current configuration.
181 	 */
182 	cap->n_nodes_max = 1 + I40E_MAX_TRAFFIC_CLASS + hw->func_caps.num_tx_qp;
183 	cap->n_levels_max = 3; /* port, TC, queue */
184 	cap->non_leaf_nodes_identical = 1;
185 	cap->leaf_nodes_identical = 1;
186 	cap->shaper_n_max = cap->n_nodes_max;
187 	cap->shaper_private_n_max = cap->n_nodes_max;
188 	cap->shaper_private_dual_rate_n_max = 0;
189 	cap->shaper_private_rate_min = 0;
190 	/* 40Gbps -> 5GBps */
191 	cap->shaper_private_rate_max = 5000000000ull;
192 	cap->shaper_shared_n_max = 0;
193 	cap->shaper_shared_n_nodes_per_shaper_max = 0;
194 	cap->shaper_shared_n_shapers_per_node_max = 0;
195 	cap->shaper_shared_dual_rate_n_max = 0;
196 	cap->shaper_shared_rate_min = 0;
197 	cap->shaper_shared_rate_max = 0;
198 	cap->sched_n_children_max = hw->func_caps.num_tx_qp;
199 	/**
200 	 * HW supports SP. But no plan to support it now.
201 	 * So, all the nodes should have the same priority.
202 	 */
203 	cap->sched_sp_n_priorities_max = 1;
204 	cap->sched_wfq_n_children_per_group_max = 0;
205 	cap->sched_wfq_n_groups_max = 0;
206 	/**
207 	 * SW only supports fair round robin now.
208 	 * So, all the nodes should have the same weight.
209 	 */
210 	cap->sched_wfq_weight_max = 1;
211 	cap->cman_head_drop_supported = 0;
212 	cap->dynamic_update_mask = 0;
213 	cap->shaper_pkt_length_adjust_min = RTE_TM_ETH_FRAMING_OVERHEAD;
214 	cap->shaper_pkt_length_adjust_max = RTE_TM_ETH_FRAMING_OVERHEAD_FCS;
215 	cap->cman_wred_context_n_max = 0;
216 	cap->cman_wred_context_private_n_max = 0;
217 	cap->cman_wred_context_shared_n_max = 0;
218 	cap->cman_wred_context_shared_n_nodes_per_context_max = 0;
219 	cap->cman_wred_context_shared_n_contexts_per_node_max = 0;
220 	cap->stats_mask = 0;
221 
222 	return 0;
223 }
224 
225 static inline struct i40e_tm_shaper_profile *
226 i40e_shaper_profile_search(struct rte_eth_dev *dev,
227 			   uint32_t shaper_profile_id)
228 {
229 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
230 	struct i40e_shaper_profile_list *shaper_profile_list =
231 		&pf->tm_conf.shaper_profile_list;
232 	struct i40e_tm_shaper_profile *shaper_profile;
233 
234 	TAILQ_FOREACH(shaper_profile, shaper_profile_list, node) {
235 		if (shaper_profile_id == shaper_profile->shaper_profile_id)
236 			return shaper_profile;
237 	}
238 
239 	return NULL;
240 }
241 
242 static int
243 i40e_shaper_profile_param_check(struct rte_tm_shaper_params *profile,
244 				struct rte_tm_error *error)
245 {
246 	/* min rate not supported */
247 	if (profile->committed.rate) {
248 		error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_RATE;
249 		error->message = "committed rate not supported";
250 		return -EINVAL;
251 	}
252 	/* min bucket size not supported */
253 	if (profile->committed.size) {
254 		error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_SIZE;
255 		error->message = "committed bucket size not supported";
256 		return -EINVAL;
257 	}
258 	/* max bucket size not supported */
259 	if (profile->peak.size) {
260 		error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE;
261 		error->message = "peak bucket size not supported";
262 		return -EINVAL;
263 	}
264 	/* length adjustment not supported */
265 	if (profile->pkt_length_adjust) {
266 		error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PKT_ADJUST_LEN;
267 		error->message = "packet length adjustment not supported";
268 		return -EINVAL;
269 	}
270 
271 	return 0;
272 }
273 
274 static int
275 i40e_shaper_profile_add(struct rte_eth_dev *dev,
276 			uint32_t shaper_profile_id,
277 			struct rte_tm_shaper_params *profile,
278 			struct rte_tm_error *error)
279 {
280 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
281 	struct i40e_tm_shaper_profile *shaper_profile;
282 	int ret;
283 
284 	if (!profile || !error)
285 		return -EINVAL;
286 
287 	ret = i40e_shaper_profile_param_check(profile, error);
288 	if (ret)
289 		return ret;
290 
291 	shaper_profile = i40e_shaper_profile_search(dev, shaper_profile_id);
292 
293 	if (shaper_profile) {
294 		error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID;
295 		error->message = "profile ID exist";
296 		return -EINVAL;
297 	}
298 
299 	shaper_profile = rte_zmalloc("i40e_tm_shaper_profile",
300 				     sizeof(struct i40e_tm_shaper_profile),
301 				     0);
302 	if (!shaper_profile)
303 		return -ENOMEM;
304 	shaper_profile->shaper_profile_id = shaper_profile_id;
305 	rte_memcpy(&shaper_profile->profile, profile,
306 			 sizeof(struct rte_tm_shaper_params));
307 	TAILQ_INSERT_TAIL(&pf->tm_conf.shaper_profile_list,
308 			  shaper_profile, node);
309 
310 	return 0;
311 }
312 
313 static int
314 i40e_shaper_profile_del(struct rte_eth_dev *dev,
315 			uint32_t shaper_profile_id,
316 			struct rte_tm_error *error)
317 {
318 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
319 	struct i40e_tm_shaper_profile *shaper_profile;
320 
321 	if (!error)
322 		return -EINVAL;
323 
324 	shaper_profile = i40e_shaper_profile_search(dev, shaper_profile_id);
325 
326 	if (!shaper_profile) {
327 		error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID;
328 		error->message = "profile ID not exist";
329 		return -EINVAL;
330 	}
331 
332 	/* don't delete a profile if it's used by one or several nodes */
333 	if (shaper_profile->reference_count) {
334 		error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE;
335 		error->message = "profile in use";
336 		return -EINVAL;
337 	}
338 
339 	TAILQ_REMOVE(&pf->tm_conf.shaper_profile_list, shaper_profile, node);
340 	rte_free(shaper_profile);
341 
342 	return 0;
343 }
344 
345 static inline struct i40e_tm_node *
346 i40e_tm_node_search(struct rte_eth_dev *dev,
347 		    uint32_t node_id, enum i40e_tm_node_type *node_type)
348 {
349 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
350 	struct i40e_tm_node_list *queue_list = &pf->tm_conf.queue_list;
351 	struct i40e_tm_node_list *tc_list = &pf->tm_conf.tc_list;
352 	struct i40e_tm_node *tm_node;
353 
354 	if (pf->tm_conf.root && pf->tm_conf.root->id == node_id) {
355 		*node_type = I40E_TM_NODE_TYPE_PORT;
356 		return pf->tm_conf.root;
357 	}
358 
359 	TAILQ_FOREACH(tm_node, tc_list, node) {
360 		if (tm_node->id == node_id) {
361 			*node_type = I40E_TM_NODE_TYPE_TC;
362 			return tm_node;
363 		}
364 	}
365 
366 	TAILQ_FOREACH(tm_node, queue_list, node) {
367 		if (tm_node->id == node_id) {
368 			*node_type = I40E_TM_NODE_TYPE_QUEUE;
369 			return tm_node;
370 		}
371 	}
372 
373 	return NULL;
374 }
375 
376 static int
377 i40e_node_param_check(struct rte_eth_dev *dev, uint32_t node_id,
378 		      uint32_t priority, uint32_t weight,
379 		      struct rte_tm_node_params *params,
380 		      struct rte_tm_error *error)
381 {
382 	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
383 
384 	if (node_id == RTE_TM_NODE_ID_NULL) {
385 		error->type = RTE_TM_ERROR_TYPE_NODE_ID;
386 		error->message = "invalid node id";
387 		return -EINVAL;
388 	}
389 
390 	if (priority) {
391 		error->type = RTE_TM_ERROR_TYPE_NODE_PRIORITY;
392 		error->message = "priority should be 0";
393 		return -EINVAL;
394 	}
395 
396 	if (weight != 1) {
397 		error->type = RTE_TM_ERROR_TYPE_NODE_WEIGHT;
398 		error->message = "weight must be 1";
399 		return -EINVAL;
400 	}
401 
402 	/* not support shared shaper */
403 	if (params->shared_shaper_id) {
404 		error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_SHAPER_ID;
405 		error->message = "shared shaper not supported";
406 		return -EINVAL;
407 	}
408 	if (params->n_shared_shapers) {
409 		error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS;
410 		error->message = "shared shaper not supported";
411 		return -EINVAL;
412 	}
413 
414 	/* for non-leaf node */
415 	if (node_id >= hw->func_caps.num_tx_qp) {
416 		if (params->nonleaf.wfq_weight_mode) {
417 			error->type =
418 				RTE_TM_ERROR_TYPE_NODE_PARAMS_WFQ_WEIGHT_MODE;
419 			error->message = "WFQ not supported";
420 			return -EINVAL;
421 		}
422 		if (params->nonleaf.n_sp_priorities != 1) {
423 			error->type =
424 				RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SP_PRIORITIES;
425 			error->message = "SP priority not supported";
426 			return -EINVAL;
427 		} else if (params->nonleaf.wfq_weight_mode &&
428 			   !(*params->nonleaf.wfq_weight_mode)) {
429 			error->type =
430 				RTE_TM_ERROR_TYPE_NODE_PARAMS_WFQ_WEIGHT_MODE;
431 			error->message = "WFP should be byte mode";
432 			return -EINVAL;
433 		}
434 
435 		return 0;
436 	}
437 
438 	/* for leaf node */
439 	if (params->leaf.cman) {
440 		error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_CMAN;
441 		error->message = "Congestion management not supported";
442 		return -EINVAL;
443 	}
444 	if (params->leaf.wred.wred_profile_id !=
445 	    RTE_TM_WRED_PROFILE_ID_NONE) {
446 		error->type =
447 			RTE_TM_ERROR_TYPE_NODE_PARAMS_WRED_PROFILE_ID;
448 		error->message = "WRED not supported";
449 		return -EINVAL;
450 	}
451 	if (params->leaf.wred.shared_wred_context_id) {
452 		error->type =
453 			RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_WRED_CONTEXT_ID;
454 		error->message = "WRED not supported";
455 		return -EINVAL;
456 	}
457 	if (params->leaf.wred.n_shared_wred_contexts) {
458 		error->type =
459 			RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_WRED_CONTEXTS;
460 		error->message = "WRED not supported";
461 		return -EINVAL;
462 	}
463 
464 	return 0;
465 }
466 
467 /**
468  * Now the TC and queue configuration is controlled by DCB.
469  * We need check if the node configuration follows the DCB configuration.
470  * In the future, we may use TM to cover DCB.
471  */
472 static int
473 i40e_node_add(struct rte_eth_dev *dev, uint32_t node_id,
474 	      uint32_t parent_node_id, uint32_t priority,
475 	      uint32_t weight, uint32_t level_id,
476 	      struct rte_tm_node_params *params,
477 	      struct rte_tm_error *error)
478 {
479 	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
480 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
481 	enum i40e_tm_node_type node_type = I40E_TM_NODE_TYPE_MAX;
482 	enum i40e_tm_node_type parent_node_type = I40E_TM_NODE_TYPE_MAX;
483 	struct i40e_tm_shaper_profile *shaper_profile = NULL;
484 	struct i40e_tm_node *tm_node;
485 	struct i40e_tm_node *parent_node;
486 	uint16_t tc_nb = 0;
487 	int ret;
488 
489 	if (!params || !error)
490 		return -EINVAL;
491 
492 	/* if already committed */
493 	if (pf->tm_conf.committed) {
494 		error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
495 		error->message = "already committed";
496 		return -EINVAL;
497 	}
498 
499 	ret = i40e_node_param_check(dev, node_id, priority, weight,
500 				    params, error);
501 	if (ret)
502 		return ret;
503 
504 	/* check if the node ID is already used */
505 	if (i40e_tm_node_search(dev, node_id, &node_type)) {
506 		error->type = RTE_TM_ERROR_TYPE_NODE_ID;
507 		error->message = "node id already used";
508 		return -EINVAL;
509 	}
510 
511 	/* check the shaper profile id */
512 	if (params->shaper_profile_id != RTE_TM_SHAPER_PROFILE_ID_NONE) {
513 		shaper_profile = i40e_shaper_profile_search(
514 					dev, params->shaper_profile_id);
515 		if (!shaper_profile) {
516 			error->type =
517 				RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID;
518 			error->message = "shaper profile not exist";
519 			return -EINVAL;
520 		}
521 	}
522 
523 	/* root node if not have a parent */
524 	if (parent_node_id == RTE_TM_NODE_ID_NULL) {
525 		/* check level */
526 		if (level_id != RTE_TM_NODE_LEVEL_ID_ANY &&
527 		    level_id > I40E_TM_NODE_TYPE_PORT) {
528 			error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;
529 			error->message = "Wrong level";
530 			return -EINVAL;
531 		}
532 
533 		/* obviously no more than one root */
534 		if (pf->tm_conf.root) {
535 			error->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;
536 			error->message = "already have a root";
537 			return -EINVAL;
538 		}
539 
540 		/* add the root node */
541 		tm_node = rte_zmalloc("i40e_tm_node",
542 				      sizeof(struct i40e_tm_node),
543 				      0);
544 		if (!tm_node)
545 			return -ENOMEM;
546 		tm_node->id = node_id;
547 		tm_node->priority = priority;
548 		tm_node->weight = weight;
549 		tm_node->reference_count = 0;
550 		tm_node->parent = NULL;
551 		tm_node->shaper_profile = shaper_profile;
552 		rte_memcpy(&tm_node->params, params,
553 				 sizeof(struct rte_tm_node_params));
554 		pf->tm_conf.root = tm_node;
555 
556 		/* increase the reference counter of the shaper profile */
557 		if (shaper_profile)
558 			shaper_profile->reference_count++;
559 
560 		return 0;
561 	}
562 
563 	/* TC or queue node */
564 	/* check the parent node */
565 	parent_node = i40e_tm_node_search(dev, parent_node_id,
566 					  &parent_node_type);
567 	if (!parent_node) {
568 		error->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;
569 		error->message = "parent not exist";
570 		return -EINVAL;
571 	}
572 	if (parent_node_type != I40E_TM_NODE_TYPE_PORT &&
573 	    parent_node_type != I40E_TM_NODE_TYPE_TC) {
574 		error->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;
575 		error->message = "parent is not port or TC";
576 		return -EINVAL;
577 	}
578 	/* check level */
579 	if (level_id != RTE_TM_NODE_LEVEL_ID_ANY &&
580 	    level_id != parent_node_type + 1) {
581 		error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;
582 		error->message = "Wrong level";
583 		return -EINVAL;
584 	}
585 
586 	/* check the node number */
587 	if (parent_node_type == I40E_TM_NODE_TYPE_PORT) {
588 		/* check the TC number */
589 		tc_nb = i40e_tc_nb_get(dev);
590 		if (pf->tm_conf.nb_tc_node >= tc_nb) {
591 			error->type = RTE_TM_ERROR_TYPE_NODE_ID;
592 			error->message = "too many TCs";
593 			return -EINVAL;
594 		}
595 	} else {
596 		/* check the queue number */
597 		if (pf->tm_conf.nb_queue_node >= hw->func_caps.num_tx_qp) {
598 			error->type = RTE_TM_ERROR_TYPE_NODE_ID;
599 			error->message = "too many queues";
600 			return -EINVAL;
601 		}
602 
603 		/**
604 		 * check the node id.
605 		 * For queue, the node id means queue id.
606 		 */
607 		if (node_id >= hw->func_caps.num_tx_qp) {
608 			error->type = RTE_TM_ERROR_TYPE_NODE_ID;
609 			error->message = "too large queue id";
610 			return -EINVAL;
611 		}
612 	}
613 
614 	/* add the TC or queue node */
615 	tm_node = rte_zmalloc("i40e_tm_node",
616 			      sizeof(struct i40e_tm_node),
617 			      0);
618 	if (!tm_node)
619 		return -ENOMEM;
620 	tm_node->id = node_id;
621 	tm_node->priority = priority;
622 	tm_node->weight = weight;
623 	tm_node->reference_count = 0;
624 	tm_node->parent = parent_node;
625 	tm_node->shaper_profile = shaper_profile;
626 	rte_memcpy(&tm_node->params, params,
627 			 sizeof(struct rte_tm_node_params));
628 	if (parent_node_type == I40E_TM_NODE_TYPE_PORT) {
629 		TAILQ_INSERT_TAIL(&pf->tm_conf.tc_list,
630 				  tm_node, node);
631 		pf->tm_conf.nb_tc_node++;
632 	} else {
633 		TAILQ_INSERT_TAIL(&pf->tm_conf.queue_list,
634 				  tm_node, node);
635 		pf->tm_conf.nb_queue_node++;
636 	}
637 	tm_node->parent->reference_count++;
638 
639 	/* increase the reference counter of the shaper profile */
640 	if (shaper_profile)
641 		shaper_profile->reference_count++;
642 
643 	return 0;
644 }
645 
646 static int
647 i40e_node_delete(struct rte_eth_dev *dev, uint32_t node_id,
648 		 struct rte_tm_error *error)
649 {
650 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
651 	enum i40e_tm_node_type node_type = I40E_TM_NODE_TYPE_MAX;
652 	struct i40e_tm_node *tm_node;
653 
654 	if (!error)
655 		return -EINVAL;
656 
657 	/* if already committed */
658 	if (pf->tm_conf.committed) {
659 		error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
660 		error->message = "already committed";
661 		return -EINVAL;
662 	}
663 
664 	if (node_id == RTE_TM_NODE_ID_NULL) {
665 		error->type = RTE_TM_ERROR_TYPE_NODE_ID;
666 		error->message = "invalid node id";
667 		return -EINVAL;
668 	}
669 
670 	/* check if the node id exists */
671 	tm_node = i40e_tm_node_search(dev, node_id, &node_type);
672 	if (!tm_node) {
673 		error->type = RTE_TM_ERROR_TYPE_NODE_ID;
674 		error->message = "no such node";
675 		return -EINVAL;
676 	}
677 
678 	/* the node should have no child */
679 	if (tm_node->reference_count) {
680 		error->type = RTE_TM_ERROR_TYPE_NODE_ID;
681 		error->message =
682 			"cannot delete a node which has children";
683 		return -EINVAL;
684 	}
685 
686 	/* root node */
687 	if (node_type == I40E_TM_NODE_TYPE_PORT) {
688 		if (tm_node->shaper_profile)
689 			tm_node->shaper_profile->reference_count--;
690 		rte_free(tm_node);
691 		pf->tm_conf.root = NULL;
692 		return 0;
693 	}
694 
695 	/* TC or queue node */
696 	if (tm_node->shaper_profile)
697 		tm_node->shaper_profile->reference_count--;
698 	tm_node->parent->reference_count--;
699 	if (node_type == I40E_TM_NODE_TYPE_TC) {
700 		TAILQ_REMOVE(&pf->tm_conf.tc_list, tm_node, node);
701 		pf->tm_conf.nb_tc_node--;
702 	} else {
703 		TAILQ_REMOVE(&pf->tm_conf.queue_list, tm_node, node);
704 		pf->tm_conf.nb_queue_node--;
705 	}
706 	rte_free(tm_node);
707 
708 	return 0;
709 }
710 
711 static int
712 i40e_node_type_get(struct rte_eth_dev *dev, uint32_t node_id,
713 		   int *is_leaf, struct rte_tm_error *error)
714 {
715 	enum i40e_tm_node_type node_type = I40E_TM_NODE_TYPE_MAX;
716 	struct i40e_tm_node *tm_node;
717 
718 	if (!is_leaf || !error)
719 		return -EINVAL;
720 
721 	if (node_id == RTE_TM_NODE_ID_NULL) {
722 		error->type = RTE_TM_ERROR_TYPE_NODE_ID;
723 		error->message = "invalid node id";
724 		return -EINVAL;
725 	}
726 
727 	/* check if the node id exists */
728 	tm_node = i40e_tm_node_search(dev, node_id, &node_type);
729 	if (!tm_node) {
730 		error->type = RTE_TM_ERROR_TYPE_NODE_ID;
731 		error->message = "no such node";
732 		return -EINVAL;
733 	}
734 
735 	if (node_type == I40E_TM_NODE_TYPE_QUEUE)
736 		*is_leaf = true;
737 	else
738 		*is_leaf = false;
739 
740 	return 0;
741 }
742 
743 static int
744 i40e_level_capabilities_get(struct rte_eth_dev *dev,
745 			    uint32_t level_id,
746 			    struct rte_tm_level_capabilities *cap,
747 			    struct rte_tm_error *error)
748 {
749 	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
750 
751 	if (!cap || !error)
752 		return -EINVAL;
753 
754 	if (level_id >= I40E_TM_NODE_TYPE_MAX) {
755 		error->type = RTE_TM_ERROR_TYPE_LEVEL_ID;
756 		error->message = "too deep level";
757 		return -EINVAL;
758 	}
759 
760 	/* root node */
761 	if (level_id == I40E_TM_NODE_TYPE_PORT) {
762 		cap->n_nodes_max = 1;
763 		cap->n_nodes_nonleaf_max = 1;
764 		cap->n_nodes_leaf_max = 0;
765 	} else if (level_id == I40E_TM_NODE_TYPE_TC) {
766 		/* TC */
767 		cap->n_nodes_max = I40E_MAX_TRAFFIC_CLASS;
768 		cap->n_nodes_nonleaf_max = I40E_MAX_TRAFFIC_CLASS;
769 		cap->n_nodes_leaf_max = 0;
770 	} else {
771 		/* queue */
772 		cap->n_nodes_max = hw->func_caps.num_tx_qp;
773 		cap->n_nodes_nonleaf_max = 0;
774 		cap->n_nodes_leaf_max = hw->func_caps.num_tx_qp;
775 	}
776 
777 	cap->non_leaf_nodes_identical = true;
778 	cap->leaf_nodes_identical = true;
779 
780 	if (level_id != I40E_TM_NODE_TYPE_QUEUE) {
781 		cap->nonleaf.shaper_private_supported = true;
782 		cap->nonleaf.shaper_private_dual_rate_supported = false;
783 		cap->nonleaf.shaper_private_rate_min = 0;
784 		/* 40Gbps -> 5GBps */
785 		cap->nonleaf.shaper_private_rate_max = 5000000000ull;
786 		cap->nonleaf.shaper_shared_n_max = 0;
787 		if (level_id == I40E_TM_NODE_TYPE_PORT)
788 			cap->nonleaf.sched_n_children_max =
789 				I40E_MAX_TRAFFIC_CLASS;
790 		else
791 			cap->nonleaf.sched_n_children_max =
792 				hw->func_caps.num_tx_qp;
793 		cap->nonleaf.sched_sp_n_priorities_max = 1;
794 		cap->nonleaf.sched_wfq_n_children_per_group_max = 0;
795 		cap->nonleaf.sched_wfq_n_groups_max = 0;
796 		cap->nonleaf.sched_wfq_weight_max = 1;
797 		cap->nonleaf.stats_mask = 0;
798 
799 		return 0;
800 	}
801 
802 	/* queue node */
803 	cap->leaf.shaper_private_supported = true;
804 	cap->leaf.shaper_private_dual_rate_supported = false;
805 	cap->leaf.shaper_private_rate_min = 0;
806 	/* 40Gbps -> 5GBps */
807 	cap->leaf.shaper_private_rate_max = 5000000000ull;
808 	cap->leaf.shaper_shared_n_max = 0;
809 	cap->leaf.cman_head_drop_supported = false;
810 	cap->leaf.cman_wred_context_private_supported = true;
811 	cap->leaf.cman_wred_context_shared_n_max = 0;
812 	cap->leaf.stats_mask = 0;
813 
814 	return 0;
815 }
816 
817 static int
818 i40e_node_capabilities_get(struct rte_eth_dev *dev,
819 			   uint32_t node_id,
820 			   struct rte_tm_node_capabilities *cap,
821 			   struct rte_tm_error *error)
822 {
823 	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
824 	enum i40e_tm_node_type node_type;
825 	struct i40e_tm_node *tm_node;
826 
827 	if (!cap || !error)
828 		return -EINVAL;
829 
830 	if (node_id == RTE_TM_NODE_ID_NULL) {
831 		error->type = RTE_TM_ERROR_TYPE_NODE_ID;
832 		error->message = "invalid node id";
833 		return -EINVAL;
834 	}
835 
836 	/* check if the node id exists */
837 	tm_node = i40e_tm_node_search(dev, node_id, &node_type);
838 	if (!tm_node) {
839 		error->type = RTE_TM_ERROR_TYPE_NODE_ID;
840 		error->message = "no such node";
841 		return -EINVAL;
842 	}
843 
844 	cap->shaper_private_supported = true;
845 	cap->shaper_private_dual_rate_supported = false;
846 	cap->shaper_private_rate_min = 0;
847 	/* 40Gbps -> 5GBps */
848 	cap->shaper_private_rate_max = 5000000000ull;
849 	cap->shaper_shared_n_max = 0;
850 
851 	if (node_type == I40E_TM_NODE_TYPE_QUEUE) {
852 		cap->leaf.cman_head_drop_supported = false;
853 		cap->leaf.cman_wred_context_private_supported = true;
854 		cap->leaf.cman_wred_context_shared_n_max = 0;
855 	} else {
856 		if (node_type == I40E_TM_NODE_TYPE_PORT)
857 			cap->nonleaf.sched_n_children_max =
858 				I40E_MAX_TRAFFIC_CLASS;
859 		else
860 			cap->nonleaf.sched_n_children_max =
861 				hw->func_caps.num_tx_qp;
862 		cap->nonleaf.sched_sp_n_priorities_max = 1;
863 		cap->nonleaf.sched_wfq_n_children_per_group_max = 0;
864 		cap->nonleaf.sched_wfq_n_groups_max = 0;
865 		cap->nonleaf.sched_wfq_weight_max = 1;
866 	}
867 
868 	cap->stats_mask = 0;
869 
870 	return 0;
871 }
872 
873 static int
874 i40e_hierarchy_commit(struct rte_eth_dev *dev,
875 		      int clear_on_fail,
876 		      struct rte_tm_error *error)
877 {
878 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
879 	struct i40e_tm_node_list *tc_list = &pf->tm_conf.tc_list;
880 	struct i40e_tm_node_list *queue_list = &pf->tm_conf.queue_list;
881 	struct i40e_tm_node *tm_node;
882 	struct i40e_vsi *vsi;
883 	struct i40e_hw *hw;
884 	struct i40e_aqc_configure_vsi_ets_sla_bw_data tc_bw;
885 	uint64_t bw;
886 	uint8_t tc_map;
887 	int ret;
888 	int i;
889 
890 	if (!error)
891 		return -EINVAL;
892 
893 	/* check the setting */
894 	if (!pf->tm_conf.root)
895 		goto done;
896 
897 	vsi = pf->main_vsi;
898 	hw = I40E_VSI_TO_HW(vsi);
899 
900 	/**
901 	 * Don't support bandwidth control for port and TCs in parallel.
902 	 * If the port has a max bandwidth, the TCs should have none.
903 	 */
904 	/* port */
905 	if (pf->tm_conf.root->shaper_profile)
906 		bw = pf->tm_conf.root->shaper_profile->profile.peak.rate;
907 	else
908 		bw = 0;
909 	if (bw) {
910 		/* check if any TC has a max bandwidth */
911 		TAILQ_FOREACH(tm_node, tc_list, node) {
912 			if (tm_node->shaper_profile &&
913 			    tm_node->shaper_profile->profile.peak.rate) {
914 				error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE;
915 				error->message = "no port and TC max bandwidth"
916 						 " in parallel";
917 				goto fail_clear;
918 			}
919 		}
920 
921 		/* interpret Bps to 50Mbps */
922 		bw = bw * 8 / 1000 / 1000 / I40E_QOS_BW_GRANULARITY;
923 
924 		/* set the max bandwidth */
925 		ret = i40e_aq_config_vsi_bw_limit(hw, vsi->seid,
926 						  (uint16_t)bw, 0, NULL);
927 		if (ret) {
928 			error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE;
929 			error->message = "fail to set port max bandwidth";
930 			goto fail_clear;
931 		}
932 
933 		goto done;
934 	}
935 
936 	/* TC */
937 	memset(&tc_bw, 0, sizeof(tc_bw));
938 	tc_bw.tc_valid_bits = vsi->enabled_tc;
939 	tc_map = vsi->enabled_tc;
940 	TAILQ_FOREACH(tm_node, tc_list, node) {
941 		if (!tm_node->reference_count) {
942 			error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;
943 			error->message = "TC without queue assigned";
944 			goto fail_clear;
945 		}
946 
947 		i = 0;
948 		while (i < I40E_MAX_TRAFFIC_CLASS && !(tc_map & BIT_ULL(i)))
949 			i++;
950 		if (i >= I40E_MAX_TRAFFIC_CLASS) {
951 			error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;
952 			error->message = "cannot find the TC";
953 			goto fail_clear;
954 		}
955 		tc_map &= ~BIT_ULL(i);
956 
957 		if (tm_node->shaper_profile)
958 			bw = tm_node->shaper_profile->profile.peak.rate;
959 		else
960 			bw = 0;
961 		if (!bw)
962 			continue;
963 
964 		/* interpret Bps to 50Mbps */
965 		bw = bw * 8 / 1000 / 1000 / I40E_QOS_BW_GRANULARITY;
966 
967 		tc_bw.tc_bw_credits[i] = rte_cpu_to_le_16((uint16_t)bw);
968 	}
969 
970 	TAILQ_FOREACH(tm_node, queue_list, node) {
971 		if (tm_node->shaper_profile)
972 			bw = tm_node->shaper_profile->profile.peak.rate;
973 		else
974 			bw = 0;
975 		if (bw) {
976 			error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;
977 			error->message = "not support queue QoS";
978 			goto fail_clear;
979 		}
980 	}
981 
982 	ret = i40e_aq_config_vsi_ets_sla_bw_limit(hw, vsi->seid, &tc_bw, NULL);
983 	if (ret) {
984 		error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE;
985 		error->message = "fail to set TC max bandwidth";
986 		goto fail_clear;
987 	}
988 
989 done:
990 	pf->tm_conf.committed = true;
991 	return 0;
992 
993 fail_clear:
994 	/* clear all the traffic manager configuration */
995 	if (clear_on_fail) {
996 		i40e_tm_conf_uninit(dev);
997 		i40e_tm_conf_init(dev);
998 	}
999 	return -EINVAL;
1000 }
1001