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