1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2018 Marvell International Ltd. 3 * Copyright(c) 2018 Semihalf. 4 * All rights reserved. 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 /** Minimum rate value in Bytes/s */ 17 #define MRVL_RATE_MIN (PP2_PPIO_MIN_CIR * 1000 / 8) 18 19 /** Minimum burst size in Bytes */ 20 #define MRVL_BURST_MIN (PP2_PPIO_MIN_CBS * 1000) 21 22 /** Maximum burst size in Bytes */ 23 #define MRVL_BURST_MAX 256000000 24 25 /** Maximum WRR weight */ 26 #define MRVL_WEIGHT_MAX 255 27 28 /** 29 * Get maximum port rate in Bytes/s. 30 * 31 * @param dev Pointer to the device. 32 * @param rate Pointer to the rate. 33 * @returns 0 on success, negative value otherwise. 34 */ 35 static int 36 mrvl_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 * Initialize traffic manager related data. 67 * 68 * @param dev Pointer to the device. 69 * @returns 0 on success, failure otherwise. 70 */ 71 int 72 mrvl_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 * Cleanup traffic manager related data. 87 * 88 * @param dev Pointer to the device. 89 */ 90 void 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 * Get node using its id. 116 * 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. 120 */ 121 static struct mrvl_tm_node * 122 mrvl_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 * Check whether node is leaf or root. 135 * 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. 141 */ 142 static int 143 mrvl_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 * Get traffic manager capabilities. 172 * 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. 177 */ 178 static int 179 mrvl_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; /* 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; 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 * Get traffic manager hierarchy level capabilities. 226 * 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. 232 */ 233 static int 234 mrvl_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 { /* 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; 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 * Get node capabilities. 297 * 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. 303 */ 304 static int 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) 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 * Get shaper profile using its id. 355 * 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. 359 */ 360 static struct mrvl_tm_shaper_profile * 361 mrvl_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 * Add a new shaper profile. 374 * 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. 380 */ 381 static int 382 mrvl_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id, 383 const 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 * Remove a shaper profile. 449 * 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. 454 */ 455 static int 456 mrvl_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 * Check node parameters. 486 * 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. 495 */ 496 static int 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 const 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 /* 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"); 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 /* 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, 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 * Add a new node. 591 * 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. 601 */ 602 static int 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, const 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 * Delete a node. 690 * 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. 695 */ 696 static int 697 mrvl_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 * Helper for suspending specific tx queue. 739 * 740 * @param dev Pointer to the device. 741 * @param node_id Id used by this node. 742 * @returns 0 on success, negative value otherwise. 743 */ 744 static 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 * Suspend a node. 758 * 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. 763 */ 764 static int 765 mrvl_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 * Resume a node. 804 * 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. 809 */ 810 static int 811 mrvl_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 * Apply traffic manager hierarchy. 845 * 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. 850 */ 851 static int 852 mrvl_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 /* 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; 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 /* reset to defaults in case applied tm hierarchy is empty */ 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; 939 out: 940 if (clear_on_fail) { 941 mrvl_tm_deinit(dev); 942 mrvl_tm_init(dev); 943 } 944 945 return ret; 946 } 947 948 /** 949 * Read statistics counters for current node. 950 * 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. 960 */ 961 static int 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) 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 * Update node statistics. 1030 * 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. 1036 */ 1037 static int 1038 mrvl_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 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, 1088 }; 1089