1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018 Marvell International Ltd.
3 * Copyright(c) 2018 Semihalf.
7 #include <rte_malloc.h>
9 #include <linux/ethtool.h>
10 #include <linux/sockios.h>
12 #include <sys/ioctl.h>
16 /** Minimum rate value in Bytes/s */
17 #define MRVL_RATE_MIN (PP2_PPIO_MIN_CIR * 1000 / 8)
19 /** Minimum burst size in Bytes */
20 #define MRVL_BURST_MIN (PP2_PPIO_MIN_CBS * 1000)
22 /** Maximum burst size in Bytes */
23 #define MRVL_BURST_MAX 256000000
25 /** Maximum WRR weight */
26 #define MRVL_WEIGHT_MAX 255
29 * Get maximum port rate in Bytes/s.
31 * @param dev Pointer to the device.
32 * @param rate Pointer to the rate.
33 * @returns 0 on success, negative value otherwise.
36 mrvl_get_max_rate(struct rte_eth_dev *dev, uint64_t *rate)
38 struct ethtool_cmd edata;
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;
48 fd = socket(AF_INET, SOCK_DGRAM, 0);
52 ret = ioctl(fd, SIOCETHTOOL, &req);
60 *rate = ethtool_cmd_speed(&edata) * 1000 * 1000 / 8;
66 * Initialize traffic manager related data.
68 * @param dev Pointer to the device.
69 * @returns 0 on success, failure otherwise.
72 mrvl_tm_init(struct rte_eth_dev *dev)
74 struct mrvl_priv *priv = dev->data->dev_private;
76 LIST_INIT(&priv->shaper_profiles);
77 LIST_INIT(&priv->nodes);
82 return mrvl_get_max_rate(dev, &priv->rate_max);
86 * Cleanup traffic manager related data.
88 * @param dev Pointer to the device.
90 void mrvl_tm_deinit(struct rte_eth_dev *dev)
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);
98 struct mrvl_tm_shaper_profile *next = LIST_NEXT(profile, next);
100 LIST_REMOVE(profile, next);
106 struct mrvl_tm_node *next = LIST_NEXT(node, next);
108 LIST_REMOVE(node, next);
115 * Get node using its id.
117 * @param priv Pointer to the port's private data.
118 * @param node_id Id used by this node.
119 * @returns Pointer to the node if exists, NULL otherwise.
121 static struct mrvl_tm_node *
122 mrvl_node_from_id(struct mrvl_priv *priv, uint32_t node_id)
124 struct mrvl_tm_node *node;
126 LIST_FOREACH(node, &priv->nodes, next)
127 if (node->id == node_id)
134 * Check whether node is leaf or root.
136 * @param dev Pointer to the device.
137 * @param node_id Id used by this node.
138 * @param is_leaf Pointer to flag indicating whether node is a leaf.
139 * @param error Pointer to the error.
140 * @returns 0 on success, negative value otherwise.
143 mrvl_node_type_get(struct rte_eth_dev *dev, uint32_t node_id, int *is_leaf,
144 struct rte_tm_error *error)
146 struct mrvl_priv *priv = dev->data->dev_private;
147 struct mrvl_tm_node *node;
150 return -rte_tm_error_set(error, EINVAL,
151 RTE_TM_ERROR_TYPE_UNSPECIFIED,
154 node = mrvl_node_from_id(priv, node_id);
156 return -rte_tm_error_set(error, ENODEV,
157 RTE_TM_ERROR_TYPE_NODE_ID,
158 NULL, "Node id does not exist\n");
160 *is_leaf = node->type == MRVL_NODE_QUEUE ? 1 : 0;
166 * Get traffic manager capabilities.
168 * @param dev Pointer to the device (unused).
169 * @param cap Pointer to the capabilities.
170 * @param error Pointer to the error.
171 * @returns 0 on success, negative value otherwise.
174 mrvl_capabilities_get(struct rte_eth_dev *dev,
175 struct rte_tm_capabilities *cap,
176 struct rte_tm_error *error)
178 struct mrvl_priv *priv = dev->data->dev_private;
181 return -rte_tm_error_set(error, EINVAL,
182 RTE_TM_ERROR_TYPE_UNSPECIFIED,
183 NULL, "Capabilities are missing\n");
185 memset(cap, 0, sizeof(*cap));
187 cap->n_nodes_max = 1 + dev->data->nb_tx_queues; /* port + txqs number */
188 cap->n_levels_max = 2; /* port level + txqs level */
189 cap->non_leaf_nodes_identical = 1;
190 cap->leaf_nodes_identical = 1;
192 cap->shaper_n_max = cap->n_nodes_max;
193 cap->shaper_private_n_max = cap->shaper_n_max;
194 cap->shaper_private_rate_min = MRVL_RATE_MIN;
195 cap->shaper_private_rate_max = priv->rate_max;
196 cap->shaper_private_packet_mode_supported = 0;
197 cap->shaper_private_byte_mode_supported = 1;
199 cap->sched_n_children_max = dev->data->nb_tx_queues;
200 cap->sched_sp_n_priorities_max = dev->data->nb_tx_queues;
201 cap->sched_wfq_n_children_per_group_max = dev->data->nb_tx_queues;
202 cap->sched_wfq_n_groups_max = 1;
203 cap->sched_wfq_weight_max = MRVL_WEIGHT_MAX;
204 cap->sched_wfq_packet_mode_supported = 0;
205 cap->sched_wfq_byte_mode_supported = 1;
207 cap->dynamic_update_mask = RTE_TM_UPDATE_NODE_SUSPEND_RESUME |
208 RTE_TM_UPDATE_NODE_STATS;
209 cap->stats_mask = RTE_TM_STATS_N_PKTS | RTE_TM_STATS_N_BYTES;
215 * Get traffic manager hierarchy level capabilities.
217 * @param dev Pointer to the device.
218 * @param level_id Id of the level.
219 * @param cap Pointer to the level capabilities.
220 * @param error Pointer to the error.
221 * @returns 0 on success, negative value otherwise.
224 mrvl_level_capabilities_get(struct rte_eth_dev *dev,
226 struct rte_tm_level_capabilities *cap,
227 struct rte_tm_error *error)
229 struct mrvl_priv *priv = dev->data->dev_private;
232 return -rte_tm_error_set(error, EINVAL,
233 RTE_TM_ERROR_TYPE_UNSPECIFIED,
236 memset(cap, 0, sizeof(*cap));
238 if (level_id != MRVL_NODE_PORT && level_id != MRVL_NODE_QUEUE)
239 return -rte_tm_error_set(error, EINVAL,
240 RTE_TM_ERROR_TYPE_LEVEL_ID,
241 NULL, "Wrong level id\n");
243 if (level_id == MRVL_NODE_PORT) {
244 cap->n_nodes_max = 1;
245 cap->n_nodes_nonleaf_max = 1;
246 cap->non_leaf_nodes_identical = 1;
248 cap->nonleaf.shaper_private_supported = 1;
249 cap->nonleaf.shaper_private_rate_min = MRVL_RATE_MIN;
250 cap->nonleaf.shaper_private_rate_max = priv->rate_max;
251 cap->nonleaf.shaper_private_packet_mode_supported = 0;
252 cap->nonleaf.shaper_private_byte_mode_supported = 1;
254 cap->nonleaf.sched_n_children_max = dev->data->nb_tx_queues;
255 cap->nonleaf.sched_sp_n_priorities_max = 1;
256 cap->nonleaf.sched_wfq_n_children_per_group_max =
257 dev->data->nb_tx_queues;
258 cap->nonleaf.sched_wfq_n_groups_max = 1;
259 cap->nonleaf.sched_wfq_weight_max = MRVL_WEIGHT_MAX;
260 cap->nonleaf.sched_wfq_packet_mode_supported = 0;
261 cap->nonleaf.sched_wfq_byte_mode_supported = 1;
262 cap->nonleaf.stats_mask = RTE_TM_STATS_N_PKTS |
263 RTE_TM_STATS_N_BYTES;
264 } else { /* level_id == MRVL_NODE_QUEUE */
265 cap->n_nodes_max = dev->data->nb_tx_queues;
266 cap->n_nodes_leaf_max = dev->data->nb_tx_queues;
267 cap->leaf_nodes_identical = 1;
269 cap->leaf.shaper_private_supported = 1;
270 cap->leaf.shaper_private_rate_min = MRVL_RATE_MIN;
271 cap->leaf.shaper_private_rate_max = priv->rate_max;
272 cap->leaf.shaper_private_packet_mode_supported = 0;
273 cap->leaf.shaper_private_byte_mode_supported = 1;
274 cap->leaf.stats_mask = RTE_TM_STATS_N_PKTS;
281 * Get node capabilities.
283 * @param dev Pointer to the device.
284 * @param node_id Id of the node.
285 * @param cap Pointer to the capabilities.
286 * @param error Pointer to the error.
287 * @returns 0 on success, negative value otherwise.
290 mrvl_node_capabilities_get(struct rte_eth_dev *dev, uint32_t node_id,
291 struct rte_tm_node_capabilities *cap,
292 struct rte_tm_error *error)
294 struct mrvl_priv *priv = dev->data->dev_private;
295 struct mrvl_tm_node *node;
298 return -rte_tm_error_set(error, EINVAL,
299 RTE_TM_ERROR_TYPE_UNSPECIFIED,
302 memset(cap, 0, sizeof(*cap));
304 node = mrvl_node_from_id(priv, node_id);
306 return -rte_tm_error_set(error, ENODEV,
307 RTE_TM_ERROR_TYPE_NODE_ID,
308 NULL, "Node id does not exist\n");
310 cap->shaper_private_supported = 1;
311 cap->shaper_private_rate_min = MRVL_RATE_MIN;
312 cap->shaper_private_rate_max = priv->rate_max;
313 cap->shaper_private_packet_mode_supported = 0;
314 cap->shaper_private_byte_mode_supported = 1;
316 if (node->type == MRVL_NODE_PORT) {
317 cap->nonleaf.sched_n_children_max = dev->data->nb_tx_queues;
318 cap->nonleaf.sched_sp_n_priorities_max = 1;
319 cap->nonleaf.sched_wfq_n_children_per_group_max =
320 dev->data->nb_tx_queues;
321 cap->nonleaf.sched_wfq_n_groups_max = 1;
322 cap->nonleaf.sched_wfq_weight_max = MRVL_WEIGHT_MAX;
323 cap->nonleaf.sched_wfq_packet_mode_supported = 0;
324 cap->nonleaf.sched_wfq_byte_mode_supported = 1;
325 cap->stats_mask = RTE_TM_STATS_N_PKTS | RTE_TM_STATS_N_BYTES;
327 cap->stats_mask = RTE_TM_STATS_N_PKTS;
334 * Get shaper profile using its id.
336 * @param priv Pointer to the port's private data.
337 * @param shaper_profile_id Id used by the shaper.
338 * @returns Pointer to the shaper profile if exists, NULL otherwise.
340 static struct mrvl_tm_shaper_profile *
341 mrvl_shaper_profile_from_id(struct mrvl_priv *priv, uint32_t shaper_profile_id)
343 struct mrvl_tm_shaper_profile *profile;
345 LIST_FOREACH(profile, &priv->shaper_profiles, next)
346 if (profile->id == shaper_profile_id)
353 * Add a new shaper profile.
355 * @param dev Pointer to the device.
356 * @param shaper_profile_id Id of the new profile.
357 * @param params Pointer to the shaper profile parameters.
358 * @param error Pointer to the error.
359 * @returns 0 on success, negative value otherwise.
362 mrvl_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id,
363 struct rte_tm_shaper_params *params,
364 struct rte_tm_error *error)
366 struct mrvl_priv *priv = dev->data->dev_private;
367 struct mrvl_tm_shaper_profile *profile;
370 return -rte_tm_error_set(error, EINVAL,
371 RTE_TM_ERROR_TYPE_UNSPECIFIED,
374 if (params->committed.rate)
375 return -rte_tm_error_set(error, EINVAL,
376 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_RATE,
377 NULL, "Committed rate not supported\n");
379 if (params->committed.size)
380 return -rte_tm_error_set(error, EINVAL,
381 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_SIZE,
382 NULL, "Committed bucket size not supported\n");
384 if (params->peak.rate < MRVL_RATE_MIN ||
385 params->peak.rate > priv->rate_max)
386 return -rte_tm_error_set(error, EINVAL,
387 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE,
388 NULL, "Peak rate is out of range\n");
390 if (params->peak.size < MRVL_BURST_MIN ||
391 params->peak.size > MRVL_BURST_MAX)
392 return -rte_tm_error_set(error, EINVAL,
393 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE,
394 NULL, "Peak size is out of range\n");
396 if (shaper_profile_id == RTE_TM_SHAPER_PROFILE_ID_NONE)
397 return -rte_tm_error_set(error, EINVAL,
398 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
399 NULL, "Wrong shaper profile id\n");
401 profile = mrvl_shaper_profile_from_id(priv, shaper_profile_id);
403 return -rte_tm_error_set(error, EEXIST,
404 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
405 NULL, "Profile id already exists\n");
407 profile = rte_zmalloc_socket(NULL, sizeof(*profile), 0,
410 return -rte_tm_error_set(error, ENOMEM,
411 RTE_TM_ERROR_TYPE_UNSPECIFIED,
414 profile->id = shaper_profile_id;
415 rte_memcpy(&profile->params, params, sizeof(profile->params));
417 LIST_INSERT_HEAD(&priv->shaper_profiles, profile, next);
423 * Remove a shaper profile.
425 * @param dev Pointer to the device.
426 * @param shaper_profile_id Id of the shaper profile.
427 * @param error Pointer to the error.
428 * @returns 0 on success, negative value otherwise.
431 mrvl_shaper_profile_delete(struct rte_eth_dev *dev, uint32_t shaper_profile_id,
432 struct rte_tm_error *error)
434 struct mrvl_priv *priv = dev->data->dev_private;
435 struct mrvl_tm_shaper_profile *profile;
437 profile = mrvl_shaper_profile_from_id(priv, shaper_profile_id);
439 return -rte_tm_error_set(error, ENODEV,
440 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
441 NULL, "Profile id does not exist\n");
444 return -rte_tm_error_set(error, EPERM,
445 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
446 NULL, "Profile is used\n");
448 LIST_REMOVE(profile, next);
455 * Check node parameters.
457 * @param dev Pointer to the device.
458 * @param node_id Id used by the node.
459 * @param priority Priority value.
460 * @param weight Weight value.
461 * @param level_id Id of the level.
462 * @param params Pointer to the node parameters.
463 * @param error Pointer to the error.
464 * @returns 0 on success, negative value otherwise.
467 mrvl_node_check_params(struct rte_eth_dev *dev, uint32_t node_id,
468 uint32_t priority, uint32_t weight, uint32_t level_id,
469 struct rte_tm_node_params *params,
470 struct rte_tm_error *error)
472 if (node_id == RTE_TM_NODE_ID_NULL)
473 return -rte_tm_error_set(error, EINVAL, RTE_TM_NODE_ID_NULL,
474 NULL, "Node id is invalid\n");
477 return -rte_tm_error_set(error, EINVAL,
478 RTE_TM_ERROR_TYPE_NODE_PRIORITY,
479 NULL, "Priority should be 0\n");
481 if (weight > MRVL_WEIGHT_MAX)
482 return -rte_tm_error_set(error, EINVAL,
483 RTE_TM_ERROR_TYPE_NODE_WEIGHT,
484 NULL, "Weight is out of range\n");
486 if (level_id != MRVL_NODE_PORT && level_id != MRVL_NODE_QUEUE)
487 return -rte_tm_error_set(error, EINVAL,
488 RTE_TM_ERROR_TYPE_LEVEL_ID,
489 NULL, "Wrong level id\n");
492 return -rte_tm_error_set(error, EINVAL,
493 RTE_TM_ERROR_TYPE_UNSPECIFIED,
496 if (params->shared_shaper_id)
497 return -rte_tm_error_set(error, EINVAL,
498 RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_SHAPER_ID,
499 NULL, "Shared shaper is not supported\n");
501 if (params->n_shared_shapers)
502 return -rte_tm_error_set(error, EINVAL,
503 RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS,
504 NULL, "Shared shaper is not supported\n");
506 /* verify port (root node) settings */
507 if (node_id >= dev->data->nb_tx_queues) {
508 if (params->nonleaf.wfq_weight_mode)
509 return -rte_tm_error_set(error, EINVAL,
510 RTE_TM_ERROR_TYPE_NODE_PARAMS_WFQ_WEIGHT_MODE,
511 NULL, "WFQ is not supported\n");
513 if (params->nonleaf.n_sp_priorities != 1)
514 return -rte_tm_error_set(error, EINVAL,
515 RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SP_PRIORITIES,
516 NULL, "SP is not supported\n");
518 if (params->stats_mask & ~(RTE_TM_STATS_N_PKTS |
519 RTE_TM_STATS_N_BYTES))
520 return -rte_tm_error_set(error, EINVAL,
521 RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS,
523 "Requested port stats are not supported\n");
528 /* verify txq (leaf node) settings */
529 if (params->leaf.cman)
530 return -rte_tm_error_set(error, EINVAL,
531 RTE_TM_ERROR_TYPE_NODE_PARAMS_CMAN,
533 "Congestion mngmt is not supported\n");
535 if (params->leaf.wred.wred_profile_id)
536 return -rte_tm_error_set(error, EINVAL,
537 RTE_TM_ERROR_TYPE_NODE_PARAMS_WRED_PROFILE_ID,
538 NULL, "WRED is not supported\n");
540 if (params->leaf.wred.shared_wred_context_id)
541 return -rte_tm_error_set(error, EINVAL,
542 RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_WRED_CONTEXT_ID,
543 NULL, "WRED is not supported\n");
545 if (params->leaf.wred.n_shared_wred_contexts)
546 return -rte_tm_error_set(error, EINVAL,
547 RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_WRED_CONTEXTS,
548 NULL, "WRED is not supported\n");
550 if (params->stats_mask & ~RTE_TM_STATS_N_PKTS)
551 return -rte_tm_error_set(error, EINVAL,
552 RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS,
554 "Requested txq stats are not supported\n");
562 * @param dev Pointer to the device.
563 * @param node_id Id of the node.
564 * @param parent_node_id Id of the parent node.
565 * @param priority Priority value.
566 * @param weight Weight value.
567 * @param level_id Id of the level.
568 * @param params Pointer to the node parameters.
569 * @param error Pointer to the error.
570 * @returns 0 on success, negative value otherwise.
573 mrvl_node_add(struct rte_eth_dev *dev, uint32_t node_id,
574 uint32_t parent_node_id, uint32_t priority, uint32_t weight,
575 uint32_t level_id, struct rte_tm_node_params *params,
576 struct rte_tm_error *error)
578 struct mrvl_priv *priv = dev->data->dev_private;
579 struct mrvl_tm_shaper_profile *profile = NULL;
580 struct mrvl_tm_node *node, *parent = NULL;
584 return -rte_tm_error_set(error, EPERM,
585 RTE_TM_ERROR_TYPE_UNSPECIFIED,
586 NULL, "Port is already started\n");
588 ret = mrvl_node_check_params(dev, node_id, priority, weight, level_id,
593 if (params->shaper_profile_id != RTE_TM_SHAPER_PROFILE_ID_NONE) {
594 profile = mrvl_shaper_profile_from_id(priv,
595 params->shaper_profile_id);
597 return -rte_tm_error_set(error, ENODEV,
598 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
599 NULL, "Shaper id does not exist\n");
602 if (parent_node_id == RTE_TM_NODE_ID_NULL) {
603 LIST_FOREACH(node, &priv->nodes, next) {
604 if (node->type != MRVL_NODE_PORT)
607 return -rte_tm_error_set(error, EINVAL,
608 RTE_TM_ERROR_TYPE_UNSPECIFIED,
609 NULL, "Root node exists\n");
612 parent = mrvl_node_from_id(priv, parent_node_id);
614 return -rte_tm_error_set(error, EINVAL,
615 RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID,
616 NULL, "Node id does not exist\n");
619 node = mrvl_node_from_id(priv, node_id);
621 return -rte_tm_error_set(error, ENODEV,
622 RTE_TM_ERROR_TYPE_NODE_ID,
623 NULL, "Node id already exists\n");
625 node = rte_zmalloc_socket(NULL, sizeof(*node), 0, rte_socket_id());
627 return -rte_tm_error_set(error, ENOMEM,
628 RTE_TM_ERROR_TYPE_UNSPECIFIED,
632 node->type = parent_node_id == RTE_TM_NODE_ID_NULL ? MRVL_NODE_PORT :
636 node->parent = parent;
641 node->profile = profile;
645 node->weight = weight;
646 node->stats_mask = params->stats_mask;
648 LIST_INSERT_HEAD(&priv->nodes, node, next);
656 * @param dev Pointer to the device.
657 * @param node_id Id of the node.
658 * @param error Pointer to the error.
659 * @returns 0 on success, negative value otherwise.
662 mrvl_node_delete(struct rte_eth_dev *dev, uint32_t node_id,
663 struct rte_tm_error *error)
665 struct mrvl_priv *priv = dev->data->dev_private;
666 struct mrvl_tm_node *node;
669 return -rte_tm_error_set(error, EPERM,
670 RTE_TM_ERROR_TYPE_UNSPECIFIED,
671 NULL, "Port is already started\n");
674 node = mrvl_node_from_id(priv, node_id);
676 return -rte_tm_error_set(error, ENODEV,
677 RTE_TM_ERROR_TYPE_NODE_ID,
678 NULL, "Node id does not exist\n");
681 return -rte_tm_error_set(error, EPERM,
682 RTE_TM_ERROR_TYPE_NODE_ID,
683 NULL, "Node id is used\n");
686 node->parent->refcnt--;
689 node->profile->refcnt--;
691 LIST_REMOVE(node, next);
698 * Helper for suspending specific tx queue.
700 * @param dev Pointer to the device.
701 * @param node_id Id used by this node.
702 * @returns 0 on success, negative value otherwise.
704 static int mrvl_node_suspend_one(struct rte_eth_dev *dev, uint32_t node_id,
705 struct rte_tm_error *error)
707 int ret = dev->dev_ops->tx_queue_stop(dev, node_id);
709 return -rte_tm_error_set(error, ret,
710 RTE_TM_ERROR_TYPE_UNSPECIFIED,
711 NULL, "Failed to suspend a txq\n");
719 * @param dev Pointer to the device.
720 * @param node_id Id of the node.
721 * @param error Pointer to the error.
722 * returns 0 on success, negative value otherwise.
725 mrvl_node_suspend(struct rte_eth_dev *dev, uint32_t node_id,
726 struct rte_tm_error *error)
728 struct mrvl_priv *priv = dev->data->dev_private;
729 struct mrvl_tm_node *node, *tmp;
732 node = mrvl_node_from_id(priv, node_id);
734 return -rte_tm_error_set(error, ENODEV,
735 RTE_TM_ERROR_TYPE_NODE_ID,
736 NULL, "Node id does not exist\n");
739 LIST_FOREACH(tmp, &priv->nodes, next) {
743 if (node != tmp->parent)
746 ret = mrvl_node_suspend_one(dev, tmp->id, error);
754 return mrvl_node_suspend_one(dev, node_id, error);
760 * @param dev Pointer to the device.
761 * @param node_id Id of the node.
762 * @param error Pointer to the error.
763 * returns 0 on success, negative value otherwise.
766 mrvl_node_resume(struct rte_eth_dev *dev, uint32_t node_id,
767 struct rte_tm_error *error)
769 struct mrvl_priv *priv = dev->data->dev_private;
770 struct mrvl_tm_node *node;
773 node = mrvl_node_from_id(priv, node_id);
775 return -rte_tm_error_set(error, ENODEV,
776 RTE_TM_ERROR_TYPE_NODE_ID,
777 NULL, "Node id does not exist\n");
781 return -rte_tm_error_set(error, EPERM,
782 RTE_TM_ERROR_TYPE_NODE_ID,
783 NULL, "Cannot suspend a port\n");
785 ret = dev->dev_ops->tx_queue_start(dev, node_id);
787 return -rte_tm_error_set(error, ret,
788 RTE_TM_ERROR_TYPE_UNSPECIFIED,
789 NULL, "Failed to resume a txq\n");
794 * Apply traffic manager hierarchy.
796 * @param dev Pointer to the device.
797 * @param clear_on_fail Flag indicating whether to do cleanup on the failure.
798 * @param error Pointer to the error.
799 * @returns 0 on success, negative value otherwise.
802 mrvl_hierarchy_commit(struct rte_eth_dev *dev, int clear_on_fail,
803 struct rte_tm_error *error)
805 struct mrvl_priv *priv = dev->data->dev_private;
806 struct mrvl_tm_node *node;
810 ret = -rte_tm_error_set(error, EPERM,
811 RTE_TM_ERROR_TYPE_UNSPECIFIED,
812 NULL, "Port is already started\n");
816 LIST_FOREACH(node, &priv->nodes, next) {
817 struct pp2_ppio_outq_params *p;
819 if (node->type == MRVL_NODE_PORT) {
823 priv->ppio_params.rate_limit_enable = 1;
824 priv->ppio_params.rate_limit_params.cir =
825 node->profile->params.peak.rate * 8 / 1000;
826 priv->ppio_params.rate_limit_params.cbs =
827 node->profile->params.peak.size / 1000;
830 "Port rate limit overrides txqs rate limit");
835 if (node->id >= dev->data->nb_tx_queues) {
836 ret = -rte_tm_error_set(error, EINVAL,
837 RTE_TM_ERROR_TYPE_NODE_ID, NULL,
838 "Not enough txqs are configured\n");
842 p = &priv->ppio_params.outqs_params.outqs_params[node->id];
845 p->sched_mode = PP2_PPIO_SCHED_M_WRR;
846 p->weight = node->weight;
848 p->sched_mode = PP2_PPIO_SCHED_M_SP;
853 p->rate_limit_enable = 1;
854 /* convert Bytes/s to kilo bits/s */
855 p->rate_limit_params.cir =
856 node->profile->params.peak.rate * 8 / 1000;
857 /* convert bits to kilo bits */
858 p->rate_limit_params.cbs =
859 node->profile->params.peak.size / 1000;
861 p->rate_limit_enable = 0;
862 p->rate_limit_params.cir = 0;
863 p->rate_limit_params.cbs = 0;
867 /* reset to defaults in case applied tm hierarchy is empty */
868 if (LIST_EMPTY(&priv->nodes)) {
871 for (i = 0; i < priv->ppio_params.outqs_params.num_outqs; i++) {
872 struct pp2_ppio_outq_params *p =
873 &priv->ppio_params.outqs_params.outqs_params[i];
875 p->sched_mode = PP2_PPIO_SCHED_M_WRR;
877 p->rate_limit_enable = 0;
878 p->rate_limit_params.cir = 0;
879 p->rate_limit_params.cbs = 0;
894 * Read statistics counters for current node.
896 * @param dev Pointer to the device.
897 * @param node_id Id of the node.
898 * @param stats Pointer to the statistics counters.
899 * @param stats_mask Pointer to mask of enabled statistics counters
900 * that are retrieved.
901 * @param clear Flag indicating whether to clear statistics.
902 * Non-zero value clears statistics.
903 * @param error Pointer to the error.
904 * @returns 0 on success, negative value otherwise.
907 mrvl_node_stats_read(struct rte_eth_dev *dev, uint32_t node_id,
908 struct rte_tm_node_stats *stats, uint64_t *stats_mask,
909 int clear, struct rte_tm_error *error)
911 struct mrvl_priv *priv = dev->data->dev_private;
912 struct mrvl_tm_node *node;
916 return -rte_tm_error_set(error, EPERM,
917 RTE_TM_ERROR_TYPE_UNSPECIFIED,
918 NULL, "Port is not started\n");
921 node = mrvl_node_from_id(priv, node_id);
923 return -rte_tm_error_set(error, ENODEV,
924 RTE_TM_ERROR_TYPE_NODE_ID,
925 NULL, "Node id does not exist\n");
928 *stats_mask = node->stats_mask;
933 memset(stats, 0, sizeof(*stats));
936 struct pp2_ppio_statistics s;
938 memset(&s, 0, sizeof(s));
939 ret = pp2_ppio_get_statistics(priv->ppio, &s, clear);
941 return -rte_tm_error_set(error, -ret,
942 RTE_TM_ERROR_TYPE_UNSPECIFIED, NULL,
943 "Failed to read port statistics\n");
945 if (node->stats_mask & RTE_TM_STATS_N_PKTS)
946 stats->n_pkts = s.tx_packets;
948 if (node->stats_mask & RTE_TM_STATS_N_BYTES)
949 stats->n_bytes = s.tx_bytes;
951 struct pp2_ppio_outq_statistics s;
953 memset(&s, 0, sizeof(s));
954 ret = pp2_ppio_outq_get_statistics(priv->ppio, node_id, &s,
957 return -rte_tm_error_set(error, -ret,
958 RTE_TM_ERROR_TYPE_UNSPECIFIED, NULL,
959 "Failed to read txq statistics\n");
961 if (node->stats_mask & RTE_TM_STATS_N_PKTS)
962 stats->n_pkts = s.deq_desc;
969 * Update node statistics.
971 * @param dev Pointer to the device.
972 * @param node_id Id of the node.
973 * @param stats_mask Bitmask of statistics counters to be enabled.
974 * @param error Pointer to the error.
975 * @returns 0 on success, negative value otherwise.
978 mrvl_node_stats_update(struct rte_eth_dev *dev, uint32_t node_id,
979 uint64_t stats_mask, struct rte_tm_error *error)
981 struct mrvl_priv *priv = dev->data->dev_private;
982 struct mrvl_tm_node *node;
984 node = mrvl_node_from_id(priv, node_id);
986 return -rte_tm_error_set(error, ENODEV,
987 RTE_TM_ERROR_TYPE_NODE_ID,
988 NULL, "Node id does not exist\n");
991 if (stats_mask & ~(RTE_TM_STATS_N_PKTS | RTE_TM_STATS_N_BYTES))
992 return -rte_tm_error_set(error, EINVAL,
993 RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS,
995 "Requested port stats are not supported\n");
997 if (stats_mask & ~RTE_TM_STATS_N_PKTS)
998 return -rte_tm_error_set(error, EINVAL,
999 RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS,
1001 "Requested txq stats are not supported\n");
1004 node->stats_mask = stats_mask;
1009 const struct rte_tm_ops mrvl_tm_ops = {
1010 .node_type_get = mrvl_node_type_get,
1011 .capabilities_get = mrvl_capabilities_get,
1012 .level_capabilities_get = mrvl_level_capabilities_get,
1013 .node_capabilities_get = mrvl_node_capabilities_get,
1014 .shaper_profile_add = mrvl_shaper_profile_add,
1015 .shaper_profile_delete = mrvl_shaper_profile_delete,
1016 .node_add = mrvl_node_add,
1017 .node_delete = mrvl_node_delete,
1018 .node_suspend = mrvl_node_suspend,
1019 .node_resume = mrvl_node_resume,
1020 .hierarchy_commit = mrvl_hierarchy_commit,
1021 .node_stats_update = mrvl_node_stats_update,
1022 .node_stats_read = mrvl_node_stats_read,