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