1e16654d9054c26bdbde2327be353084e2dd3792
[dpdk.git] / drivers / net / ice / ice_dcf_sched.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2017 Intel Corporation
3  */
4 #include <rte_tm_driver.h>
5
6 #include "base/ice_sched.h"
7 #include "ice_dcf_ethdev.h"
8
9 static int ice_dcf_hierarchy_commit(struct rte_eth_dev *dev,
10                                  __rte_unused int clear_on_fail,
11                                  __rte_unused struct rte_tm_error *error);
12 static int ice_dcf_node_add(struct rte_eth_dev *dev, uint32_t node_id,
13               uint32_t parent_node_id, uint32_t priority,
14               uint32_t weight, uint32_t level_id,
15               struct rte_tm_node_params *params,
16               struct rte_tm_error *error);
17 static int ice_dcf_node_delete(struct rte_eth_dev *dev, uint32_t node_id,
18                             struct rte_tm_error *error);
19 static int ice_dcf_shaper_profile_add(struct rte_eth_dev *dev,
20                         uint32_t shaper_profile_id,
21                         struct rte_tm_shaper_params *profile,
22                         struct rte_tm_error *error);
23 static int ice_dcf_shaper_profile_del(struct rte_eth_dev *dev,
24                                    uint32_t shaper_profile_id,
25                                    struct rte_tm_error *error);
26
27 const struct rte_tm_ops ice_dcf_tm_ops = {
28         .shaper_profile_add = ice_dcf_shaper_profile_add,
29         .shaper_profile_delete = ice_dcf_shaper_profile_del,
30         .hierarchy_commit = ice_dcf_hierarchy_commit,
31         .node_add = ice_dcf_node_add,
32         .node_delete = ice_dcf_node_delete,
33 };
34
35 void
36 ice_dcf_tm_conf_init(struct rte_eth_dev *dev)
37 {
38         struct ice_dcf_adapter *adapter = dev->data->dev_private;
39         struct ice_dcf_hw *hw = &adapter->real_hw;
40
41         /* initialize shaper profile list */
42         TAILQ_INIT(&hw->tm_conf.shaper_profile_list);
43
44         /* initialize node configuration */
45         hw->tm_conf.root = NULL;
46         TAILQ_INIT(&hw->tm_conf.tc_list);
47         TAILQ_INIT(&hw->tm_conf.vsi_list);
48         hw->tm_conf.nb_tc_node = 0;
49         hw->tm_conf.nb_vsi_node = 0;
50         hw->tm_conf.committed = false;
51 }
52
53 void
54 ice_dcf_tm_conf_uninit(struct rte_eth_dev *dev)
55 {
56         struct ice_dcf_adapter *adapter = dev->data->dev_private;
57         struct ice_dcf_hw *hw = &adapter->real_hw;
58         struct ice_dcf_tm_shaper_profile *shaper_profile;
59         struct ice_dcf_tm_node *tm_node;
60
61         /* clear node configuration */
62         while ((tm_node = TAILQ_FIRST(&hw->tm_conf.vsi_list))) {
63                 TAILQ_REMOVE(&hw->tm_conf.vsi_list, tm_node, node);
64                 rte_free(tm_node);
65         }
66         hw->tm_conf.nb_vsi_node = 0;
67         while ((tm_node = TAILQ_FIRST(&hw->tm_conf.tc_list))) {
68                 TAILQ_REMOVE(&hw->tm_conf.tc_list, tm_node, node);
69                 rte_free(tm_node);
70         }
71         hw->tm_conf.nb_tc_node = 0;
72         if (hw->tm_conf.root) {
73                 rte_free(hw->tm_conf.root);
74                 hw->tm_conf.root = NULL;
75         }
76
77         /* Remove all shaper profiles */
78         while ((shaper_profile =
79                TAILQ_FIRST(&hw->tm_conf.shaper_profile_list))) {
80                 TAILQ_REMOVE(&hw->tm_conf.shaper_profile_list,
81                              shaper_profile, node);
82                 rte_free(shaper_profile);
83         }
84 }
85
86 static inline struct ice_dcf_tm_node *
87 ice_dcf_tm_node_search(struct rte_eth_dev *dev,
88                     uint32_t node_id, enum ice_dcf_tm_node_type *node_type)
89 {
90         struct ice_dcf_adapter *adapter = dev->data->dev_private;
91         struct ice_dcf_hw *hw = &adapter->real_hw;
92         struct ice_dcf_tm_node_list *vsi_list = &hw->tm_conf.vsi_list;
93         struct ice_dcf_tm_node_list *tc_list = &hw->tm_conf.tc_list;
94         struct ice_dcf_tm_node *tm_node;
95
96         if (hw->tm_conf.root && hw->tm_conf.root->id == node_id) {
97                 *node_type = ICE_DCF_TM_NODE_TYPE_PORT;
98                 return hw->tm_conf.root;
99         }
100
101         TAILQ_FOREACH(tm_node, tc_list, node) {
102                 if (tm_node->id == node_id) {
103                         *node_type = ICE_DCF_TM_NODE_TYPE_TC;
104                         return tm_node;
105                 }
106         }
107
108         TAILQ_FOREACH(tm_node, vsi_list, node) {
109                 if (tm_node->id == node_id) {
110                         *node_type = ICE_DCF_TM_NODE_TYPE_VSI;
111                         return tm_node;
112                 }
113         }
114
115         return NULL;
116 }
117
118 static inline struct ice_dcf_tm_shaper_profile *
119 ice_dcf_shaper_profile_search(struct rte_eth_dev *dev,
120                            uint32_t shaper_profile_id)
121 {
122         struct ice_dcf_adapter *adapter = dev->data->dev_private;
123         struct ice_dcf_hw *hw = &adapter->real_hw;
124         struct ice_dcf_shaper_profile_list *shaper_profile_list =
125                 &hw->tm_conf.shaper_profile_list;
126         struct ice_dcf_tm_shaper_profile *shaper_profile;
127
128         TAILQ_FOREACH(shaper_profile, shaper_profile_list, node) {
129                 if (shaper_profile_id == shaper_profile->shaper_profile_id)
130                         return shaper_profile;
131         }
132
133         return NULL;
134 }
135
136 static int
137 ice_dcf_node_param_check(struct ice_dcf_hw *hw, uint32_t node_id,
138                       uint32_t priority, uint32_t weight,
139                       struct rte_tm_node_params *params,
140                       struct rte_tm_error *error)
141 {
142         /* checked all the unsupported parameter */
143         if (node_id == RTE_TM_NODE_ID_NULL) {
144                 error->type = RTE_TM_ERROR_TYPE_NODE_ID;
145                 error->message = "invalid node id";
146                 return -EINVAL;
147         }
148
149         if (priority) {
150                 error->type = RTE_TM_ERROR_TYPE_NODE_PRIORITY;
151                 error->message = "priority should be 0";
152                 return -EINVAL;
153         }
154
155         if (weight != 1) {
156                 error->type = RTE_TM_ERROR_TYPE_NODE_WEIGHT;
157                 error->message = "weight must be 1";
158                 return -EINVAL;
159         }
160
161         /* not support shared shaper */
162         if (params->shared_shaper_id) {
163                 error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_SHAPER_ID;
164                 error->message = "shared shaper not supported";
165                 return -EINVAL;
166         }
167         if (params->n_shared_shapers) {
168                 error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS;
169                 error->message = "shared shaper not supported";
170                 return -EINVAL;
171         }
172
173         /* for non-leaf node */
174         if (node_id >= 8 * hw->num_vfs) {
175                 if (params->nonleaf.wfq_weight_mode) {
176                         error->type =
177                                 RTE_TM_ERROR_TYPE_NODE_PARAMS_WFQ_WEIGHT_MODE;
178                         error->message = "WFQ not supported";
179                         return -EINVAL;
180                 }
181                 if (params->nonleaf.n_sp_priorities != 1) {
182                         error->type =
183                                 RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SP_PRIORITIES;
184                         error->message = "SP priority not supported";
185                         return -EINVAL;
186                 } else if (params->nonleaf.wfq_weight_mode &&
187                            !(*params->nonleaf.wfq_weight_mode)) {
188                         error->type =
189                                 RTE_TM_ERROR_TYPE_NODE_PARAMS_WFQ_WEIGHT_MODE;
190                         error->message = "WFP should be byte mode";
191                         return -EINVAL;
192                 }
193
194                 return 0;
195         }
196
197         /* for leaf node */
198         if (params->leaf.cman) {
199                 error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_CMAN;
200                 error->message = "Congestion management not supported";
201                 return -EINVAL;
202         }
203         if (params->leaf.wred.wred_profile_id !=
204             RTE_TM_WRED_PROFILE_ID_NONE) {
205                 error->type =
206                         RTE_TM_ERROR_TYPE_NODE_PARAMS_WRED_PROFILE_ID;
207                 error->message = "WRED not supported";
208                 return -EINVAL;
209         }
210         if (params->leaf.wred.shared_wred_context_id) {
211                 error->type =
212                         RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_WRED_CONTEXT_ID;
213                 error->message = "WRED not supported";
214                 return -EINVAL;
215         }
216         if (params->leaf.wred.n_shared_wred_contexts) {
217                 error->type =
218                         RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_WRED_CONTEXTS;
219                 error->message = "WRED not supported";
220                 return -EINVAL;
221         }
222
223         return 0;
224 }
225
226 static int
227 ice_dcf_node_add(struct rte_eth_dev *dev, uint32_t node_id,
228               uint32_t parent_node_id, uint32_t priority,
229               uint32_t weight, uint32_t level_id,
230               struct rte_tm_node_params *params,
231               struct rte_tm_error *error)
232 {
233         enum ice_dcf_tm_node_type parent_node_type = ICE_DCF_TM_NODE_TYPE_MAX;
234         enum ice_dcf_tm_node_type node_type = ICE_DCF_TM_NODE_TYPE_MAX;
235         struct ice_dcf_tm_shaper_profile *shaper_profile = NULL;
236         struct ice_dcf_adapter *adapter = dev->data->dev_private;
237         struct ice_dcf_hw *hw = &adapter->real_hw;
238         struct ice_dcf_tm_node *parent_node;
239         struct ice_dcf_tm_node *tm_node;
240         uint16_t tc_nb = 1;
241         int i, ret;
242
243         if (!params || !error)
244                 return -EINVAL;
245
246         /* if already committed */
247         if (hw->tm_conf.committed) {
248                 error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
249                 error->message = "already committed";
250                 return -EINVAL;
251         }
252
253         ret = ice_dcf_node_param_check(hw, node_id, priority, weight,
254                                    params, error);
255         if (ret)
256                 return ret;
257
258         for (i = 1; i < ICE_MAX_TRAFFIC_CLASS; i++) {
259                 if (hw->ets_config->tc_valid_bits & (1 << i))
260                         tc_nb++;
261         }
262
263         /* check if the node is already existed */
264         if (ice_dcf_tm_node_search(dev, node_id, &node_type)) {
265                 error->type = RTE_TM_ERROR_TYPE_NODE_ID;
266                 error->message = "node id already used";
267                 return -EINVAL;
268         }
269
270         /* check the shaper profile id */
271         if (params->shaper_profile_id != RTE_TM_SHAPER_PROFILE_ID_NONE) {
272                 shaper_profile = ice_dcf_shaper_profile_search(dev,
273                         params->shaper_profile_id);
274                 if (!shaper_profile) {
275                         error->type =
276                                 RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID;
277                         error->message = "shaper profile not exist";
278                         return -EINVAL;
279                 }
280         }
281
282         /* add root node if not have a parent */
283         if (parent_node_id == RTE_TM_NODE_ID_NULL) {
284                 /* check level */
285                 if (level_id != ICE_DCF_TM_NODE_TYPE_PORT) {
286                         error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;
287                         error->message = "Wrong level";
288                         return -EINVAL;
289                 }
290
291                 /* obviously no more than one root */
292                 if (hw->tm_conf.root) {
293                         error->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;
294                         error->message = "already have a root";
295                         return -EINVAL;
296                 }
297
298                 /* add the root node */
299                 tm_node = rte_zmalloc("ice_dcf_tm_node",
300                                       sizeof(struct ice_dcf_tm_node),
301                                       0);
302                 if (!tm_node)
303                         return -ENOMEM;
304                 tm_node->id = node_id;
305                 tm_node->parent = NULL;
306                 tm_node->reference_count = 0;
307                 rte_memcpy(&tm_node->params, params,
308                                  sizeof(struct rte_tm_node_params));
309                 hw->tm_conf.root = tm_node;
310
311                 return 0;
312         }
313
314         /* TC or vsi node */
315         /* check the parent node */
316         parent_node = ice_dcf_tm_node_search(dev, parent_node_id,
317                                           &parent_node_type);
318         if (!parent_node) {
319                 error->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;
320                 error->message = "parent not exist";
321                 return -EINVAL;
322         }
323         if (parent_node_type != ICE_DCF_TM_NODE_TYPE_PORT &&
324             parent_node_type != ICE_DCF_TM_NODE_TYPE_TC) {
325                 error->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;
326                 error->message = "parent is not port or TC";
327                 return -EINVAL;
328         }
329         /* check level */
330         if (level_id != RTE_TM_NODE_LEVEL_ID_ANY &&
331             level_id != (uint32_t)(parent_node_type + 1)) {
332                 error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;
333                 error->message = "Wrong level";
334                 return -EINVAL;
335         }
336
337         /* check the TC node number */
338         if (parent_node_type == ICE_DCF_TM_NODE_TYPE_PORT) {
339                 /* check the TC number */
340                 if (hw->tm_conf.nb_tc_node >= tc_nb) {
341                         error->type = RTE_TM_ERROR_TYPE_NODE_ID;
342                         error->message = "too many TCs";
343                         return -EINVAL;
344                 }
345         } else {
346                 /* check the vsi node number */
347                 if (parent_node->reference_count >= hw->num_vfs) {
348                         error->type = RTE_TM_ERROR_TYPE_NODE_ID;
349                         error->message = "too many VSI for one TC";
350                         return -EINVAL;
351                 }
352                 /* check the vsi node id */
353                 if (node_id > (uint32_t)(tc_nb * hw->num_vfs)) {
354                         error->type = RTE_TM_ERROR_TYPE_NODE_ID;
355                         error->message = "too large VSI id";
356                         return -EINVAL;
357                 }
358         }
359
360         /* add the TC or vsi node */
361         tm_node = rte_zmalloc("ice_dcf_tm_node",
362                               sizeof(struct ice_dcf_tm_node),
363                               0);
364         if (!tm_node)
365                 return -ENOMEM;
366         tm_node->id = node_id;
367         tm_node->priority = priority;
368         tm_node->weight = weight;
369         tm_node->shaper_profile = shaper_profile;
370         tm_node->reference_count = 0;
371         tm_node->parent = parent_node;
372         rte_memcpy(&tm_node->params, params,
373                          sizeof(struct rte_tm_node_params));
374         if (parent_node_type == ICE_DCF_TM_NODE_TYPE_PORT) {
375                 TAILQ_INSERT_TAIL(&hw->tm_conf.tc_list,
376                                   tm_node, node);
377                 tm_node->tc = hw->tm_conf.nb_tc_node;
378                 hw->tm_conf.nb_tc_node++;
379         } else {
380                 TAILQ_INSERT_TAIL(&hw->tm_conf.vsi_list,
381                                   tm_node, node);
382                 tm_node->tc = parent_node->tc;
383                 hw->tm_conf.nb_vsi_node++;
384         }
385         tm_node->parent->reference_count++;
386
387         /* increase the reference counter of the shaper profile */
388         if (shaper_profile)
389                 shaper_profile->reference_count++;
390
391         return 0;
392 }
393
394 static int
395 ice_dcf_node_delete(struct rte_eth_dev *dev, uint32_t node_id,
396                  struct rte_tm_error *error)
397 {
398         enum ice_dcf_tm_node_type node_type = ICE_DCF_TM_NODE_TYPE_MAX;
399         struct ice_dcf_adapter *adapter = dev->data->dev_private;
400         struct ice_dcf_hw *hw = &adapter->real_hw;
401         struct ice_dcf_tm_node *tm_node;
402
403         if (!error)
404                 return -EINVAL;
405
406         /* if already committed */
407         if (hw->tm_conf.committed) {
408                 error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
409                 error->message = "already committed";
410                 return -EINVAL;
411         }
412
413         if (node_id == RTE_TM_NODE_ID_NULL) {
414                 error->type = RTE_TM_ERROR_TYPE_NODE_ID;
415                 error->message = "invalid node id";
416                 return -EINVAL;
417         }
418
419         /* check if the node id exists */
420         tm_node = ice_dcf_tm_node_search(dev, node_id, &node_type);
421         if (!tm_node) {
422                 error->type = RTE_TM_ERROR_TYPE_NODE_ID;
423                 error->message = "no such node";
424                 return -EINVAL;
425         }
426
427         /* the node should have no child */
428         if (tm_node->reference_count) {
429                 error->type = RTE_TM_ERROR_TYPE_NODE_ID;
430                 error->message =
431                         "cannot delete a node which has children";
432                 return -EINVAL;
433         }
434
435         /* root node */
436         if (node_type == ICE_DCF_TM_NODE_TYPE_PORT) {
437                 if (tm_node->shaper_profile)
438                         tm_node->shaper_profile->reference_count--;
439                 rte_free(tm_node);
440                 hw->tm_conf.root = NULL;
441                 return 0;
442         }
443
444         /* TC or VSI node */
445         if (tm_node->shaper_profile)
446                 tm_node->shaper_profile->reference_count--;
447         tm_node->parent->reference_count--;
448         if (node_type == ICE_DCF_TM_NODE_TYPE_TC) {
449                 TAILQ_REMOVE(&hw->tm_conf.tc_list, tm_node, node);
450                 hw->tm_conf.nb_tc_node--;
451         } else {
452                 TAILQ_REMOVE(&hw->tm_conf.vsi_list, tm_node, node);
453                 hw->tm_conf.nb_vsi_node--;
454         }
455         rte_free(tm_node);
456
457         return 0;
458 }
459
460 static int
461 ice_dcf_shaper_profile_param_check(struct rte_tm_shaper_params *profile,
462                                 struct rte_tm_error *error)
463 {
464         /* min bucket size not supported */
465         if (profile->committed.size) {
466                 error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_SIZE;
467                 error->message = "committed bucket size not supported";
468                 return -EINVAL;
469         }
470         /* max bucket size not supported */
471         if (profile->peak.size) {
472                 error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE;
473                 error->message = "peak bucket size not supported";
474                 return -EINVAL;
475         }
476         /* length adjustment not supported */
477         if (profile->pkt_length_adjust) {
478                 error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PKT_ADJUST_LEN;
479                 error->message = "packet length adjustment not supported";
480                 return -EINVAL;
481         }
482
483         return 0;
484 }
485
486 static int
487 ice_dcf_shaper_profile_add(struct rte_eth_dev *dev,
488                         uint32_t shaper_profile_id,
489                         struct rte_tm_shaper_params *profile,
490                         struct rte_tm_error *error)
491 {
492         struct ice_dcf_adapter *adapter = dev->data->dev_private;
493         struct ice_dcf_hw *hw = &adapter->real_hw;
494         struct ice_dcf_tm_shaper_profile *shaper_profile;
495         int ret;
496
497         if (!profile || !error)
498                 return -EINVAL;
499
500         ret = ice_dcf_shaper_profile_param_check(profile, error);
501         if (ret)
502                 return ret;
503
504         shaper_profile = ice_dcf_shaper_profile_search(dev, shaper_profile_id);
505
506         if (shaper_profile) {
507                 error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID;
508                 error->message = "profile ID exist";
509                 return -EINVAL;
510         }
511
512         shaper_profile = rte_zmalloc("ice_dcf_tm_shaper_profile",
513                                      sizeof(struct ice_dcf_tm_shaper_profile),
514                                      0);
515         if (!shaper_profile)
516                 return -ENOMEM;
517         shaper_profile->shaper_profile_id = shaper_profile_id;
518         rte_memcpy(&shaper_profile->profile, profile,
519                          sizeof(struct rte_tm_shaper_params));
520         TAILQ_INSERT_TAIL(&hw->tm_conf.shaper_profile_list,
521                           shaper_profile, node);
522
523         return 0;
524 }
525
526 static int
527 ice_dcf_shaper_profile_del(struct rte_eth_dev *dev,
528                         uint32_t shaper_profile_id,
529                         struct rte_tm_error *error)
530 {
531         struct ice_dcf_adapter *adapter = dev->data->dev_private;
532         struct ice_dcf_hw *hw = &adapter->real_hw;
533         struct ice_dcf_tm_shaper_profile *shaper_profile;
534
535         if (!error)
536                 return -EINVAL;
537
538         shaper_profile = ice_dcf_shaper_profile_search(dev, shaper_profile_id);
539
540         if (!shaper_profile) {
541                 error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID;
542                 error->message = "profile ID not exist";
543                 return -EINVAL;
544         }
545
546         /* don't delete a profile if it's used by one or several nodes */
547         if (shaper_profile->reference_count) {
548                 error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE;
549                 error->message = "profile in use";
550                 return -EINVAL;
551         }
552
553         TAILQ_REMOVE(&hw->tm_conf.shaper_profile_list, shaper_profile, node);
554         rte_free(shaper_profile);
555
556         return 0;
557 }
558
559 static int
560 ice_dcf_set_vf_bw(struct ice_dcf_hw *hw,
561                         struct virtchnl_dcf_bw_cfg_list *vf_bw,
562                         uint16_t len)
563 {
564         struct dcf_virtchnl_cmd args;
565         int err;
566
567         memset(&args, 0, sizeof(args));
568         args.v_op = VIRTCHNL_OP_DCF_CONFIG_BW;
569         args.req_msg = (uint8_t *)vf_bw;
570         args.req_msglen  = len;
571         err = ice_dcf_execute_virtchnl_cmd(hw, &args);
572         if (err)
573                 PMD_DRV_LOG(ERR, "fail to execute command %s",
574                             "VIRTCHNL_OP_DCF_CONFIG_BW");
575         return err;
576 }
577
578 static int
579 ice_dcf_validate_tc_bw(struct virtchnl_dcf_bw_cfg_list *tc_bw,
580                         uint32_t port_bw)
581 {
582         struct virtchnl_dcf_bw_cfg *cfg;
583         bool lowest_cir_mark = false;
584         u32 total_peak, rest_peak;
585         u32 committed, peak;
586         int i;
587
588         total_peak = 0;
589         for (i = 0; i < tc_bw->num_elem; i++)
590                 total_peak += tc_bw->cfg[i].shaper.peak;
591
592         for (i = 0; i < tc_bw->num_elem; i++) {
593                 cfg = &tc_bw->cfg[i];
594                 peak = cfg->shaper.peak;
595                 committed = cfg->shaper.committed;
596                 rest_peak = total_peak - peak;
597
598                 if (lowest_cir_mark && peak == 0) {
599                         PMD_DRV_LOG(ERR, "Max bandwidth must be configured for TC%u",
600                                 cfg->tc_num);
601                         return -EINVAL;
602                 }
603
604                 if (!lowest_cir_mark && committed)
605                         lowest_cir_mark = true;
606
607                 if (committed && committed + rest_peak > port_bw) {
608                         PMD_DRV_LOG(ERR, "Total value of TC%u min bandwidth and other TCs' max bandwidth %ukbps should be less than port link speed %ukbps",
609                                 cfg->tc_num, committed + rest_peak, port_bw);
610                         return -EINVAL;
611                 }
612
613                 if (committed && committed < ICE_SCHED_MIN_BW) {
614                         PMD_DRV_LOG(ERR, "If TC%u min Tx bandwidth is set, it cannot be less than 500Kbps",
615                                 cfg->tc_num);
616                         return -EINVAL;
617                 }
618
619                 if (peak && committed > peak) {
620                         PMD_DRV_LOG(ERR, "TC%u Min Tx bandwidth cannot be greater than max Tx bandwidth",
621                                 cfg->tc_num);
622                         return -EINVAL;
623                 }
624
625                 if (peak > port_bw) {
626                         PMD_DRV_LOG(ERR, "TC%u max Tx bandwidth %uKbps is greater than current link speed %uKbps",
627                                 cfg->tc_num, peak, port_bw);
628                         return -EINVAL;
629                 }
630         }
631
632         return 0;
633 }
634
635 static int ice_dcf_commit_check(struct ice_dcf_hw *hw)
636 {
637         struct ice_dcf_tm_node_list *tc_list = &hw->tm_conf.tc_list;
638         struct ice_dcf_tm_node_list *vsi_list = &hw->tm_conf.vsi_list;
639         struct ice_dcf_tm_node *tm_node;
640
641         if (!(hw->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_QOS)) {
642                 PMD_DRV_LOG(ERR, "Configure VF bandwidth is not supported");
643                 return ICE_ERR_NOT_SUPPORTED;
644         }
645
646         /* check if all TC nodes are set */
647         if (BIT(hw->tm_conf.nb_tc_node) & hw->ets_config->tc_valid_bits) {
648                 PMD_DRV_LOG(ERR, "Not all enabled TC nodes are set");
649                 return ICE_ERR_PARAM;
650         }
651
652         /* check if all VF vsi nodes are binded to all TCs */
653         TAILQ_FOREACH(tm_node, tc_list, node) {
654                 if (tm_node->reference_count != hw->num_vfs) {
655                         PMD_DRV_LOG(ERR, "Not all VFs are binded to TC%u",
656                                         tm_node->tc);
657                         return ICE_ERR_PARAM;
658                 }
659         }
660
661         /* check if VF vsi node id start with 0 */
662         tm_node = TAILQ_FIRST(vsi_list);
663         if (tm_node->id != 0) {
664                 PMD_DRV_LOG(ERR, "VF vsi node id must start with 0");
665                 return ICE_ERR_PARAM;
666         }
667
668         return ICE_SUCCESS;
669 }
670
671 int
672 ice_dcf_replay_vf_bw(struct ice_dcf_hw *hw, uint16_t vf_id)
673 {
674         struct ice_aqc_port_ets_elem old_ets_config;
675         struct ice_dcf_adapter *adapter;
676         struct ice_hw *parent_hw;
677         int ret, size;
678
679         adapter = hw->eth_dev->data->dev_private;
680         parent_hw = &adapter->parent.hw;
681
682         /* store the old ets config */
683         old_ets_config = *hw->ets_config;
684
685         ice_memset(hw->ets_config, 0, sizeof(*hw->ets_config), ICE_NONDMA_MEM);
686         ret = ice_aq_query_port_ets(parent_hw->port_info,
687                         hw->ets_config, sizeof(*hw->ets_config),
688                         NULL);
689         if (ret) {
690                 PMD_DRV_LOG(ERR, "DCF Query Port ETS failed");
691                 return ret;
692         }
693
694         if (memcmp(&old_ets_config, hw->ets_config, sizeof(old_ets_config))) {
695                 PMD_DRV_LOG(DEBUG, "ETS config changes, do not replay BW");
696                 return ICE_SUCCESS;
697         }
698
699         size = sizeof(struct virtchnl_dcf_bw_cfg_list) +
700                 sizeof(struct virtchnl_dcf_bw_cfg) *
701                 (hw->tm_conf.nb_tc_node - 1);
702
703         ret = ice_dcf_set_vf_bw(hw, hw->qos_bw_cfg[vf_id], size);
704         if (ret) {
705                 PMD_DRV_LOG(DEBUG, "VF %u BW replay failed", vf_id);
706                 return ICE_ERR_CFG;
707         }
708
709         return ICE_SUCCESS;
710 }
711
712 static int ice_dcf_hierarchy_commit(struct rte_eth_dev *dev,
713                                  int clear_on_fail,
714                                  __rte_unused struct rte_tm_error *error)
715 {
716         struct ice_dcf_adapter *adapter = dev->data->dev_private;
717         struct ice_dcf_hw *hw = &adapter->real_hw;
718         struct virtchnl_dcf_bw_cfg_list *vf_bw;
719         struct virtchnl_dcf_bw_cfg_list *tc_bw;
720         struct ice_dcf_tm_node_list *vsi_list = &hw->tm_conf.vsi_list;
721         struct rte_tm_shaper_params *profile;
722         struct ice_dcf_tm_node *tm_node;
723         uint32_t port_bw, cir_total;
724         uint16_t size, vf_id;
725         uint8_t num_elem = 0;
726         int i, ret_val;
727
728         ret_val = ice_dcf_commit_check(hw);
729         if (ret_val)
730                 goto fail_clear;
731
732         size = sizeof(struct virtchnl_dcf_bw_cfg_list) +
733                 sizeof(struct virtchnl_dcf_bw_cfg) *
734                 (hw->tm_conf.nb_tc_node - 1);
735         vf_bw = rte_zmalloc("vf_bw", size, 0);
736         if (!vf_bw) {
737                 ret_val = ICE_ERR_NO_MEMORY;
738                 goto fail_clear;
739         }
740         tc_bw = rte_zmalloc("tc_bw", size, 0);
741         if (!tc_bw) {
742                 ret_val = ICE_ERR_NO_MEMORY;
743                 goto fail_clear;
744         }
745
746         /* port bandwidth (Kbps) */
747         port_bw = hw->link_speed * 1000;
748         cir_total = 0;
749
750         /* init tc bw configuration */
751 #define ICE_DCF_SCHED_TC_NODE 0xffff
752         tc_bw->vf_id = ICE_DCF_SCHED_TC_NODE;
753         tc_bw->node_type = VIRTCHNL_DCF_TARGET_TC_BW;
754         tc_bw->num_elem = hw->tm_conf.nb_tc_node;
755         for (i = 0; i < tc_bw->num_elem; i++) {
756                 tc_bw->cfg[i].tc_num = i;
757                 tc_bw->cfg[i].type = VIRTCHNL_BW_SHAPER;
758                 tc_bw->cfg[i].bw_type |=
759                         VIRTCHNL_DCF_BW_PIR | VIRTCHNL_DCF_BW_CIR;
760         }
761
762         /* start with VF1, skip VF0 since DCF does not need to configure
763          * bandwidth for itself
764          */
765         for (vf_id = 1; vf_id < hw->num_vfs; vf_id++) {
766                 num_elem = 0;
767                 vf_bw->vf_id = vf_id;
768                 vf_bw->node_type = VIRTCHNL_DCF_TARGET_VF_BW;
769                 TAILQ_FOREACH(tm_node, vsi_list, node) {
770                         /* scan the nodes belong to one VSI */
771                         if (tm_node->id - hw->num_vfs * tm_node->tc != vf_id)
772                                 continue;
773                         vf_bw->cfg[num_elem].tc_num = tm_node->tc;
774                         vf_bw->cfg[num_elem].type = VIRTCHNL_BW_SHAPER;
775                         if (tm_node->shaper_profile) {
776                                 /* Transfer from Byte per seconds to Kbps */
777                                 profile = &tm_node->shaper_profile->profile;
778                                 vf_bw->cfg[num_elem].shaper.peak =
779                                 profile->peak.rate / 1000 * BITS_PER_BYTE;
780                                 vf_bw->cfg[num_elem].shaper.committed =
781                                 profile->committed.rate / 1000 * BITS_PER_BYTE;
782                                 vf_bw->cfg[num_elem].bw_type |=
783                                         VIRTCHNL_DCF_BW_PIR |
784                                         VIRTCHNL_DCF_BW_CIR;
785                         }
786
787                         /* update tc node bw configuration */
788                         tc_bw->cfg[tm_node->tc].shaper.peak +=
789                                 vf_bw->cfg[num_elem].shaper.peak;
790                         tc_bw->cfg[tm_node->tc].shaper.committed +=
791                                 vf_bw->cfg[num_elem].shaper.committed;
792
793                         cir_total += vf_bw->cfg[num_elem].shaper.committed;
794                         num_elem++;
795                 }
796
797                 vf_bw->num_elem = num_elem;
798                 ret_val = ice_dcf_set_vf_bw(hw, vf_bw, size);
799                 if (ret_val)
800                         goto fail_clear;
801
802                 hw->qos_bw_cfg[vf_id] = rte_zmalloc("vf_bw_cfg", size, 0);
803                 if (!hw->qos_bw_cfg[vf_id]) {
804                         ret_val = ICE_ERR_NO_MEMORY;
805                         goto fail_clear;
806                 }
807                 /* store the bandwidth information for replay */
808                 ice_memcpy(hw->qos_bw_cfg[vf_id], vf_bw, sizeof(*vf_bw),
809                            ICE_NONDMA_TO_NONDMA);
810                 ice_memset(vf_bw, 0, size, ICE_NONDMA_MEM);
811         }
812
813         /* check if total CIR is larger than port bandwidth */
814         if (cir_total > port_bw) {
815                 PMD_DRV_LOG(ERR, "Total CIR of all VFs is larger than port bandwidth");
816                 ret_val = ICE_ERR_PARAM;
817                 goto fail_clear;
818         }
819
820         /* check and commit tc node bw configuration */
821         ret_val = ice_dcf_validate_tc_bw(tc_bw, port_bw);
822         if (ret_val)
823                 goto fail_clear;
824         ret_val = ice_dcf_set_vf_bw(hw, tc_bw, size);
825         if (ret_val)
826                 goto fail_clear;
827
828         hw->tm_conf.committed = true;
829         return ret_val;
830
831 fail_clear:
832         /* clear all the traffic manager configuration */
833         if (clear_on_fail) {
834                 ice_dcf_tm_conf_uninit(dev);
835                 ice_dcf_tm_conf_init(dev);
836         }
837         return ret_val;
838 }