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 = (uint64_t)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;
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");
155 return -rte_tm_error_set(error, EINVAL,
156 RTE_TM_ERROR_TYPE_UNSPECIFIED,
159 node = mrvl_node_from_id(priv, node_id);
161 return -rte_tm_error_set(error, ENODEV,
162 RTE_TM_ERROR_TYPE_NODE_ID,
163 NULL, "Node id does not exist\n");
165 *is_leaf = node->type == MRVL_NODE_QUEUE ? 1 : 0;
171 * Get traffic manager capabilities.
173 * @param dev Pointer to the device (unused).
174 * @param cap Pointer to the capabilities.
175 * @param error Pointer to the error.
176 * @returns 0 on success, negative value otherwise.
179 mrvl_capabilities_get(struct rte_eth_dev *dev,
180 struct rte_tm_capabilities *cap,
181 struct rte_tm_error *error)
183 struct mrvl_priv *priv = dev->data->dev_private;
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");
191 return -rte_tm_error_set(error, EINVAL,
192 RTE_TM_ERROR_TYPE_UNSPECIFIED,
193 NULL, "Capabilities are missing\n");
195 memset(cap, 0, sizeof(*cap));
197 cap->n_nodes_max = 1 + dev->data->nb_tx_queues; /* port + txqs number */
198 cap->n_levels_max = 2; /* port level + txqs level */
199 cap->non_leaf_nodes_identical = 1;
200 cap->leaf_nodes_identical = 1;
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;
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;
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;
225 * Get traffic manager hierarchy level capabilities.
227 * @param dev Pointer to the device.
228 * @param level_id Id of the level.
229 * @param cap Pointer to the level capabilities.
230 * @param error Pointer to the error.
231 * @returns 0 on success, negative value otherwise.
234 mrvl_level_capabilities_get(struct rte_eth_dev *dev,
236 struct rte_tm_level_capabilities *cap,
237 struct rte_tm_error *error)
239 struct mrvl_priv *priv = dev->data->dev_private;
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");
247 return -rte_tm_error_set(error, EINVAL,
248 RTE_TM_ERROR_TYPE_UNSPECIFIED,
251 memset(cap, 0, sizeof(*cap));
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");
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;
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;
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 { /* level_id == MRVL_NODE_QUEUE */
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;
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;
296 * Get node capabilities.
298 * @param dev Pointer to the device.
299 * @param node_id Id of the node.
300 * @param cap Pointer to the capabilities.
301 * @param error Pointer to the error.
302 * @returns 0 on success, negative value otherwise.
305 mrvl_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)
309 struct mrvl_priv *priv = dev->data->dev_private;
310 struct mrvl_tm_node *node;
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");
318 return -rte_tm_error_set(error, EINVAL,
319 RTE_TM_ERROR_TYPE_UNSPECIFIED,
322 memset(cap, 0, sizeof(*cap));
324 node = mrvl_node_from_id(priv, node_id);
326 return -rte_tm_error_set(error, ENODEV,
327 RTE_TM_ERROR_TYPE_NODE_ID,
328 NULL, "Node id does not exist\n");
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;
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;
347 cap->stats_mask = RTE_TM_STATS_N_PKTS;
354 * Get shaper profile using its id.
356 * @param priv Pointer to the port's private data.
357 * @param shaper_profile_id Id used by the shaper.
358 * @returns Pointer to the shaper profile if exists, NULL otherwise.
360 static struct mrvl_tm_shaper_profile *
361 mrvl_shaper_profile_from_id(struct mrvl_priv *priv, uint32_t shaper_profile_id)
363 struct mrvl_tm_shaper_profile *profile;
365 LIST_FOREACH(profile, &priv->shaper_profiles, next)
366 if (profile->id == shaper_profile_id)
373 * Add a new shaper profile.
375 * @param dev Pointer to the device.
376 * @param shaper_profile_id Id of the new profile.
377 * @param params Pointer to the shaper profile parameters.
378 * @param error Pointer to the error.
379 * @returns 0 on success, negative value otherwise.
382 mrvl_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)
386 struct mrvl_priv *priv = dev->data->dev_private;
387 struct mrvl_tm_shaper_profile *profile;
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");
395 return -rte_tm_error_set(error, EINVAL,
396 RTE_TM_ERROR_TYPE_UNSPECIFIED,
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");
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");
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");
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");
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");
426 profile = mrvl_shaper_profile_from_id(priv, shaper_profile_id);
428 return -rte_tm_error_set(error, EEXIST,
429 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
430 NULL, "Profile id already exists\n");
432 profile = rte_zmalloc_socket(NULL, sizeof(*profile), 0,
435 return -rte_tm_error_set(error, ENOMEM,
436 RTE_TM_ERROR_TYPE_UNSPECIFIED,
439 profile->id = shaper_profile_id;
440 rte_memcpy(&profile->params, params, sizeof(profile->params));
442 LIST_INSERT_HEAD(&priv->shaper_profiles, profile, next);
448 * Remove a shaper profile.
450 * @param dev Pointer to the device.
451 * @param shaper_profile_id Id of the shaper profile.
452 * @param error Pointer to the error.
453 * @returns 0 on success, negative value otherwise.
456 mrvl_shaper_profile_delete(struct rte_eth_dev *dev, uint32_t shaper_profile_id,
457 struct rte_tm_error *error)
459 struct mrvl_priv *priv = dev->data->dev_private;
460 struct mrvl_tm_shaper_profile *profile;
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");
467 profile = mrvl_shaper_profile_from_id(priv, shaper_profile_id);
469 return -rte_tm_error_set(error, ENODEV,
470 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
471 NULL, "Profile id does not exist\n");
474 return -rte_tm_error_set(error, EPERM,
475 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
476 NULL, "Profile is used\n");
478 LIST_REMOVE(profile, next);
485 * Check node parameters.
487 * @param dev Pointer to the device.
488 * @param node_id Id used by the node.
489 * @param priority Priority value.
490 * @param weight Weight value.
491 * @param level_id Id of the level.
492 * @param params Pointer to the node parameters.
493 * @param error Pointer to the error.
494 * @returns 0 on success, negative value otherwise.
497 mrvl_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)
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");
507 return -rte_tm_error_set(error, EINVAL,
508 RTE_TM_ERROR_TYPE_NODE_PRIORITY,
509 NULL, "Priority should be 0\n");
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");
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");
522 return -rte_tm_error_set(error, EINVAL,
523 RTE_TM_ERROR_TYPE_UNSPECIFIED,
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");
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");
536 /* verify port (root node) settings */
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");
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");
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,
553 "Requested port stats are not supported\n");
558 /* verify txq (leaf node) settings */
559 if (params->leaf.cman)
560 return -rte_tm_error_set(error, EINVAL,
561 RTE_TM_ERROR_TYPE_NODE_PARAMS_CMAN,
563 "Congestion mngmt is not supported\n");
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");
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");
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");
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,
584 "Requested txq stats are not supported\n");
592 * @param dev Pointer to the device.
593 * @param node_id Id of the node.
594 * @param parent_node_id Id of the parent node.
595 * @param priority Priority value.
596 * @param weight Weight value.
597 * @param level_id Id of the level.
598 * @param params Pointer to the node parameters.
599 * @param error Pointer to the error.
600 * @returns 0 on success, negative value otherwise.
603 mrvl_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)
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;
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");
619 return -rte_tm_error_set(error, EPERM,
620 RTE_TM_ERROR_TYPE_UNSPECIFIED,
621 NULL, "Port is already started\n");
623 ret = mrvl_node_check_params(dev, node_id, priority, weight, level_id,
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);
632 return -rte_tm_error_set(error, ENODEV,
633 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
634 NULL, "Shaper id does not exist\n");
637 if (parent_node_id == RTE_TM_NODE_ID_NULL) {
638 LIST_FOREACH(node, &priv->nodes, next) {
639 if (node->type != MRVL_NODE_PORT)
642 return -rte_tm_error_set(error, EINVAL,
643 RTE_TM_ERROR_TYPE_UNSPECIFIED,
644 NULL, "Root node exists\n");
647 parent = mrvl_node_from_id(priv, parent_node_id);
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");
654 node = mrvl_node_from_id(priv, node_id);
656 return -rte_tm_error_set(error, ENODEV,
657 RTE_TM_ERROR_TYPE_NODE_ID,
658 NULL, "Node id already exists\n");
660 node = rte_zmalloc_socket(NULL, sizeof(*node), 0, rte_socket_id());
662 return -rte_tm_error_set(error, ENOMEM,
663 RTE_TM_ERROR_TYPE_UNSPECIFIED,
667 node->type = parent_node_id == RTE_TM_NODE_ID_NULL ? MRVL_NODE_PORT :
671 node->parent = parent;
676 node->profile = profile;
680 node->weight = weight;
681 node->stats_mask = params->stats_mask;
683 LIST_INSERT_HEAD(&priv->nodes, node, next);
691 * @param dev Pointer to the device.
692 * @param node_id Id of the node.
693 * @param error Pointer to the error.
694 * @returns 0 on success, negative value otherwise.
697 mrvl_node_delete(struct rte_eth_dev *dev, uint32_t node_id,
698 struct rte_tm_error *error)
700 struct mrvl_priv *priv = dev->data->dev_private;
701 struct mrvl_tm_node *node;
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");
709 return -rte_tm_error_set(error, EPERM,
710 RTE_TM_ERROR_TYPE_UNSPECIFIED,
711 NULL, "Port is already started\n");
714 node = mrvl_node_from_id(priv, node_id);
716 return -rte_tm_error_set(error, ENODEV,
717 RTE_TM_ERROR_TYPE_NODE_ID,
718 NULL, "Node id does not exist\n");
721 return -rte_tm_error_set(error, EPERM,
722 RTE_TM_ERROR_TYPE_NODE_ID,
723 NULL, "Node id is used\n");
726 node->parent->refcnt--;
729 node->profile->refcnt--;
731 LIST_REMOVE(node, next);
738 * Helper for suspending specific tx queue.
740 * @param dev Pointer to the device.
741 * @param node_id Id used by this node.
742 * @returns 0 on success, negative value otherwise.
744 static int mrvl_node_suspend_one(struct rte_eth_dev *dev, uint32_t node_id,
745 struct rte_tm_error *error)
747 int ret = dev->dev_ops->tx_queue_stop(dev, node_id);
749 return -rte_tm_error_set(error, ret,
750 RTE_TM_ERROR_TYPE_UNSPECIFIED,
751 NULL, "Failed to suspend a txq\n");
759 * @param dev Pointer to the device.
760 * @param node_id Id of the node.
761 * @param error Pointer to the error.
762 * returns 0 on success, negative value otherwise.
765 mrvl_node_suspend(struct rte_eth_dev *dev, uint32_t node_id,
766 struct rte_tm_error *error)
768 struct mrvl_priv *priv = dev->data->dev_private;
769 struct mrvl_tm_node *node, *tmp;
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");
777 node = mrvl_node_from_id(priv, node_id);
779 return -rte_tm_error_set(error, ENODEV,
780 RTE_TM_ERROR_TYPE_NODE_ID,
781 NULL, "Node id does not exist\n");
784 LIST_FOREACH(tmp, &priv->nodes, next) {
788 if (node != tmp->parent)
791 ret = mrvl_node_suspend_one(dev, tmp->id, error);
799 return mrvl_node_suspend_one(dev, node_id, error);
805 * @param dev Pointer to the device.
806 * @param node_id Id of the node.
807 * @param error Pointer to the error.
808 * returns 0 on success, negative value otherwise.
811 mrvl_node_resume(struct rte_eth_dev *dev, uint32_t node_id,
812 struct rte_tm_error *error)
814 struct mrvl_priv *priv = dev->data->dev_private;
815 struct mrvl_tm_node *node;
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");
823 node = mrvl_node_from_id(priv, node_id);
825 return -rte_tm_error_set(error, ENODEV,
826 RTE_TM_ERROR_TYPE_NODE_ID,
827 NULL, "Node id does not exist\n");
831 return -rte_tm_error_set(error, EPERM,
832 RTE_TM_ERROR_TYPE_NODE_ID,
833 NULL, "Cannot suspend a port\n");
835 ret = dev->dev_ops->tx_queue_start(dev, node_id);
837 return -rte_tm_error_set(error, ret,
838 RTE_TM_ERROR_TYPE_UNSPECIFIED,
839 NULL, "Failed to resume a txq\n");
844 * Apply traffic manager hierarchy.
846 * @param dev Pointer to the device.
847 * @param clear_on_fail Flag indicating whether to do cleanup on the failure.
848 * @param error Pointer to the error.
849 * @returns 0 on success, negative value otherwise.
852 mrvl_hierarchy_commit(struct rte_eth_dev *dev, int clear_on_fail,
853 struct rte_tm_error *error)
855 struct mrvl_priv *priv = dev->data->dev_private;
856 struct mrvl_tm_node *node;
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");
865 ret = -rte_tm_error_set(error, EPERM,
866 RTE_TM_ERROR_TYPE_UNSPECIFIED,
867 NULL, "Port is already started\n");
871 LIST_FOREACH(node, &priv->nodes, next) {
872 struct pp2_ppio_outq_params *p;
874 if (node->type == MRVL_NODE_PORT) {
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;
885 "Port rate limit overrides txqs rate limit");
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");
897 p = &priv->ppio_params.outqs_params.outqs_params[node->id];
900 p->sched_mode = PP2_PPIO_SCHED_M_WRR;
901 p->weight = node->weight;
903 p->sched_mode = PP2_PPIO_SCHED_M_SP;
908 p->rate_limit_enable = 1;
909 /* convert Bytes/s to kilo bits/s */
910 p->rate_limit_params.cir =
911 node->profile->params.peak.rate * 8 / 1000;
912 /* convert bits to kilo bits */
913 p->rate_limit_params.cbs =
914 node->profile->params.peak.size / 1000;
916 p->rate_limit_enable = 0;
917 p->rate_limit_params.cir = 0;
918 p->rate_limit_params.cbs = 0;
922 /* reset to defaults in case applied tm hierarchy is empty */
923 if (LIST_EMPTY(&priv->nodes)) {
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];
930 p->sched_mode = PP2_PPIO_SCHED_M_WRR;
932 p->rate_limit_enable = 0;
933 p->rate_limit_params.cir = 0;
934 p->rate_limit_params.cbs = 0;
949 * Read statistics counters for current node.
951 * @param dev Pointer to the device.
952 * @param node_id Id of the node.
953 * @param stats Pointer to the statistics counters.
954 * @param stats_mask Pointer to mask of enabled statistics counters
955 * that are retrieved.
956 * @param clear Flag indicating whether to clear statistics.
957 * Non-zero value clears statistics.
958 * @param error Pointer to the error.
959 * @returns 0 on success, negative value otherwise.
962 mrvl_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)
966 struct mrvl_priv *priv = dev->data->dev_private;
967 struct mrvl_tm_node *node;
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");
976 return -rte_tm_error_set(error, EPERM,
977 RTE_TM_ERROR_TYPE_UNSPECIFIED,
978 NULL, "Port is not started\n");
981 node = mrvl_node_from_id(priv, node_id);
983 return -rte_tm_error_set(error, ENODEV,
984 RTE_TM_ERROR_TYPE_NODE_ID,
985 NULL, "Node id does not exist\n");
988 *stats_mask = node->stats_mask;
993 memset(stats, 0, sizeof(*stats));
996 struct pp2_ppio_statistics s;
998 memset(&s, 0, sizeof(s));
999 ret = pp2_ppio_get_statistics(priv->ppio, &s, clear);
1001 return -rte_tm_error_set(error, -ret,
1002 RTE_TM_ERROR_TYPE_UNSPECIFIED, NULL,
1003 "Failed to read port statistics\n");
1005 if (node->stats_mask & RTE_TM_STATS_N_PKTS)
1006 stats->n_pkts = s.tx_packets;
1008 if (node->stats_mask & RTE_TM_STATS_N_BYTES)
1009 stats->n_bytes = s.tx_bytes;
1011 struct pp2_ppio_outq_statistics s;
1013 memset(&s, 0, sizeof(s));
1014 ret = pp2_ppio_outq_get_statistics(priv->ppio, node_id, &s,
1017 return -rte_tm_error_set(error, -ret,
1018 RTE_TM_ERROR_TYPE_UNSPECIFIED, NULL,
1019 "Failed to read txq statistics\n");
1021 if (node->stats_mask & RTE_TM_STATS_N_PKTS)
1022 stats->n_pkts = s.deq_desc;
1029 * Update node statistics.
1031 * @param dev Pointer to the device.
1032 * @param node_id Id of the node.
1033 * @param stats_mask Bitmask of statistics counters to be enabled.
1034 * @param error Pointer to the error.
1035 * @returns 0 on success, negative value otherwise.
1038 mrvl_node_stats_update(struct rte_eth_dev *dev, uint32_t node_id,
1039 uint64_t stats_mask, struct rte_tm_error *error)
1041 struct mrvl_priv *priv = dev->data->dev_private;
1042 struct mrvl_tm_node *node;
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");
1049 node = mrvl_node_from_id(priv, node_id);
1051 return -rte_tm_error_set(error, ENODEV,
1052 RTE_TM_ERROR_TYPE_NODE_ID,
1053 NULL, "Node id does not exist\n");
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,
1060 "Requested port stats are not supported\n");
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,
1066 "Requested txq stats are not supported\n");
1069 node->stats_mask = stats_mask;
1074 const 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,