1
2
3
4
5
6
7#include <rte_malloc.h>
8
9#include <linux/ethtool.h>
10#include <linux/sockios.h>
11#include <net/if.h>
12#include <sys/ioctl.h>
13
14#include "mrvl_tm.h"
15
16
17#define MRVL_RATE_MIN (PP2_PPIO_MIN_CIR * 1000 / 8)
18
19
20#define MRVL_BURST_MIN (PP2_PPIO_MIN_CBS * 1000)
21
22
23#define MRVL_BURST_MAX 256000000
24
25
26#define MRVL_WEIGHT_MAX 255
27
28
29
30
31
32
33
34
35static int
36mrvl_get_max_rate(struct rte_eth_dev *dev, uint64_t *rate)
37{
38 struct ethtool_cmd edata;
39 struct ifreq req;
40 int ret, fd;
41
42 memset(&edata, 0, sizeof(edata));
43 memset(&req, 0, sizeof(req));
44 edata.cmd = ETHTOOL_GSET;
45 strcpy(req.ifr_name, dev->data->name);
46 req.ifr_data = (void *)&edata;
47
48 fd = socket(AF_INET, SOCK_DGRAM, 0);
49 if (fd == -1)
50 return -1;
51
52 ret = ioctl(fd, SIOCETHTOOL, &req);
53 if (ret == -1) {
54 close(fd);
55 return -1;
56 }
57
58 close(fd);
59
60 *rate = (uint64_t)ethtool_cmd_speed(&edata) * 1000 * 1000 / 8;
61
62 return 0;
63}
64
65
66
67
68
69
70
71int
72mrvl_tm_init(struct rte_eth_dev *dev)
73{
74 struct mrvl_priv *priv = dev->data->dev_private;
75
76 LIST_INIT(&priv->shaper_profiles);
77 LIST_INIT(&priv->nodes);
78
79 if (priv->rate_max)
80 return 0;
81
82 return mrvl_get_max_rate(dev, &priv->rate_max);
83}
84
85
86
87
88
89
90void mrvl_tm_deinit(struct rte_eth_dev *dev)
91{
92 struct mrvl_priv *priv = dev->data->dev_private;
93 struct mrvl_tm_shaper_profile *profile =
94 LIST_FIRST(&priv->shaper_profiles);
95 struct mrvl_tm_node *node = LIST_FIRST(&priv->nodes);
96
97 while (profile) {
98 struct mrvl_tm_shaper_profile *next = LIST_NEXT(profile, next);
99
100 LIST_REMOVE(profile, next);
101 rte_free(profile);
102 profile = next;
103 }
104
105 while (node) {
106 struct mrvl_tm_node *next = LIST_NEXT(node, next);
107
108 LIST_REMOVE(node, next);
109 rte_free(node);
110 node = next;
111 }
112}
113
114
115
116
117
118
119
120
121static struct mrvl_tm_node *
122mrvl_node_from_id(struct mrvl_priv *priv, uint32_t node_id)
123{
124 struct mrvl_tm_node *node;
125
126 LIST_FOREACH(node, &priv->nodes, next)
127 if (node->id == node_id)
128 return node;
129
130 return NULL;
131}
132
133
134
135
136
137
138
139
140
141
142static int
143mrvl_node_type_get(struct rte_eth_dev *dev, uint32_t node_id, int *is_leaf,
144 struct rte_tm_error *error)
145{
146 struct mrvl_priv *priv = dev->data->dev_private;
147 struct mrvl_tm_node *node;
148
149 if (!priv->configured)
150 return -rte_tm_error_set(error, ENODEV,
151 RTE_TM_ERROR_TYPE_UNSPECIFIED,
152 NULL, "Port didn't configured\n");
153
154 if (!is_leaf)
155 return -rte_tm_error_set(error, EINVAL,
156 RTE_TM_ERROR_TYPE_UNSPECIFIED,
157 NULL, NULL);
158
159 node = mrvl_node_from_id(priv, node_id);
160 if (!node)
161 return -rte_tm_error_set(error, ENODEV,
162 RTE_TM_ERROR_TYPE_NODE_ID,
163 NULL, "Node id does not exist\n");
164
165 *is_leaf = node->type == MRVL_NODE_QUEUE ? 1 : 0;
166
167 return 0;
168}
169
170
171
172
173
174
175
176
177
178static int
179mrvl_capabilities_get(struct rte_eth_dev *dev,
180 struct rte_tm_capabilities *cap,
181 struct rte_tm_error *error)
182{
183 struct mrvl_priv *priv = dev->data->dev_private;
184
185 if (!priv->configured)
186 return -rte_tm_error_set(error, ENODEV,
187 RTE_TM_ERROR_TYPE_UNSPECIFIED,
188 NULL, "Port didn't configured\n");
189
190 if (!cap)
191 return -rte_tm_error_set(error, EINVAL,
192 RTE_TM_ERROR_TYPE_UNSPECIFIED,
193 NULL, "Capabilities are missing\n");
194
195 memset(cap, 0, sizeof(*cap));
196
197 cap->n_nodes_max = 1 + dev->data->nb_tx_queues;
198 cap->n_levels_max = 2;
199 cap->non_leaf_nodes_identical = 1;
200 cap->leaf_nodes_identical = 1;
201
202 cap->shaper_n_max = cap->n_nodes_max;
203 cap->shaper_private_n_max = cap->shaper_n_max;
204 cap->shaper_private_rate_min = MRVL_RATE_MIN;
205 cap->shaper_private_rate_max = priv->rate_max;
206 cap->shaper_private_packet_mode_supported = 0;
207 cap->shaper_private_byte_mode_supported = 1;
208
209 cap->sched_n_children_max = dev->data->nb_tx_queues;
210 cap->sched_sp_n_priorities_max = dev->data->nb_tx_queues;
211 cap->sched_wfq_n_children_per_group_max = dev->data->nb_tx_queues;
212 cap->sched_wfq_n_groups_max = 1;
213 cap->sched_wfq_weight_max = MRVL_WEIGHT_MAX;
214 cap->sched_wfq_packet_mode_supported = 0;
215 cap->sched_wfq_byte_mode_supported = 1;
216
217 cap->dynamic_update_mask = RTE_TM_UPDATE_NODE_SUSPEND_RESUME |
218 RTE_TM_UPDATE_NODE_STATS;
219 cap->stats_mask = RTE_TM_STATS_N_PKTS | RTE_TM_STATS_N_BYTES;
220
221 return 0;
222}
223
224
225
226
227
228
229
230
231
232
233static int
234mrvl_level_capabilities_get(struct rte_eth_dev *dev,
235 uint32_t level_id,
236 struct rte_tm_level_capabilities *cap,
237 struct rte_tm_error *error)
238{
239 struct mrvl_priv *priv = dev->data->dev_private;
240
241 if (!priv->configured)
242 return -rte_tm_error_set(error, ENODEV,
243 RTE_TM_ERROR_TYPE_UNSPECIFIED,
244 NULL, "Port didn't configured\n");
245
246 if (!cap)
247 return -rte_tm_error_set(error, EINVAL,
248 RTE_TM_ERROR_TYPE_UNSPECIFIED,
249 NULL, NULL);
250
251 memset(cap, 0, sizeof(*cap));
252
253 if (level_id != MRVL_NODE_PORT && level_id != MRVL_NODE_QUEUE)
254 return -rte_tm_error_set(error, EINVAL,
255 RTE_TM_ERROR_TYPE_LEVEL_ID,
256 NULL, "Wrong level id\n");
257
258 if (level_id == MRVL_NODE_PORT) {
259 cap->n_nodes_max = 1;
260 cap->n_nodes_nonleaf_max = 1;
261 cap->non_leaf_nodes_identical = 1;
262
263 cap->nonleaf.shaper_private_supported = 1;
264 cap->nonleaf.shaper_private_rate_min = MRVL_RATE_MIN;
265 cap->nonleaf.shaper_private_rate_max = priv->rate_max;
266 cap->nonleaf.shaper_private_packet_mode_supported = 0;
267 cap->nonleaf.shaper_private_byte_mode_supported = 1;
268
269 cap->nonleaf.sched_n_children_max = dev->data->nb_tx_queues;
270 cap->nonleaf.sched_sp_n_priorities_max = 1;
271 cap->nonleaf.sched_wfq_n_children_per_group_max =
272 dev->data->nb_tx_queues;
273 cap->nonleaf.sched_wfq_n_groups_max = 1;
274 cap->nonleaf.sched_wfq_weight_max = MRVL_WEIGHT_MAX;
275 cap->nonleaf.sched_wfq_packet_mode_supported = 0;
276 cap->nonleaf.sched_wfq_byte_mode_supported = 1;
277 cap->nonleaf.stats_mask = RTE_TM_STATS_N_PKTS |
278 RTE_TM_STATS_N_BYTES;
279 } else {
280 cap->n_nodes_max = dev->data->nb_tx_queues;
281 cap->n_nodes_leaf_max = dev->data->nb_tx_queues;
282 cap->leaf_nodes_identical = 1;
283
284 cap->leaf.shaper_private_supported = 1;
285 cap->leaf.shaper_private_rate_min = MRVL_RATE_MIN;
286 cap->leaf.shaper_private_rate_max = priv->rate_max;
287 cap->leaf.shaper_private_packet_mode_supported = 0;
288 cap->leaf.shaper_private_byte_mode_supported = 1;
289 cap->leaf.stats_mask = RTE_TM_STATS_N_PKTS;
290 }
291
292 return 0;
293}
294
295
296
297
298
299
300
301
302
303
304static int
305mrvl_node_capabilities_get(struct rte_eth_dev *dev, uint32_t node_id,
306 struct rte_tm_node_capabilities *cap,
307 struct rte_tm_error *error)
308{
309 struct mrvl_priv *priv = dev->data->dev_private;
310 struct mrvl_tm_node *node;
311
312 if (!priv->configured)
313 return -rte_tm_error_set(error, ENODEV,
314 RTE_TM_ERROR_TYPE_UNSPECIFIED,
315 NULL, "Port didn't configured\n");
316
317 if (!cap)
318 return -rte_tm_error_set(error, EINVAL,
319 RTE_TM_ERROR_TYPE_UNSPECIFIED,
320 NULL, NULL);
321
322 memset(cap, 0, sizeof(*cap));
323
324 node = mrvl_node_from_id(priv, node_id);
325 if (!node)
326 return -rte_tm_error_set(error, ENODEV,
327 RTE_TM_ERROR_TYPE_NODE_ID,
328 NULL, "Node id does not exist\n");
329
330 cap->shaper_private_supported = 1;
331 cap->shaper_private_rate_min = MRVL_RATE_MIN;
332 cap->shaper_private_rate_max = priv->rate_max;
333 cap->shaper_private_packet_mode_supported = 0;
334 cap->shaper_private_byte_mode_supported = 1;
335
336 if (node->type == MRVL_NODE_PORT) {
337 cap->nonleaf.sched_n_children_max = dev->data->nb_tx_queues;
338 cap->nonleaf.sched_sp_n_priorities_max = 1;
339 cap->nonleaf.sched_wfq_n_children_per_group_max =
340 dev->data->nb_tx_queues;
341 cap->nonleaf.sched_wfq_n_groups_max = 1;
342 cap->nonleaf.sched_wfq_weight_max = MRVL_WEIGHT_MAX;
343 cap->nonleaf.sched_wfq_packet_mode_supported = 0;
344 cap->nonleaf.sched_wfq_byte_mode_supported = 1;
345 cap->stats_mask = RTE_TM_STATS_N_PKTS | RTE_TM_STATS_N_BYTES;
346 } else {
347 cap->stats_mask = RTE_TM_STATS_N_PKTS;
348 }
349
350 return 0;
351}
352
353
354
355
356
357
358
359
360static struct mrvl_tm_shaper_profile *
361mrvl_shaper_profile_from_id(struct mrvl_priv *priv, uint32_t shaper_profile_id)
362{
363 struct mrvl_tm_shaper_profile *profile;
364
365 LIST_FOREACH(profile, &priv->shaper_profiles, next)
366 if (profile->id == shaper_profile_id)
367 return profile;
368
369 return NULL;
370}
371
372
373
374
375
376
377
378
379
380
381static int
382mrvl_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id,
383 struct rte_tm_shaper_params *params,
384 struct rte_tm_error *error)
385{
386 struct mrvl_priv *priv = dev->data->dev_private;
387 struct mrvl_tm_shaper_profile *profile;
388
389 if (!priv->configured)
390 return -rte_tm_error_set(error, ENODEV,
391 RTE_TM_ERROR_TYPE_UNSPECIFIED,
392 NULL, "Port didn't configured\n");
393
394 if (!params)
395 return -rte_tm_error_set(error, EINVAL,
396 RTE_TM_ERROR_TYPE_UNSPECIFIED,
397 NULL, NULL);
398
399 if (params->committed.rate)
400 return -rte_tm_error_set(error, EINVAL,
401 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_RATE,
402 NULL, "Committed rate not supported\n");
403
404 if (params->committed.size)
405 return -rte_tm_error_set(error, EINVAL,
406 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_SIZE,
407 NULL, "Committed bucket size not supported\n");
408
409 if (params->peak.rate < MRVL_RATE_MIN ||
410 params->peak.rate > priv->rate_max)
411 return -rte_tm_error_set(error, EINVAL,
412 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE,
413 NULL, "Peak rate is out of range\n");
414
415 if (params->peak.size < MRVL_BURST_MIN ||
416 params->peak.size > MRVL_BURST_MAX)
417 return -rte_tm_error_set(error, EINVAL,
418 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE,
419 NULL, "Peak size is out of range\n");
420
421 if (shaper_profile_id == RTE_TM_SHAPER_PROFILE_ID_NONE)
422 return -rte_tm_error_set(error, EINVAL,
423 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
424 NULL, "Wrong shaper profile id\n");
425
426 profile = mrvl_shaper_profile_from_id(priv, shaper_profile_id);
427 if (profile)
428 return -rte_tm_error_set(error, EEXIST,
429 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
430 NULL, "Profile id already exists\n");
431
432 profile = rte_zmalloc_socket(NULL, sizeof(*profile), 0,
433 rte_socket_id());
434 if (!profile)
435 return -rte_tm_error_set(error, ENOMEM,
436 RTE_TM_ERROR_TYPE_UNSPECIFIED,
437 NULL, NULL);
438
439 profile->id = shaper_profile_id;
440 rte_memcpy(&profile->params, params, sizeof(profile->params));
441
442 LIST_INSERT_HEAD(&priv->shaper_profiles, profile, next);
443
444 return 0;
445}
446
447
448
449
450
451
452
453
454
455static int
456mrvl_shaper_profile_delete(struct rte_eth_dev *dev, uint32_t shaper_profile_id,
457 struct rte_tm_error *error)
458{
459 struct mrvl_priv *priv = dev->data->dev_private;
460 struct mrvl_tm_shaper_profile *profile;
461
462 if (!priv->configured)
463 return -rte_tm_error_set(error, ENODEV,
464 RTE_TM_ERROR_TYPE_UNSPECIFIED,
465 NULL, "Port didn't configured\n");
466
467 profile = mrvl_shaper_profile_from_id(priv, shaper_profile_id);
468 if (!profile)
469 return -rte_tm_error_set(error, ENODEV,
470 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
471 NULL, "Profile id does not exist\n");
472
473 if (profile->refcnt)
474 return -rte_tm_error_set(error, EPERM,
475 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
476 NULL, "Profile is used\n");
477
478 LIST_REMOVE(profile, next);
479 rte_free(profile);
480
481 return 0;
482}
483
484
485
486
487
488
489
490
491
492
493
494
495
496static int
497mrvl_node_check_params(struct rte_eth_dev *dev, uint32_t node_id,
498 uint32_t priority, uint32_t weight, uint32_t level_id,
499 struct rte_tm_node_params *params,
500 struct rte_tm_error *error)
501{
502 if (node_id == RTE_TM_NODE_ID_NULL)
503 return -rte_tm_error_set(error, EINVAL, RTE_TM_NODE_ID_NULL,
504 NULL, "Node id is invalid\n");
505
506 if (priority)
507 return -rte_tm_error_set(error, EINVAL,
508 RTE_TM_ERROR_TYPE_NODE_PRIORITY,
509 NULL, "Priority should be 0\n");
510
511 if (weight > MRVL_WEIGHT_MAX)
512 return -rte_tm_error_set(error, EINVAL,
513 RTE_TM_ERROR_TYPE_NODE_WEIGHT,
514 NULL, "Weight is out of range\n");
515
516 if (level_id != MRVL_NODE_PORT && level_id != MRVL_NODE_QUEUE)
517 return -rte_tm_error_set(error, EINVAL,
518 RTE_TM_ERROR_TYPE_LEVEL_ID,
519 NULL, "Wrong level id\n");
520
521 if (!params)
522 return -rte_tm_error_set(error, EINVAL,
523 RTE_TM_ERROR_TYPE_UNSPECIFIED,
524 NULL, NULL);
525
526 if (params->shared_shaper_id)
527 return -rte_tm_error_set(error, EINVAL,
528 RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_SHAPER_ID,
529 NULL, "Shared shaper is not supported\n");
530
531 if (params->n_shared_shapers)
532 return -rte_tm_error_set(error, EINVAL,
533 RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS,
534 NULL, "Shared shaper is not supported\n");
535
536
537 if (node_id >= dev->data->nb_tx_queues) {
538 if (params->nonleaf.wfq_weight_mode)
539 return -rte_tm_error_set(error, EINVAL,
540 RTE_TM_ERROR_TYPE_NODE_PARAMS_WFQ_WEIGHT_MODE,
541 NULL, "WFQ is not supported\n");
542
543 if (params->nonleaf.n_sp_priorities != 1)
544 return -rte_tm_error_set(error, EINVAL,
545 RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SP_PRIORITIES,
546 NULL, "SP is not supported\n");
547
548 if (params->stats_mask & ~(RTE_TM_STATS_N_PKTS |
549 RTE_TM_STATS_N_BYTES))
550 return -rte_tm_error_set(error, EINVAL,
551 RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS,
552 NULL,
553 "Requested port stats are not supported\n");
554
555 return 0;
556 }
557
558
559 if (params->leaf.cman)
560 return -rte_tm_error_set(error, EINVAL,
561 RTE_TM_ERROR_TYPE_NODE_PARAMS_CMAN,
562 NULL,
563 "Congestion mngmt is not supported\n");
564
565 if (params->leaf.wred.wred_profile_id)
566 return -rte_tm_error_set(error, EINVAL,
567 RTE_TM_ERROR_TYPE_NODE_PARAMS_WRED_PROFILE_ID,
568 NULL, "WRED is not supported\n");
569
570 if (params->leaf.wred.shared_wred_context_id)
571 return -rte_tm_error_set(error, EINVAL,
572 RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_WRED_CONTEXT_ID,
573 NULL, "WRED is not supported\n");
574
575 if (params->leaf.wred.n_shared_wred_contexts)
576 return -rte_tm_error_set(error, EINVAL,
577 RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_WRED_CONTEXTS,
578 NULL, "WRED is not supported\n");
579
580 if (params->stats_mask & ~RTE_TM_STATS_N_PKTS)
581 return -rte_tm_error_set(error, EINVAL,
582 RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS,
583 NULL,
584 "Requested txq stats are not supported\n");
585
586 return 0;
587}
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602static int
603mrvl_node_add(struct rte_eth_dev *dev, uint32_t node_id,
604 uint32_t parent_node_id, uint32_t priority, uint32_t weight,
605 uint32_t level_id, struct rte_tm_node_params *params,
606 struct rte_tm_error *error)
607{
608 struct mrvl_priv *priv = dev->data->dev_private;
609 struct mrvl_tm_shaper_profile *profile = NULL;
610 struct mrvl_tm_node *node, *parent = NULL;
611 int ret;
612
613 if (!priv->configured)
614 return -rte_tm_error_set(error, ENODEV,
615 RTE_TM_ERROR_TYPE_UNSPECIFIED,
616 NULL, "Port didn't configured\n");
617
618 if (priv->ppio)
619 return -rte_tm_error_set(error, EPERM,
620 RTE_TM_ERROR_TYPE_UNSPECIFIED,
621 NULL, "Port is already started\n");
622
623 ret = mrvl_node_check_params(dev, node_id, priority, weight, level_id,
624 params, error);
625 if (ret)
626 return ret;
627
628 if (params->shaper_profile_id != RTE_TM_SHAPER_PROFILE_ID_NONE) {
629 profile = mrvl_shaper_profile_from_id(priv,
630 params->shaper_profile_id);
631 if (!profile)
632 return -rte_tm_error_set(error, ENODEV,
633 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
634 NULL, "Shaper id does not exist\n");
635 }
636
637 if (parent_node_id == RTE_TM_NODE_ID_NULL) {
638 LIST_FOREACH(node, &priv->nodes, next) {
639 if (node->type != MRVL_NODE_PORT)
640 continue;
641
642 return -rte_tm_error_set(error, EINVAL,
643 RTE_TM_ERROR_TYPE_UNSPECIFIED,
644 NULL, "Root node exists\n");
645 }
646 } else {
647 parent = mrvl_node_from_id(priv, parent_node_id);
648 if (!parent)
649 return -rte_tm_error_set(error, EINVAL,
650 RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID,
651 NULL, "Node id does not exist\n");
652 }
653
654 node = mrvl_node_from_id(priv, node_id);
655 if (node)
656 return -rte_tm_error_set(error, ENODEV,
657 RTE_TM_ERROR_TYPE_NODE_ID,
658 NULL, "Node id already exists\n");
659
660 node = rte_zmalloc_socket(NULL, sizeof(*node), 0, rte_socket_id());
661 if (!node)
662 return -rte_tm_error_set(error, ENOMEM,
663 RTE_TM_ERROR_TYPE_UNSPECIFIED,
664 NULL, NULL);
665
666 node->id = node_id;
667 node->type = parent_node_id == RTE_TM_NODE_ID_NULL ? MRVL_NODE_PORT :
668 MRVL_NODE_QUEUE;
669
670 if (parent) {
671 node->parent = parent;
672 parent->refcnt++;
673 }
674
675 if (profile) {
676 node->profile = profile;
677 profile->refcnt++;
678 }
679
680 node->weight = weight;
681 node->stats_mask = params->stats_mask;
682
683 LIST_INSERT_HEAD(&priv->nodes, node, next);
684
685 return 0;
686}
687
688
689
690
691
692
693
694
695
696static int
697mrvl_node_delete(struct rte_eth_dev *dev, uint32_t node_id,
698 struct rte_tm_error *error)
699{
700 struct mrvl_priv *priv = dev->data->dev_private;
701 struct mrvl_tm_node *node;
702
703 if (!priv->configured)
704 return -rte_tm_error_set(error, ENODEV,
705 RTE_TM_ERROR_TYPE_UNSPECIFIED,
706 NULL, "Port didn't configured\n");
707
708 if (priv->ppio) {
709 return -rte_tm_error_set(error, EPERM,
710 RTE_TM_ERROR_TYPE_UNSPECIFIED,
711 NULL, "Port is already started\n");
712 }
713
714 node = mrvl_node_from_id(priv, node_id);
715 if (!node)
716 return -rte_tm_error_set(error, ENODEV,
717 RTE_TM_ERROR_TYPE_NODE_ID,
718 NULL, "Node id does not exist\n");
719
720 if (node->refcnt)
721 return -rte_tm_error_set(error, EPERM,
722 RTE_TM_ERROR_TYPE_NODE_ID,
723 NULL, "Node id is used\n");
724
725 if (node->parent)
726 node->parent->refcnt--;
727
728 if (node->profile)
729 node->profile->refcnt--;
730
731 LIST_REMOVE(node, next);
732 rte_free(node);
733
734 return 0;
735}
736
737
738
739
740
741
742
743
744static int mrvl_node_suspend_one(struct rte_eth_dev *dev, uint32_t node_id,
745 struct rte_tm_error *error)
746{
747 int ret = dev->dev_ops->tx_queue_stop(dev, node_id);
748 if (ret)
749 return -rte_tm_error_set(error, ret,
750 RTE_TM_ERROR_TYPE_UNSPECIFIED,
751 NULL, "Failed to suspend a txq\n");
752
753 return 0;
754}
755
756
757
758
759
760
761
762
763
764static int
765mrvl_node_suspend(struct rte_eth_dev *dev, uint32_t node_id,
766 struct rte_tm_error *error)
767{
768 struct mrvl_priv *priv = dev->data->dev_private;
769 struct mrvl_tm_node *node, *tmp;
770 int ret;
771
772 if (!priv->configured)
773 return -rte_tm_error_set(error, ENODEV,
774 RTE_TM_ERROR_TYPE_UNSPECIFIED,
775 NULL, "Port didn't configured\n");
776
777 node = mrvl_node_from_id(priv, node_id);
778 if (!node)
779 return -rte_tm_error_set(error, ENODEV,
780 RTE_TM_ERROR_TYPE_NODE_ID,
781 NULL, "Node id does not exist\n");
782
783 if (!node->parent) {
784 LIST_FOREACH(tmp, &priv->nodes, next) {
785 if (!tmp->parent)
786 continue;
787
788 if (node != tmp->parent)
789 continue;
790
791 ret = mrvl_node_suspend_one(dev, tmp->id, error);
792 if (ret)
793 return ret;
794 }
795
796 return 0;
797 }
798
799 return mrvl_node_suspend_one(dev, node_id, error);
800}
801
802
803
804
805
806
807
808
809
810static int
811mrvl_node_resume(struct rte_eth_dev *dev, uint32_t node_id,
812 struct rte_tm_error *error)
813{
814 struct mrvl_priv *priv = dev->data->dev_private;
815 struct mrvl_tm_node *node;
816 int ret;
817
818 if (!priv->configured)
819 return -rte_tm_error_set(error, ENODEV,
820 RTE_TM_ERROR_TYPE_UNSPECIFIED,
821 NULL, "Port didn't configured\n");
822
823 node = mrvl_node_from_id(priv, node_id);
824 if (!node)
825 return -rte_tm_error_set(error, ENODEV,
826 RTE_TM_ERROR_TYPE_NODE_ID,
827 NULL, "Node id does not exist\n");
828
829
830 if (!node->parent)
831 return -rte_tm_error_set(error, EPERM,
832 RTE_TM_ERROR_TYPE_NODE_ID,
833 NULL, "Cannot suspend a port\n");
834
835 ret = dev->dev_ops->tx_queue_start(dev, node_id);
836 if (ret)
837 return -rte_tm_error_set(error, ret,
838 RTE_TM_ERROR_TYPE_UNSPECIFIED,
839 NULL, "Failed to resume a txq\n");
840 return 0;
841}
842
843
844
845
846
847
848
849
850
851static int
852mrvl_hierarchy_commit(struct rte_eth_dev *dev, int clear_on_fail,
853 struct rte_tm_error *error)
854{
855 struct mrvl_priv *priv = dev->data->dev_private;
856 struct mrvl_tm_node *node;
857 int ret;
858
859 if (!priv->configured)
860 return -rte_tm_error_set(error, ENODEV,
861 RTE_TM_ERROR_TYPE_UNSPECIFIED,
862 NULL, "Port didn't configured\n");
863
864 if (priv->ppio) {
865 ret = -rte_tm_error_set(error, EPERM,
866 RTE_TM_ERROR_TYPE_UNSPECIFIED,
867 NULL, "Port is already started\n");
868 goto out;
869 }
870
871 LIST_FOREACH(node, &priv->nodes, next) {
872 struct pp2_ppio_outq_params *p;
873
874 if (node->type == MRVL_NODE_PORT) {
875 if (!node->profile)
876 continue;
877
878 priv->ppio_params.rate_limit_enable = 1;
879 priv->ppio_params.rate_limit_params.cir =
880 node->profile->params.peak.rate * 8 / 1000;
881 priv->ppio_params.rate_limit_params.cbs =
882 node->profile->params.peak.size / 1000;
883
884 MRVL_LOG(INFO,
885 "Port rate limit overrides txqs rate limit");
886
887 continue;
888 }
889
890 if (node->id >= dev->data->nb_tx_queues) {
891 ret = -rte_tm_error_set(error, EINVAL,
892 RTE_TM_ERROR_TYPE_NODE_ID, NULL,
893 "Not enough txqs are configured\n");
894 goto out;
895 }
896
897 p = &priv->ppio_params.outqs_params.outqs_params[node->id];
898
899 if (node->weight) {
900 p->sched_mode = PP2_PPIO_SCHED_M_WRR;
901 p->weight = node->weight;
902 } else {
903 p->sched_mode = PP2_PPIO_SCHED_M_SP;
904 p->weight = 0;
905 }
906
907 if (node->profile) {
908 p->rate_limit_enable = 1;
909
910 p->rate_limit_params.cir =
911 node->profile->params.peak.rate * 8 / 1000;
912
913 p->rate_limit_params.cbs =
914 node->profile->params.peak.size / 1000;
915 } else {
916 p->rate_limit_enable = 0;
917 p->rate_limit_params.cir = 0;
918 p->rate_limit_params.cbs = 0;
919 }
920 }
921
922
923 if (LIST_EMPTY(&priv->nodes)) {
924 int i;
925
926 for (i = 0; i < priv->ppio_params.outqs_params.num_outqs; i++) {
927 struct pp2_ppio_outq_params *p =
928 &priv->ppio_params.outqs_params.outqs_params[i];
929
930 p->sched_mode = PP2_PPIO_SCHED_M_WRR;
931 p->weight = 0;
932 p->rate_limit_enable = 0;
933 p->rate_limit_params.cir = 0;
934 p->rate_limit_params.cbs = 0;
935 }
936 }
937
938 return 0;
939out:
940 if (clear_on_fail) {
941 mrvl_tm_deinit(dev);
942 mrvl_tm_init(dev);
943 }
944
945 return ret;
946}
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961static int
962mrvl_node_stats_read(struct rte_eth_dev *dev, uint32_t node_id,
963 struct rte_tm_node_stats *stats, uint64_t *stats_mask,
964 int clear, struct rte_tm_error *error)
965{
966 struct mrvl_priv *priv = dev->data->dev_private;
967 struct mrvl_tm_node *node;
968 int ret;
969
970 if (!priv->configured)
971 return -rte_tm_error_set(error, ENODEV,
972 RTE_TM_ERROR_TYPE_UNSPECIFIED,
973 NULL, "Port didn't configured\n");
974
975 if (!priv->ppio) {
976 return -rte_tm_error_set(error, EPERM,
977 RTE_TM_ERROR_TYPE_UNSPECIFIED,
978 NULL, "Port is not started\n");
979 }
980
981 node = mrvl_node_from_id(priv, node_id);
982 if (!node)
983 return -rte_tm_error_set(error, ENODEV,
984 RTE_TM_ERROR_TYPE_NODE_ID,
985 NULL, "Node id does not exist\n");
986
987 if (stats_mask)
988 *stats_mask = node->stats_mask;
989
990 if (!stats)
991 return 0;
992
993 memset(stats, 0, sizeof(*stats));
994
995 if (!node->parent) {
996 struct pp2_ppio_statistics s;
997
998 memset(&s, 0, sizeof(s));
999 ret = pp2_ppio_get_statistics(priv->ppio, &s, clear);
1000 if (ret)
1001 return -rte_tm_error_set(error, -ret,
1002 RTE_TM_ERROR_TYPE_UNSPECIFIED, NULL,
1003 "Failed to read port statistics\n");
1004
1005 if (node->stats_mask & RTE_TM_STATS_N_PKTS)
1006 stats->n_pkts = s.tx_packets;
1007
1008 if (node->stats_mask & RTE_TM_STATS_N_BYTES)
1009 stats->n_bytes = s.tx_bytes;
1010 } else {
1011 struct pp2_ppio_outq_statistics s;
1012
1013 memset(&s, 0, sizeof(s));
1014 ret = pp2_ppio_outq_get_statistics(priv->ppio, node_id, &s,
1015 clear);
1016 if (ret)
1017 return -rte_tm_error_set(error, -ret,
1018 RTE_TM_ERROR_TYPE_UNSPECIFIED, NULL,
1019 "Failed to read txq statistics\n");
1020
1021 if (node->stats_mask & RTE_TM_STATS_N_PKTS)
1022 stats->n_pkts = s.deq_desc;
1023 }
1024
1025 return 0;
1026}
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037static int
1038mrvl_node_stats_update(struct rte_eth_dev *dev, uint32_t node_id,
1039 uint64_t stats_mask, struct rte_tm_error *error)
1040{
1041 struct mrvl_priv *priv = dev->data->dev_private;
1042 struct mrvl_tm_node *node;
1043
1044 if (!priv->configured)
1045 return -rte_tm_error_set(error, ENODEV,
1046 RTE_TM_ERROR_TYPE_UNSPECIFIED,
1047 NULL, "Port didn't configured\n");
1048
1049 node = mrvl_node_from_id(priv, node_id);
1050 if (!node)
1051 return -rte_tm_error_set(error, ENODEV,
1052 RTE_TM_ERROR_TYPE_NODE_ID,
1053 NULL, "Node id does not exist\n");
1054
1055 if (!node->parent) {
1056 if (stats_mask & ~(RTE_TM_STATS_N_PKTS | RTE_TM_STATS_N_BYTES))
1057 return -rte_tm_error_set(error, EINVAL,
1058 RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS,
1059 NULL,
1060 "Requested port stats are not supported\n");
1061 } else {
1062 if (stats_mask & ~RTE_TM_STATS_N_PKTS)
1063 return -rte_tm_error_set(error, EINVAL,
1064 RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS,
1065 NULL,
1066 "Requested txq stats are not supported\n");
1067 }
1068
1069 node->stats_mask = stats_mask;
1070
1071 return 0;
1072}
1073
1074const struct rte_tm_ops mrvl_tm_ops = {
1075 .node_type_get = mrvl_node_type_get,
1076 .capabilities_get = mrvl_capabilities_get,
1077 .level_capabilities_get = mrvl_level_capabilities_get,
1078 .node_capabilities_get = mrvl_node_capabilities_get,
1079 .shaper_profile_add = mrvl_shaper_profile_add,
1080 .shaper_profile_delete = mrvl_shaper_profile_delete,
1081 .node_add = mrvl_node_add,
1082 .node_delete = mrvl_node_delete,
1083 .node_suspend = mrvl_node_suspend,
1084 .node_resume = mrvl_node_resume,
1085 .hierarchy_commit = mrvl_hierarchy_commit,
1086 .node_stats_update = mrvl_node_stats_update,
1087 .node_stats_read = mrvl_node_stats_read,
1088};
1089