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
;
197 cap
->sched_n_children_max
= dev
->data
->nb_tx_queues
;
198 cap
->sched_sp_n_priorities_max
= dev
->data
->nb_tx_queues
;
199 cap
->sched_wfq_n_children_per_group_max
= dev
->data
->nb_tx_queues
;
200 cap
->sched_wfq_n_groups_max
= 1;
201 cap
->sched_wfq_weight_max
= MRVL_WEIGHT_MAX
;
203 cap
->dynamic_update_mask
= RTE_TM_UPDATE_NODE_SUSPEND_RESUME
|
204 RTE_TM_UPDATE_NODE_STATS
;
205 cap
->stats_mask
= RTE_TM_STATS_N_PKTS
| RTE_TM_STATS_N_BYTES
;
211 * Get traffic manager hierarchy level capabilities.
213 * @param dev Pointer to the device.
214 * @param level_id Id of the level.
215 * @param cap Pointer to the level capabilities.
216 * @param error Pointer to the error.
217 * @returns 0 on success, negative value otherwise.
220 mrvl_level_capabilities_get(struct rte_eth_dev
*dev
,
222 struct rte_tm_level_capabilities
*cap
,
223 struct rte_tm_error
*error
)
225 struct mrvl_priv
*priv
= dev
->data
->dev_private
;
228 return -rte_tm_error_set(error
, EINVAL
,
229 RTE_TM_ERROR_TYPE_UNSPECIFIED
,
232 memset(cap
, 0, sizeof(*cap
));
234 if (level_id
!= MRVL_NODE_PORT
&& level_id
!= MRVL_NODE_QUEUE
)
235 return -rte_tm_error_set(error
, EINVAL
,
236 RTE_TM_ERROR_TYPE_LEVEL_ID
,
237 NULL
, "Wrong level id\n");
239 if (level_id
== MRVL_NODE_PORT
) {
240 cap
->n_nodes_max
= 1;
241 cap
->n_nodes_nonleaf_max
= 1;
242 cap
->non_leaf_nodes_identical
= 1;
244 cap
->nonleaf
.shaper_private_supported
= 1;
245 cap
->nonleaf
.shaper_private_rate_min
= MRVL_RATE_MIN
;
246 cap
->nonleaf
.shaper_private_rate_max
= priv
->rate_max
;
248 cap
->nonleaf
.sched_n_children_max
= dev
->data
->nb_tx_queues
;
249 cap
->nonleaf
.sched_sp_n_priorities_max
= 1;
250 cap
->nonleaf
.sched_wfq_n_children_per_group_max
=
251 dev
->data
->nb_tx_queues
;
252 cap
->nonleaf
.sched_wfq_n_groups_max
= 1;
253 cap
->nonleaf
.sched_wfq_weight_max
= MRVL_WEIGHT_MAX
;
254 cap
->nonleaf
.stats_mask
= RTE_TM_STATS_N_PKTS
|
255 RTE_TM_STATS_N_BYTES
;
256 } else { /* level_id == MRVL_NODE_QUEUE */
257 cap
->n_nodes_max
= dev
->data
->nb_tx_queues
;
258 cap
->n_nodes_leaf_max
= dev
->data
->nb_tx_queues
;
259 cap
->leaf_nodes_identical
= 1;
261 cap
->leaf
.shaper_private_supported
= 1;
262 cap
->leaf
.shaper_private_rate_min
= MRVL_RATE_MIN
;
263 cap
->leaf
.shaper_private_rate_max
= priv
->rate_max
;
264 cap
->leaf
.stats_mask
= RTE_TM_STATS_N_PKTS
;
271 * Get node capabilities.
273 * @param dev Pointer to the device.
274 * @param node_id Id of the node.
275 * @param cap Pointer to the capabilities.
276 * @param error Pointer to the error.
277 * @returns 0 on success, negative value otherwise.
280 mrvl_node_capabilities_get(struct rte_eth_dev
*dev
, uint32_t node_id
,
281 struct rte_tm_node_capabilities
*cap
,
282 struct rte_tm_error
*error
)
284 struct mrvl_priv
*priv
= dev
->data
->dev_private
;
285 struct mrvl_tm_node
*node
;
288 return -rte_tm_error_set(error
, EINVAL
,
289 RTE_TM_ERROR_TYPE_UNSPECIFIED
,
292 memset(cap
, 0, sizeof(*cap
));
294 node
= mrvl_node_from_id(priv
, node_id
);
296 return -rte_tm_error_set(error
, ENODEV
,
297 RTE_TM_ERROR_TYPE_NODE_ID
,
298 NULL
, "Node id does not exist\n");
300 cap
->shaper_private_supported
= 1;
301 cap
->shaper_private_rate_min
= MRVL_RATE_MIN
;
302 cap
->shaper_private_rate_max
= priv
->rate_max
;
304 if (node
->type
== MRVL_NODE_PORT
) {
305 cap
->nonleaf
.sched_n_children_max
= dev
->data
->nb_tx_queues
;
306 cap
->nonleaf
.sched_sp_n_priorities_max
= 1;
307 cap
->nonleaf
.sched_wfq_n_children_per_group_max
=
308 dev
->data
->nb_tx_queues
;
309 cap
->nonleaf
.sched_wfq_n_groups_max
= 1;
310 cap
->nonleaf
.sched_wfq_weight_max
= MRVL_WEIGHT_MAX
;
311 cap
->stats_mask
= RTE_TM_STATS_N_PKTS
| RTE_TM_STATS_N_BYTES
;
313 cap
->stats_mask
= RTE_TM_STATS_N_PKTS
;
320 * Get shaper profile using its id.
322 * @param priv Pointer to the port's private data.
323 * @param shaper_profile_id Id used by the shaper.
324 * @returns Pointer to the shaper profile if exists, NULL otherwise.
326 static struct mrvl_tm_shaper_profile
*
327 mrvl_shaper_profile_from_id(struct mrvl_priv
*priv
, uint32_t shaper_profile_id
)
329 struct mrvl_tm_shaper_profile
*profile
;
331 LIST_FOREACH(profile
, &priv
->shaper_profiles
, next
)
332 if (profile
->id
== shaper_profile_id
)
339 * Add a new shaper profile.
341 * @param dev Pointer to the device.
342 * @param shaper_profile_id Id of the new profile.
343 * @param params Pointer to the shaper profile parameters.
344 * @param error Pointer to the error.
345 * @returns 0 on success, negative value otherwise.
348 mrvl_shaper_profile_add(struct rte_eth_dev
*dev
, uint32_t shaper_profile_id
,
349 struct rte_tm_shaper_params
*params
,
350 struct rte_tm_error
*error
)
352 struct mrvl_priv
*priv
= dev
->data
->dev_private
;
353 struct mrvl_tm_shaper_profile
*profile
;
356 return -rte_tm_error_set(error
, EINVAL
,
357 RTE_TM_ERROR_TYPE_UNSPECIFIED
,
360 if (params
->committed
.rate
)
361 return -rte_tm_error_set(error
, EINVAL
,
362 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_RATE
,
363 NULL
, "Committed rate not supported\n");
365 if (params
->committed
.size
)
366 return -rte_tm_error_set(error
, EINVAL
,
367 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_SIZE
,
368 NULL
, "Committed bucket size not supported\n");
370 if (params
->peak
.rate
< MRVL_RATE_MIN
||
371 params
->peak
.rate
> priv
->rate_max
)
372 return -rte_tm_error_set(error
, EINVAL
,
373 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE
,
374 NULL
, "Peak rate is out of range\n");
376 if (params
->peak
.size
< MRVL_BURST_MIN
||
377 params
->peak
.size
> MRVL_BURST_MAX
)
378 return -rte_tm_error_set(error
, EINVAL
,
379 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE
,
380 NULL
, "Peak size is out of range\n");
382 if (shaper_profile_id
== RTE_TM_SHAPER_PROFILE_ID_NONE
)
383 return -rte_tm_error_set(error
, EINVAL
,
384 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID
,
385 NULL
, "Wrong shaper profile id\n");
387 profile
= mrvl_shaper_profile_from_id(priv
, shaper_profile_id
);
389 return -rte_tm_error_set(error
, EEXIST
,
390 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID
,
391 NULL
, "Profile id already exists\n");
393 profile
= rte_zmalloc_socket(NULL
, sizeof(*profile
), 0,
396 return -rte_tm_error_set(error
, ENOMEM
,
397 RTE_TM_ERROR_TYPE_UNSPECIFIED
,
400 profile
->id
= shaper_profile_id
;
401 rte_memcpy(&profile
->params
, params
, sizeof(profile
->params
));
403 LIST_INSERT_HEAD(&priv
->shaper_profiles
, profile
, next
);
409 * Remove a shaper profile.
411 * @param dev Pointer to the device.
412 * @param shaper_profile_id Id of the shaper profile.
413 * @param error Pointer to the error.
414 * @returns 0 on success, negative value otherwise.
417 mrvl_shaper_profile_delete(struct rte_eth_dev
*dev
, uint32_t shaper_profile_id
,
418 struct rte_tm_error
*error
)
420 struct mrvl_priv
*priv
= dev
->data
->dev_private
;
421 struct mrvl_tm_shaper_profile
*profile
;
423 profile
= mrvl_shaper_profile_from_id(priv
, shaper_profile_id
);
425 return -rte_tm_error_set(error
, ENODEV
,
426 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID
,
427 NULL
, "Profile id does not exist\n");
430 return -rte_tm_error_set(error
, EPERM
,
431 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID
,
432 NULL
, "Profile is used\n");
434 LIST_REMOVE(profile
, next
);
441 * Check node parameters.
443 * @param dev Pointer to the device.
444 * @param node_id Id used by the node.
445 * @param priority Priority value.
446 * @param weight Weight value.
447 * @param level_id Id of the level.
448 * @param params Pointer to the node parameters.
449 * @param error Pointer to the error.
450 * @returns 0 on success, negative value otherwise.
453 mrvl_node_check_params(struct rte_eth_dev
*dev
, uint32_t node_id
,
454 uint32_t priority
, uint32_t weight
, uint32_t level_id
,
455 struct rte_tm_node_params
*params
,
456 struct rte_tm_error
*error
)
458 if (node_id
== RTE_TM_NODE_ID_NULL
)
459 return -rte_tm_error_set(error
, EINVAL
, RTE_TM_NODE_ID_NULL
,
460 NULL
, "Node id is invalid\n");
463 return -rte_tm_error_set(error
, EINVAL
,
464 RTE_TM_ERROR_TYPE_NODE_PRIORITY
,
465 NULL
, "Priority should be 0\n");
467 if (weight
> MRVL_WEIGHT_MAX
)
468 return -rte_tm_error_set(error
, EINVAL
,
469 RTE_TM_ERROR_TYPE_NODE_WEIGHT
,
470 NULL
, "Weight is out of range\n");
472 if (level_id
!= MRVL_NODE_PORT
&& level_id
!= MRVL_NODE_QUEUE
)
473 return -rte_tm_error_set(error
, EINVAL
,
474 RTE_TM_ERROR_TYPE_LEVEL_ID
,
475 NULL
, "Wrong level id\n");
478 return -rte_tm_error_set(error
, EINVAL
,
479 RTE_TM_ERROR_TYPE_UNSPECIFIED
,
482 if (params
->shared_shaper_id
)
483 return -rte_tm_error_set(error
, EINVAL
,
484 RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_SHAPER_ID
,
485 NULL
, "Shared shaper is not supported\n");
487 if (params
->n_shared_shapers
)
488 return -rte_tm_error_set(error
, EINVAL
,
489 RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS
,
490 NULL
, "Shared shaper is not supported\n");
492 /* verify port (root node) settings */
493 if (node_id
>= dev
->data
->nb_tx_queues
) {
494 if (params
->nonleaf
.wfq_weight_mode
)
495 return -rte_tm_error_set(error
, EINVAL
,
496 RTE_TM_ERROR_TYPE_NODE_PARAMS_WFQ_WEIGHT_MODE
,
497 NULL
, "WFQ is not supported\n");
499 if (params
->nonleaf
.n_sp_priorities
!= 1)
500 return -rte_tm_error_set(error
, EINVAL
,
501 RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SP_PRIORITIES
,
502 NULL
, "SP is not supported\n");
504 if (params
->stats_mask
& ~(RTE_TM_STATS_N_PKTS
|
505 RTE_TM_STATS_N_BYTES
))
506 return -rte_tm_error_set(error
, EINVAL
,
507 RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS
,
509 "Requested port stats are not supported\n");
514 /* verify txq (leaf node) settings */
515 if (params
->leaf
.cman
)
516 return -rte_tm_error_set(error
, EINVAL
,
517 RTE_TM_ERROR_TYPE_NODE_PARAMS_CMAN
,
519 "Congestion mngmt is not supported\n");
521 if (params
->leaf
.wred
.wred_profile_id
)
522 return -rte_tm_error_set(error
, EINVAL
,
523 RTE_TM_ERROR_TYPE_NODE_PARAMS_WRED_PROFILE_ID
,
524 NULL
, "WRED is not supported\n");
526 if (params
->leaf
.wred
.shared_wred_context_id
)
527 return -rte_tm_error_set(error
, EINVAL
,
528 RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_WRED_CONTEXT_ID
,
529 NULL
, "WRED is not supported\n");
531 if (params
->leaf
.wred
.n_shared_wred_contexts
)
532 return -rte_tm_error_set(error
, EINVAL
,
533 RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_WRED_CONTEXTS
,
534 NULL
, "WRED is not supported\n");
536 if (params
->stats_mask
& ~RTE_TM_STATS_N_PKTS
)
537 return -rte_tm_error_set(error
, EINVAL
,
538 RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS
,
540 "Requested txq stats are not supported\n");
548 * @param dev Pointer to the device.
549 * @param node_id Id of the node.
550 * @param parent_node_id Id of the parent node.
551 * @param priority Priority value.
552 * @param weight Weight value.
553 * @param level_id Id of the level.
554 * @param params Pointer to the node parameters.
555 * @param error Pointer to the error.
556 * @returns 0 on success, negative value otherwise.
559 mrvl_node_add(struct rte_eth_dev
*dev
, uint32_t node_id
,
560 uint32_t parent_node_id
, uint32_t priority
, uint32_t weight
,
561 uint32_t level_id
, struct rte_tm_node_params
*params
,
562 struct rte_tm_error
*error
)
564 struct mrvl_priv
*priv
= dev
->data
->dev_private
;
565 struct mrvl_tm_shaper_profile
*profile
= NULL
;
566 struct mrvl_tm_node
*node
, *parent
= NULL
;
570 return -rte_tm_error_set(error
, EPERM
,
571 RTE_TM_ERROR_TYPE_UNSPECIFIED
,
572 NULL
, "Port is already started\n");
574 ret
= mrvl_node_check_params(dev
, node_id
, priority
, weight
, level_id
,
579 if (params
->shaper_profile_id
!= RTE_TM_SHAPER_PROFILE_ID_NONE
) {
580 profile
= mrvl_shaper_profile_from_id(priv
,
581 params
->shaper_profile_id
);
583 return -rte_tm_error_set(error
, ENODEV
,
584 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID
,
585 NULL
, "Shaper id does not exist\n");
588 if (parent_node_id
== RTE_TM_NODE_ID_NULL
) {
589 LIST_FOREACH(node
, &priv
->nodes
, next
) {
590 if (node
->type
!= MRVL_NODE_PORT
)
593 return -rte_tm_error_set(error
, EINVAL
,
594 RTE_TM_ERROR_TYPE_UNSPECIFIED
,
595 NULL
, "Root node exists\n");
598 parent
= mrvl_node_from_id(priv
, parent_node_id
);
600 return -rte_tm_error_set(error
, EINVAL
,
601 RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID
,
602 NULL
, "Node id does not exist\n");
605 node
= mrvl_node_from_id(priv
, node_id
);
607 return -rte_tm_error_set(error
, ENODEV
,
608 RTE_TM_ERROR_TYPE_NODE_ID
,
609 NULL
, "Node id already exists\n");
611 node
= rte_zmalloc_socket(NULL
, sizeof(*node
), 0, rte_socket_id());
613 return -rte_tm_error_set(error
, ENOMEM
,
614 RTE_TM_ERROR_TYPE_UNSPECIFIED
,
618 node
->type
= parent_node_id
== RTE_TM_NODE_ID_NULL
? MRVL_NODE_PORT
:
622 node
->parent
= parent
;
627 node
->profile
= profile
;
631 node
->weight
= weight
;
632 node
->stats_mask
= params
->stats_mask
;
634 LIST_INSERT_HEAD(&priv
->nodes
, node
, next
);
642 * @param dev Pointer to the device.
643 * @param node_id Id of the node.
644 * @param error Pointer to the error.
645 * @returns 0 on success, negative value otherwise.
648 mrvl_node_delete(struct rte_eth_dev
*dev
, uint32_t node_id
,
649 struct rte_tm_error
*error
)
651 struct mrvl_priv
*priv
= dev
->data
->dev_private
;
652 struct mrvl_tm_node
*node
;
655 return -rte_tm_error_set(error
, EPERM
,
656 RTE_TM_ERROR_TYPE_UNSPECIFIED
,
657 NULL
, "Port is already started\n");
660 node
= mrvl_node_from_id(priv
, node_id
);
662 return -rte_tm_error_set(error
, ENODEV
,
663 RTE_TM_ERROR_TYPE_NODE_ID
,
664 NULL
, "Node id does not exist\n");
667 return -rte_tm_error_set(error
, EPERM
,
668 RTE_TM_ERROR_TYPE_NODE_ID
,
669 NULL
, "Node id is used\n");
672 node
->parent
->refcnt
--;
675 node
->profile
->refcnt
--;
677 LIST_REMOVE(node
, next
);
684 * Helper for suspending specific tx queue.
686 * @param dev Pointer to the device.
687 * @param node_id Id used by this node.
688 * @returns 0 on success, negative value otherwise.
690 static int mrvl_node_suspend_one(struct rte_eth_dev
*dev
, uint32_t node_id
,
691 struct rte_tm_error
*error
)
693 int ret
= dev
->dev_ops
->tx_queue_stop(dev
, node_id
);
695 return -rte_tm_error_set(error
, ret
,
696 RTE_TM_ERROR_TYPE_UNSPECIFIED
,
697 NULL
, "Failed to suspend a txq\n");
705 * @param dev Pointer to the device.
706 * @param node_id Id of the node.
707 * @param error Pointer to the error.
708 * returns 0 on success, negative value otherwise.
711 mrvl_node_suspend(struct rte_eth_dev
*dev
, uint32_t node_id
,
712 struct rte_tm_error
*error
)
714 struct mrvl_priv
*priv
= dev
->data
->dev_private
;
715 struct mrvl_tm_node
*node
, *tmp
;
718 node
= mrvl_node_from_id(priv
, node_id
);
720 return -rte_tm_error_set(error
, ENODEV
,
721 RTE_TM_ERROR_TYPE_NODE_ID
,
722 NULL
, "Node id does not exist\n");
725 LIST_FOREACH(tmp
, &priv
->nodes
, next
) {
729 if (node
!= tmp
->parent
)
732 ret
= mrvl_node_suspend_one(dev
, tmp
->id
, error
);
740 return mrvl_node_suspend_one(dev
, node_id
, error
);
746 * @param dev Pointer to the device.
747 * @param node_id Id of the node.
748 * @param error Pointer to the error.
749 * returns 0 on success, negative value otherwise.
752 mrvl_node_resume(struct rte_eth_dev
*dev
, uint32_t node_id
,
753 struct rte_tm_error
*error
)
755 struct mrvl_priv
*priv
= dev
->data
->dev_private
;
756 struct mrvl_tm_node
*node
;
759 node
= mrvl_node_from_id(priv
, node_id
);
761 return -rte_tm_error_set(error
, ENODEV
,
762 RTE_TM_ERROR_TYPE_NODE_ID
,
763 NULL
, "Node id does not exist\n");
767 return -rte_tm_error_set(error
, EPERM
,
768 RTE_TM_ERROR_TYPE_NODE_ID
,
769 NULL
, "Cannot suspend a port\n");
771 ret
= dev
->dev_ops
->tx_queue_start(dev
, node_id
);
773 return -rte_tm_error_set(error
, ret
,
774 RTE_TM_ERROR_TYPE_UNSPECIFIED
,
775 NULL
, "Failed to resume a txq\n");
780 * Apply traffic manager hierarchy.
782 * @param dev Pointer to the device.
783 * @param clear_on_fail Flag indicating whether to do cleanup on the failure.
784 * @param error Pointer to the error.
785 * @returns 0 on success, negative value otherwise.
788 mrvl_hierarchy_commit(struct rte_eth_dev
*dev
, int clear_on_fail
,
789 struct rte_tm_error
*error
)
791 struct mrvl_priv
*priv
= dev
->data
->dev_private
;
792 struct mrvl_tm_node
*node
;
796 ret
= -rte_tm_error_set(error
, EPERM
,
797 RTE_TM_ERROR_TYPE_UNSPECIFIED
,
798 NULL
, "Port is already started\n");
802 LIST_FOREACH(node
, &priv
->nodes
, next
) {
803 struct pp2_ppio_outq_params
*p
;
805 if (node
->type
== MRVL_NODE_PORT
) {
809 priv
->ppio_params
.rate_limit_enable
= 1;
810 priv
->ppio_params
.rate_limit_params
.cir
=
811 node
->profile
->params
.peak
.rate
* 8 / 1000;
812 priv
->ppio_params
.rate_limit_params
.cbs
=
813 node
->profile
->params
.peak
.size
/ 1000;
816 "Port rate limit overrides txqs rate limit");
821 if (node
->id
>= dev
->data
->nb_tx_queues
) {
822 ret
= -rte_tm_error_set(error
, EINVAL
,
823 RTE_TM_ERROR_TYPE_NODE_ID
, NULL
,
824 "Not enough txqs are configured\n");
828 p
= &priv
->ppio_params
.outqs_params
.outqs_params
[node
->id
];
831 p
->sched_mode
= PP2_PPIO_SCHED_M_WRR
;
832 p
->weight
= node
->weight
;
834 p
->sched_mode
= PP2_PPIO_SCHED_M_SP
;
839 p
->rate_limit_enable
= 1;
840 /* convert Bytes/s to kilo bits/s */
841 p
->rate_limit_params
.cir
=
842 node
->profile
->params
.peak
.rate
* 8 / 1000;
843 /* convert bits to kilo bits */
844 p
->rate_limit_params
.cbs
=
845 node
->profile
->params
.peak
.size
/ 1000;
847 p
->rate_limit_enable
= 0;
848 p
->rate_limit_params
.cir
= 0;
849 p
->rate_limit_params
.cbs
= 0;
853 /* reset to defaults in case applied tm hierarchy is empty */
854 if (LIST_EMPTY(&priv
->nodes
)) {
857 for (i
= 0; i
< priv
->ppio_params
.outqs_params
.num_outqs
; i
++) {
858 struct pp2_ppio_outq_params
*p
=
859 &priv
->ppio_params
.outqs_params
.outqs_params
[i
];
861 p
->sched_mode
= PP2_PPIO_SCHED_M_WRR
;
863 p
->rate_limit_enable
= 0;
864 p
->rate_limit_params
.cir
= 0;
865 p
->rate_limit_params
.cbs
= 0;
880 * Read statistics counters for current node.
882 * @param dev Pointer to the device.
883 * @param node_id Id of the node.
884 * @param stats Pointer to the statistics counters.
885 * @param stats_mask Pointer to mask of enabled statistics counters
886 * that are retrieved.
887 * @param clear Flag indicating whether to clear statistics.
888 * Non-zero value clears statistics.
889 * @param error Pointer to the error.
890 * @returns 0 on success, negative value otherwise.
893 mrvl_node_stats_read(struct rte_eth_dev
*dev
, uint32_t node_id
,
894 struct rte_tm_node_stats
*stats
, uint64_t *stats_mask
,
895 int clear
, struct rte_tm_error
*error
)
897 struct mrvl_priv
*priv
= dev
->data
->dev_private
;
898 struct mrvl_tm_node
*node
;
902 return -rte_tm_error_set(error
, EPERM
,
903 RTE_TM_ERROR_TYPE_UNSPECIFIED
,
904 NULL
, "Port is not started\n");
907 node
= mrvl_node_from_id(priv
, node_id
);
909 return -rte_tm_error_set(error
, ENODEV
,
910 RTE_TM_ERROR_TYPE_NODE_ID
,
911 NULL
, "Node id does not exist\n");
914 *stats_mask
= node
->stats_mask
;
919 memset(stats
, 0, sizeof(*stats
));
922 struct pp2_ppio_statistics s
;
924 memset(&s
, 0, sizeof(s
));
925 ret
= pp2_ppio_get_statistics(priv
->ppio
, &s
, clear
);
927 return -rte_tm_error_set(error
, -ret
,
928 RTE_TM_ERROR_TYPE_UNSPECIFIED
, NULL
,
929 "Failed to read port statistics\n");
931 if (node
->stats_mask
& RTE_TM_STATS_N_PKTS
)
932 stats
->n_pkts
= s
.tx_packets
;
934 if (node
->stats_mask
& RTE_TM_STATS_N_BYTES
)
935 stats
->n_bytes
= s
.tx_bytes
;
937 struct pp2_ppio_outq_statistics s
;
939 memset(&s
, 0, sizeof(s
));
940 ret
= pp2_ppio_outq_get_statistics(priv
->ppio
, node_id
, &s
,
943 return -rte_tm_error_set(error
, -ret
,
944 RTE_TM_ERROR_TYPE_UNSPECIFIED
, NULL
,
945 "Failed to read txq statistics\n");
947 if (node
->stats_mask
& RTE_TM_STATS_N_PKTS
)
948 stats
->n_pkts
= s
.deq_desc
;
955 * Update node statistics.
957 * @param dev Pointer to the device.
958 * @param node_id Id of the node.
959 * @param stats_mask Bitmask of statistics counters to be enabled.
960 * @param error Pointer to the error.
961 * @returns 0 on success, negative value otherwise.
964 mrvl_node_stats_update(struct rte_eth_dev
*dev
, uint32_t node_id
,
965 uint64_t stats_mask
, struct rte_tm_error
*error
)
967 struct mrvl_priv
*priv
= dev
->data
->dev_private
;
968 struct mrvl_tm_node
*node
;
970 node
= mrvl_node_from_id(priv
, node_id
);
972 return -rte_tm_error_set(error
, ENODEV
,
973 RTE_TM_ERROR_TYPE_NODE_ID
,
974 NULL
, "Node id does not exist\n");
977 if (stats_mask
& ~(RTE_TM_STATS_N_PKTS
| RTE_TM_STATS_N_BYTES
))
978 return -rte_tm_error_set(error
, EINVAL
,
979 RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS
,
981 "Requested port stats are not supported\n");
983 if (stats_mask
& ~RTE_TM_STATS_N_PKTS
)
984 return -rte_tm_error_set(error
, EINVAL
,
985 RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS
,
987 "Requested txq stats are not supported\n");
990 node
->stats_mask
= stats_mask
;
995 const struct rte_tm_ops mrvl_tm_ops
= {
996 .node_type_get
= mrvl_node_type_get
,
997 .capabilities_get
= mrvl_capabilities_get
,
998 .level_capabilities_get
= mrvl_level_capabilities_get
,
999 .node_capabilities_get
= mrvl_node_capabilities_get
,
1000 .shaper_profile_add
= mrvl_shaper_profile_add
,
1001 .shaper_profile_delete
= mrvl_shaper_profile_delete
,
1002 .node_add
= mrvl_node_add
,
1003 .node_delete
= mrvl_node_delete
,
1004 .node_suspend
= mrvl_node_suspend
,
1005 .node_resume
= mrvl_node_resume
,
1006 .hierarchy_commit
= mrvl_hierarchy_commit
,
1007 .node_stats_update
= mrvl_node_stats_update
,
1008 .node_stats_read
= mrvl_node_stats_read
,