net/i40e: fix Rx packet statistics
[dpdk.git] / drivers / net / dpaa2 / dpaa2_tm.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2020 NXP
3  */
4
5 #include <rte_ethdev.h>
6 #include <rte_malloc.h>
7 #include <rte_tm_driver.h>
8
9 #include "dpaa2_ethdev.h"
10
11 #define DPAA2_BURST_MAX (64 * 1024)
12
13 #define DPAA2_SHAPER_MIN_RATE 0
14 #define DPAA2_SHAPER_MAX_RATE 107374182400ull
15 #define DPAA2_WEIGHT_MAX 24701
16
17 int
18 dpaa2_tm_init(struct rte_eth_dev *dev)
19 {
20         struct dpaa2_dev_priv *priv = dev->data->dev_private;
21
22         LIST_INIT(&priv->shaper_profiles);
23         LIST_INIT(&priv->nodes);
24
25         return 0;
26 }
27
28 void dpaa2_tm_deinit(struct rte_eth_dev *dev)
29 {
30         struct dpaa2_dev_priv *priv = dev->data->dev_private;
31         struct dpaa2_tm_shaper_profile *profile =
32                 LIST_FIRST(&priv->shaper_profiles);
33         struct dpaa2_tm_node *node = LIST_FIRST(&priv->nodes);
34
35         while (profile) {
36                 struct dpaa2_tm_shaper_profile *next = LIST_NEXT(profile, next);
37
38                 LIST_REMOVE(profile, next);
39                 rte_free(profile);
40                 profile = next;
41         }
42
43         while (node) {
44                 struct dpaa2_tm_node *next = LIST_NEXT(node, next);
45
46                 LIST_REMOVE(node, next);
47                 rte_free(node);
48                 node = next;
49         }
50 }
51
52 static struct dpaa2_tm_node *
53 dpaa2_node_from_id(struct dpaa2_dev_priv *priv, uint32_t node_id)
54 {
55         struct dpaa2_tm_node *node;
56
57         LIST_FOREACH(node, &priv->nodes, next)
58                 if (node->id == node_id)
59                         return node;
60
61         return NULL;
62 }
63
64 static int
65 dpaa2_capabilities_get(struct rte_eth_dev *dev,
66                        struct rte_tm_capabilities *cap,
67                       struct rte_tm_error *error)
68 {
69         if (!cap)
70                 return -rte_tm_error_set(error, EINVAL,
71                                          RTE_TM_ERROR_TYPE_UNSPECIFIED,
72                                          NULL, "Capabilities are NULL\n");
73
74         memset(cap, 0, sizeof(*cap));
75
76         /* root node(port) + txqs number, assuming each TX
77          * Queue is mapped to each TC
78          */
79         cap->n_nodes_max = 1 + dev->data->nb_tx_queues;
80         cap->n_levels_max = 2; /* port level + txqs level */
81         cap->non_leaf_nodes_identical = 1;
82         cap->leaf_nodes_identical = 1;
83
84         cap->shaper_n_max = 1;
85         cap->shaper_private_n_max = 1;
86         cap->shaper_private_dual_rate_n_max = 1;
87         cap->shaper_private_rate_min = DPAA2_SHAPER_MIN_RATE;
88         cap->shaper_private_rate_max = DPAA2_SHAPER_MAX_RATE;
89
90         cap->sched_n_children_max = dev->data->nb_tx_queues;
91         cap->sched_sp_n_priorities_max = dev->data->nb_tx_queues;
92         cap->sched_wfq_n_children_per_group_max = dev->data->nb_tx_queues;
93         cap->sched_wfq_n_groups_max = 2;
94         cap->sched_wfq_weight_max = DPAA2_WEIGHT_MAX;
95
96         cap->dynamic_update_mask = RTE_TM_UPDATE_NODE_STATS;
97         cap->stats_mask = RTE_TM_STATS_N_PKTS | RTE_TM_STATS_N_BYTES;
98
99         return 0;
100 }
101
102 static int
103 dpaa2_level_capabilities_get(struct rte_eth_dev *dev,
104                             uint32_t level_id,
105                             struct rte_tm_level_capabilities *cap,
106                             struct rte_tm_error *error)
107 {
108         if (!cap)
109                 return -rte_tm_error_set(error, EINVAL,
110                                          RTE_TM_ERROR_TYPE_UNSPECIFIED,
111                                          NULL, NULL);
112
113         memset(cap, 0, sizeof(*cap));
114
115         if (level_id > 1)
116                 return -rte_tm_error_set(error, EINVAL,
117                                          RTE_TM_ERROR_TYPE_LEVEL_ID,
118                                          NULL, "Wrong level id\n");
119
120         if (level_id == 0) { /* Root node */
121                 cap->n_nodes_max = 1;
122                 cap->n_nodes_nonleaf_max = 1;
123                 cap->non_leaf_nodes_identical = 1;
124
125                 cap->nonleaf.shaper_private_supported = 1;
126                 cap->nonleaf.shaper_private_dual_rate_supported = 1;
127                 cap->nonleaf.shaper_private_rate_min = DPAA2_SHAPER_MIN_RATE;
128                 cap->nonleaf.shaper_private_rate_max = DPAA2_SHAPER_MAX_RATE;
129
130                 cap->nonleaf.sched_n_children_max = dev->data->nb_tx_queues;
131                 cap->nonleaf.sched_sp_n_priorities_max = 1;
132                 cap->nonleaf.sched_wfq_n_children_per_group_max =
133                         dev->data->nb_tx_queues;
134                 cap->nonleaf.sched_wfq_n_groups_max = 2;
135                 cap->nonleaf.sched_wfq_weight_max = DPAA2_WEIGHT_MAX;
136                 cap->nonleaf.stats_mask = RTE_TM_STATS_N_PKTS |
137                                           RTE_TM_STATS_N_BYTES;
138         } else { /* leaf nodes */
139                 cap->n_nodes_max = dev->data->nb_tx_queues;
140                 cap->n_nodes_leaf_max = dev->data->nb_tx_queues;
141                 cap->leaf_nodes_identical = 1;
142
143                 cap->leaf.stats_mask = RTE_TM_STATS_N_PKTS;
144         }
145
146         return 0;
147 }
148
149 static int
150 dpaa2_node_capabilities_get(struct rte_eth_dev *dev, uint32_t node_id,
151                             struct rte_tm_node_capabilities *cap,
152                            struct rte_tm_error *error)
153 {
154         struct dpaa2_tm_node *node;
155         struct dpaa2_dev_priv *priv = dev->data->dev_private;
156
157         if (!cap)
158                 return -rte_tm_error_set(error, EINVAL,
159                                          RTE_TM_ERROR_TYPE_UNSPECIFIED,
160                                          NULL, NULL);
161
162         memset(cap, 0, sizeof(*cap));
163
164         node = dpaa2_node_from_id(priv, node_id);
165         if (!node)
166                 return -rte_tm_error_set(error, ENODEV,
167                                          RTE_TM_ERROR_TYPE_NODE_ID,
168                                          NULL, "Node id does not exist\n");
169
170         if (node->type == 0) {
171                 cap->shaper_private_supported = 1;
172
173                 cap->nonleaf.sched_n_children_max = dev->data->nb_tx_queues;
174                 cap->nonleaf.sched_sp_n_priorities_max = 1;
175                 cap->nonleaf.sched_wfq_n_children_per_group_max =
176                         dev->data->nb_tx_queues;
177                 cap->nonleaf.sched_wfq_n_groups_max = 2;
178                 cap->nonleaf.sched_wfq_weight_max = DPAA2_WEIGHT_MAX;
179                 cap->stats_mask = RTE_TM_STATS_N_PKTS | RTE_TM_STATS_N_BYTES;
180         } else {
181                 cap->stats_mask = RTE_TM_STATS_N_PKTS;
182         }
183
184         return 0;
185 }
186
187 static int
188 dpaa2_node_type_get(struct rte_eth_dev *dev, uint32_t node_id, int *is_leaf,
189                     struct rte_tm_error *error)
190 {
191         struct dpaa2_dev_priv *priv = dev->data->dev_private;
192         struct dpaa2_tm_node *node;
193
194         if (!is_leaf)
195                 return -rte_tm_error_set(error, EINVAL,
196                                          RTE_TM_ERROR_TYPE_UNSPECIFIED,
197                                          NULL, NULL);
198
199         node = dpaa2_node_from_id(priv, node_id);
200         if (!node)
201                 return -rte_tm_error_set(error, ENODEV,
202                                          RTE_TM_ERROR_TYPE_NODE_ID,
203                                          NULL, "Node id does not exist\n");
204
205         *is_leaf = node->type == 1/*NODE_QUEUE*/ ? 1 : 0;
206
207         return 0;
208 }
209
210 static struct dpaa2_tm_shaper_profile *
211 dpaa2_shaper_profile_from_id(struct dpaa2_dev_priv *priv,
212                                 uint32_t shaper_profile_id)
213 {
214         struct dpaa2_tm_shaper_profile *profile;
215
216         LIST_FOREACH(profile, &priv->shaper_profiles, next)
217                 if (profile->id == shaper_profile_id)
218                         return profile;
219
220         return NULL;
221 }
222
223 static int
224 dpaa2_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id,
225                          struct rte_tm_shaper_params *params,
226                         struct rte_tm_error *error)
227 {
228         struct dpaa2_dev_priv *priv = dev->data->dev_private;
229         struct dpaa2_tm_shaper_profile *profile;
230
231         if (!params)
232                 return -rte_tm_error_set(error, EINVAL,
233                                          RTE_TM_ERROR_TYPE_UNSPECIFIED,
234                                          NULL, NULL);
235         if (params->committed.rate > DPAA2_SHAPER_MAX_RATE)
236                 return -rte_tm_error_set(error, EINVAL,
237                                 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE,
238                                 NULL, "committed rate is out of range\n");
239
240         if (params->committed.size > DPAA2_BURST_MAX)
241                 return -rte_tm_error_set(error, EINVAL,
242                                 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE,
243                                 NULL, "committed size is out of range\n");
244
245         if (params->peak.rate > DPAA2_SHAPER_MAX_RATE)
246                 return -rte_tm_error_set(error, EINVAL,
247                                 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE,
248                                 NULL, "Peak rate is out of range\n");
249
250         if (params->peak.size > DPAA2_BURST_MAX)
251                 return -rte_tm_error_set(error, EINVAL,
252                                 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE,
253                                 NULL, "Peak size is out of range\n");
254
255         if (shaper_profile_id == RTE_TM_SHAPER_PROFILE_ID_NONE)
256                 return -rte_tm_error_set(error, EINVAL,
257                                          RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
258                                          NULL, "Wrong shaper profile id\n");
259
260         profile = dpaa2_shaper_profile_from_id(priv, shaper_profile_id);
261         if (profile)
262                 return -rte_tm_error_set(error, EEXIST,
263                                          RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
264                                          NULL, "Profile id already exists\n");
265
266         profile = rte_zmalloc_socket(NULL, sizeof(*profile), 0,
267                                      rte_socket_id());
268         if (!profile)
269                 return -rte_tm_error_set(error, ENOMEM,
270                                          RTE_TM_ERROR_TYPE_UNSPECIFIED,
271                                          NULL, NULL);
272
273         profile->id = shaper_profile_id;
274         rte_memcpy(&profile->params, params, sizeof(profile->params));
275
276         LIST_INSERT_HEAD(&priv->shaper_profiles, profile, next);
277
278         return 0;
279 }
280
281 static int
282 dpaa2_shaper_profile_delete(struct rte_eth_dev *dev, uint32_t shaper_profile_id,
283                             struct rte_tm_error *error)
284 {
285         struct dpaa2_dev_priv *priv = dev->data->dev_private;
286         struct dpaa2_tm_shaper_profile *profile;
287
288         profile = dpaa2_shaper_profile_from_id(priv, shaper_profile_id);
289         if (!profile)
290                 return -rte_tm_error_set(error, ENODEV,
291                                          RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
292                                          NULL, "Profile id does not exist\n");
293
294         if (profile->refcnt)
295                 return -rte_tm_error_set(error, EPERM,
296                                          RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
297                                          NULL, "Profile is used\n");
298
299         LIST_REMOVE(profile, next);
300         rte_free(profile);
301
302         return 0;
303 }
304
305 static int
306 dpaa2_node_check_params(struct rte_eth_dev *dev, uint32_t node_id,
307                 __rte_unused uint32_t priority, uint32_t weight,
308                        uint32_t level_id,
309                        struct rte_tm_node_params *params,
310                        struct rte_tm_error *error)
311 {
312         if (node_id == RTE_TM_NODE_ID_NULL)
313                 return -rte_tm_error_set(error, EINVAL, RTE_TM_NODE_ID_NULL,
314                                          NULL, "Node id is invalid\n");
315
316         if (weight > DPAA2_WEIGHT_MAX)
317                 return -rte_tm_error_set(error, EINVAL,
318                                          RTE_TM_ERROR_TYPE_NODE_WEIGHT,
319                                          NULL, "Weight is out of range\n");
320
321         if (level_id != 0 && level_id != 1)
322                 return -rte_tm_error_set(error, EINVAL,
323                                          RTE_TM_ERROR_TYPE_LEVEL_ID,
324                                          NULL, "Wrong level id\n");
325
326         if (!params)
327                 return -rte_tm_error_set(error, EINVAL,
328                                          RTE_TM_ERROR_TYPE_UNSPECIFIED,
329                                          NULL, NULL);
330
331         if (params->shared_shaper_id)
332                 return -rte_tm_error_set(error, EINVAL,
333                                 RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_SHAPER_ID,
334                                 NULL, "Shared shaper is not supported\n");
335
336         if (params->n_shared_shapers)
337                 return -rte_tm_error_set(error, EINVAL,
338                                 RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS,
339                                 NULL, "Shared shaper is not supported\n");
340
341         /* verify port (root node) settings */
342         if (node_id >= dev->data->nb_tx_queues) {
343                 if (params->nonleaf.wfq_weight_mode)
344                         return -rte_tm_error_set(error, EINVAL,
345                                 RTE_TM_ERROR_TYPE_NODE_PARAMS_WFQ_WEIGHT_MODE,
346                                 NULL, "WFQ weight mode is not supported\n");
347
348                 if (params->stats_mask & ~(RTE_TM_STATS_N_PKTS |
349                                            RTE_TM_STATS_N_BYTES))
350                         return -rte_tm_error_set(error, EINVAL,
351                                 RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS,
352                                 NULL,
353                                 "Requested port stats are not supported\n");
354
355                 return 0;
356         }
357         if (params->shaper_profile_id != RTE_TM_SHAPER_PROFILE_ID_NONE)
358                 return -rte_tm_error_set(error, EINVAL,
359                         RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID,
360                         NULL, "Private shaper not supported on leaf\n");
361
362         if (params->stats_mask & ~RTE_TM_STATS_N_PKTS)
363                 return -rte_tm_error_set(error, EINVAL,
364                         RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS,
365                         NULL,
366                         "Requested stats are not supported\n");
367
368         /* check leaf node */
369         if (level_id == 1) {
370                 if (params->leaf.cman != RTE_TM_CMAN_TAIL_DROP)
371                         return -rte_tm_error_set(error, ENODEV,
372                                         RTE_TM_ERROR_TYPE_NODE_PARAMS_CMAN,
373                                         NULL, "Only taildrop is supported\n");
374         }
375
376         return 0;
377 }
378
379 static int
380 dpaa2_node_add(struct rte_eth_dev *dev, uint32_t node_id,
381               uint32_t parent_node_id, uint32_t priority, uint32_t weight,
382               uint32_t level_id, struct rte_tm_node_params *params,
383               struct rte_tm_error *error)
384 {
385         struct dpaa2_dev_priv *priv = dev->data->dev_private;
386         struct dpaa2_tm_shaper_profile *profile = NULL;
387         struct dpaa2_tm_node *node, *parent = NULL;
388         int ret;
389
390         if (0/* If device is started*/)
391                 return -rte_tm_error_set(error, EPERM,
392                                          RTE_TM_ERROR_TYPE_UNSPECIFIED,
393                                          NULL, "Port is already started\n");
394
395         ret = dpaa2_node_check_params(dev, node_id, priority, weight, level_id,
396                                       params, error);
397         if (ret)
398                 return ret;
399
400         if (params->shaper_profile_id != RTE_TM_SHAPER_PROFILE_ID_NONE) {
401                 profile = dpaa2_shaper_profile_from_id(priv,
402                                                      params->shaper_profile_id);
403                 if (!profile)
404                         return -rte_tm_error_set(error, ENODEV,
405                                         RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
406                                         NULL, "Shaper id does not exist\n");
407         }
408         if (parent_node_id == RTE_TM_NODE_ID_NULL) {
409                 LIST_FOREACH(node, &priv->nodes, next) {
410                         if (node->type != 0 /*root node*/)
411                                 continue;
412
413                         return -rte_tm_error_set(error, EINVAL,
414                                                  RTE_TM_ERROR_TYPE_UNSPECIFIED,
415                                                  NULL, "Root node exists\n");
416                 }
417         } else {
418                 parent = dpaa2_node_from_id(priv, parent_node_id);
419                 if (!parent)
420                         return -rte_tm_error_set(error, EINVAL,
421                                         RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID,
422                                         NULL, "Parent node id not exist\n");
423         }
424
425         node = dpaa2_node_from_id(priv, node_id);
426         if (node)
427                 return -rte_tm_error_set(error, ENODEV,
428                                          RTE_TM_ERROR_TYPE_NODE_ID,
429                                          NULL, "Node id already exists\n");
430
431         node = rte_zmalloc_socket(NULL, sizeof(*node), 0, rte_socket_id());
432         if (!node)
433                 return -rte_tm_error_set(error, ENOMEM,
434                                          RTE_TM_ERROR_TYPE_UNSPECIFIED,
435                                          NULL, NULL);
436
437         node->id = node_id;
438         node->type = parent_node_id == RTE_TM_NODE_ID_NULL ? 0/*NODE_PORT*/ :
439                                                              1/*NODE_QUEUE*/;
440
441         if (parent) {
442                 node->parent = parent;
443                 parent->refcnt++;
444         }
445
446         if (profile) {
447                 node->profile = profile;
448                 profile->refcnt++;
449         }
450
451         node->weight = weight;
452         node->priority = priority;
453         node->stats_mask = params->stats_mask;
454
455         LIST_INSERT_HEAD(&priv->nodes, node, next);
456
457         return 0;
458 }
459
460 static int
461 dpaa2_node_delete(struct rte_eth_dev *dev, uint32_t node_id,
462                   struct rte_tm_error *error)
463 {
464         struct dpaa2_dev_priv *priv = dev->data->dev_private;
465         struct dpaa2_tm_node *node;
466
467         if (0) {
468                 return -rte_tm_error_set(error, EPERM,
469                                          RTE_TM_ERROR_TYPE_UNSPECIFIED,
470                                          NULL, "Port is already started\n");
471         }
472
473         node = dpaa2_node_from_id(priv, node_id);
474         if (!node)
475                 return -rte_tm_error_set(error, ENODEV,
476                                          RTE_TM_ERROR_TYPE_NODE_ID,
477                                          NULL, "Node id does not exist\n");
478
479         if (node->refcnt)
480                 return -rte_tm_error_set(error, EPERM,
481                                          RTE_TM_ERROR_TYPE_NODE_ID,
482                                          NULL, "Node id is used\n");
483
484         if (node->parent)
485                 node->parent->refcnt--;
486
487         if (node->profile)
488                 node->profile->refcnt--;
489
490         LIST_REMOVE(node, next);
491         rte_free(node);
492
493         return 0;
494 }
495
496 static int
497 dpaa2_hierarchy_commit(struct rte_eth_dev *dev, int clear_on_fail,
498                        struct rte_tm_error *error)
499 {
500         struct dpaa2_dev_priv *priv = dev->data->dev_private;
501         struct dpaa2_tm_node *node, *temp_node;
502         struct fsl_mc_io *dpni = (struct fsl_mc_io *)dev->process_private;
503         int ret;
504         int wfq_grp = 0, is_wfq_grp = 0, conf[DPNI_MAX_TC];
505         struct dpni_tx_priorities_cfg prio_cfg;
506
507         memset(&prio_cfg, 0, sizeof(prio_cfg));
508         memset(conf, 0, sizeof(conf));
509
510         LIST_FOREACH(node, &priv->nodes, next) {
511                 if (node->type == 0/*root node*/) {
512                         if (!node->profile)
513                                 continue;
514
515                         struct dpni_tx_shaping_cfg tx_cr_shaper, tx_er_shaper;
516
517                         tx_cr_shaper.max_burst_size =
518                                 node->profile->params.committed.size;
519                         tx_cr_shaper.rate_limit =
520                                 node->profile->params.committed.rate / (1024 * 1024);
521                         tx_er_shaper.max_burst_size =
522                                 node->profile->params.peak.size;
523                         tx_er_shaper.rate_limit =
524                                 node->profile->params.peak.rate / (1024 * 1024);
525                         ret = dpni_set_tx_shaping(dpni, 0, priv->token,
526                                         &tx_cr_shaper, &tx_er_shaper, 0);
527                         if (ret) {
528                                 ret = -rte_tm_error_set(error, EINVAL,
529                                         RTE_TM_ERROR_TYPE_SHAPER_PROFILE, NULL,
530                                         "Error in setting Shaping\n");
531                                 goto out;
532                         }
533
534                         continue;
535                 } else { /* level 1, all leaf nodes */
536                         if (node->id >= dev->data->nb_tx_queues) {
537                                 ret = -rte_tm_error_set(error, EINVAL,
538                                                 RTE_TM_ERROR_TYPE_NODE_ID, NULL,
539                                                 "Not enough txqs configured\n");
540                                 goto out;
541                         }
542
543                         if (conf[node->id])
544                                 continue;
545
546                         LIST_FOREACH(temp_node, &priv->nodes, next) {
547                                 if (temp_node->id == node->id ||
548                                         temp_node->type == 0)
549                                         continue;
550                                 if (conf[temp_node->id])
551                                         continue;
552                                 if (node->priority == temp_node->priority) {
553                                         if (wfq_grp == 0) {
554                                                 prio_cfg.tc_sched[temp_node->id].mode =
555                                                                 DPNI_TX_SCHED_WEIGHTED_A;
556                                                 /* DPDK support lowest weight 1
557                                                  * and DPAA2 platform 100
558                                                  */
559                                                 prio_cfg.tc_sched[temp_node->id].delta_bandwidth =
560                                                                 temp_node->weight + 99;
561                                         } else if (wfq_grp == 1) {
562                                                 prio_cfg.tc_sched[temp_node->id].mode =
563                                                                 DPNI_TX_SCHED_WEIGHTED_B;
564                                                 prio_cfg.tc_sched[temp_node->id].delta_bandwidth =
565                                                                 temp_node->weight + 99;
566                                         } else {
567                                                 /*TODO: add one more check for
568                                                  * number of nodes in a group
569                                                  */
570                                                 ret = -rte_tm_error_set(error, EINVAL,
571                                                         RTE_TM_ERROR_TYPE_UNSPECIFIED, NULL,
572                                                         "Only 2 WFQ Groups are supported\n");
573                                                 goto out;
574                                         }
575                                         conf[temp_node->id] = 1;
576                                         is_wfq_grp = 1;
577                                 }
578                         }
579                         if (is_wfq_grp) {
580                                 if (wfq_grp == 0) {
581                                         prio_cfg.tc_sched[node->id].mode =
582                                                         DPNI_TX_SCHED_WEIGHTED_A;
583                                         prio_cfg.tc_sched[node->id].delta_bandwidth =
584                                                         node->weight + 99;
585                                         prio_cfg.prio_group_A = node->priority;
586                                 } else if (wfq_grp == 1) {
587                                         prio_cfg.tc_sched[node->id].mode =
588                                                         DPNI_TX_SCHED_WEIGHTED_B;
589                                         prio_cfg.tc_sched[node->id].delta_bandwidth =
590                                                         node->weight + 99;
591                                         prio_cfg.prio_group_B = node->priority;
592                                 }
593                                 wfq_grp++;
594                                 is_wfq_grp = 0;
595                         }
596                         conf[node->id] = 1;
597                 }
598                 if (wfq_grp)
599                         prio_cfg.separate_groups = 1;
600         }
601         ret = dpni_set_tx_priorities(dpni, 0, priv->token, &prio_cfg);
602         if (ret) {
603                 ret = -rte_tm_error_set(error, EINVAL,
604                                         RTE_TM_ERROR_TYPE_UNSPECIFIED, NULL,
605                                         "Scheduling Failed\n");
606                 goto out;
607         }
608
609         return 0;
610
611 out:
612         if (clear_on_fail) {
613                 dpaa2_tm_deinit(dev);
614                 dpaa2_tm_init(dev);
615         }
616
617         return ret;
618 }
619
620 const struct rte_tm_ops dpaa2_tm_ops = {
621         .node_type_get = dpaa2_node_type_get,
622         .capabilities_get = dpaa2_capabilities_get,
623         .level_capabilities_get = dpaa2_level_capabilities_get,
624         .node_capabilities_get = dpaa2_node_capabilities_get,
625         .shaper_profile_add = dpaa2_shaper_profile_add,
626         .shaper_profile_delete = dpaa2_shaper_profile_delete,
627         .node_add = dpaa2_node_add,
628         .node_delete = dpaa2_node_delete,
629         .hierarchy_commit = dpaa2_hierarchy_commit,
630 };