1 /*- 2 * BSD LICENSE 3 * 4 * Copyright(c) 2010-2017 Intel Corporation. All rights reserved. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <rte_malloc.h> 35 36 #include "ixgbe_ethdev.h" 37 38 static int ixgbe_tm_capabilities_get(struct rte_eth_dev *dev, 39 struct rte_tm_capabilities *cap, 40 struct rte_tm_error *error); 41 static int ixgbe_shaper_profile_add(struct rte_eth_dev *dev, 42 uint32_t shaper_profile_id, 43 struct rte_tm_shaper_params *profile, 44 struct rte_tm_error *error); 45 static int ixgbe_shaper_profile_del(struct rte_eth_dev *dev, 46 uint32_t shaper_profile_id, 47 struct rte_tm_error *error); 48 static int ixgbe_node_add(struct rte_eth_dev *dev, uint32_t node_id, 49 uint32_t parent_node_id, uint32_t priority, 50 uint32_t weight, uint32_t level_id, 51 struct rte_tm_node_params *params, 52 struct rte_tm_error *error); 53 static int ixgbe_node_delete(struct rte_eth_dev *dev, uint32_t node_id, 54 struct rte_tm_error *error); 55 static int ixgbe_node_type_get(struct rte_eth_dev *dev, uint32_t node_id, 56 int *is_leaf, struct rte_tm_error *error); 57 static int ixgbe_level_capabilities_get(struct rte_eth_dev *dev, 58 uint32_t level_id, 59 struct rte_tm_level_capabilities *cap, 60 struct rte_tm_error *error); 61 static int ixgbe_node_capabilities_get(struct rte_eth_dev *dev, 62 uint32_t node_id, 63 struct rte_tm_node_capabilities *cap, 64 struct rte_tm_error *error); 65 static int ixgbe_hierarchy_commit(struct rte_eth_dev *dev, 66 int clear_on_fail, 67 struct rte_tm_error *error); 68 69 const struct rte_tm_ops ixgbe_tm_ops = { 70 .capabilities_get = ixgbe_tm_capabilities_get, 71 .shaper_profile_add = ixgbe_shaper_profile_add, 72 .shaper_profile_delete = ixgbe_shaper_profile_del, 73 .node_add = ixgbe_node_add, 74 .node_delete = ixgbe_node_delete, 75 .node_type_get = ixgbe_node_type_get, 76 .level_capabilities_get = ixgbe_level_capabilities_get, 77 .node_capabilities_get = ixgbe_node_capabilities_get, 78 .hierarchy_commit = ixgbe_hierarchy_commit, 79 }; 80 81 int 82 ixgbe_tm_ops_get(struct rte_eth_dev *dev __rte_unused, 83 void *arg) 84 { 85 if (!arg) 86 return -EINVAL; 87 88 *(const void **)arg = &ixgbe_tm_ops; 89 90 return 0; 91 } 92 93 void 94 ixgbe_tm_conf_init(struct rte_eth_dev *dev) 95 { 96 struct ixgbe_tm_conf *tm_conf = 97 IXGBE_DEV_PRIVATE_TO_TM_CONF(dev->data->dev_private); 98 99 /* initialize shaper profile list */ 100 TAILQ_INIT(&tm_conf->shaper_profile_list); 101 102 /* initialize node configuration */ 103 tm_conf->root = NULL; 104 TAILQ_INIT(&tm_conf->queue_list); 105 TAILQ_INIT(&tm_conf->tc_list); 106 tm_conf->nb_tc_node = 0; 107 tm_conf->nb_queue_node = 0; 108 tm_conf->committed = false; 109 } 110 111 void 112 ixgbe_tm_conf_uninit(struct rte_eth_dev *dev) 113 { 114 struct ixgbe_tm_conf *tm_conf = 115 IXGBE_DEV_PRIVATE_TO_TM_CONF(dev->data->dev_private); 116 struct ixgbe_tm_shaper_profile *shaper_profile; 117 struct ixgbe_tm_node *tm_node; 118 119 /* clear node configuration */ 120 while ((tm_node = TAILQ_FIRST(&tm_conf->queue_list))) { 121 TAILQ_REMOVE(&tm_conf->queue_list, tm_node, node); 122 rte_free(tm_node); 123 } 124 tm_conf->nb_queue_node = 0; 125 while ((tm_node = TAILQ_FIRST(&tm_conf->tc_list))) { 126 TAILQ_REMOVE(&tm_conf->tc_list, tm_node, node); 127 rte_free(tm_node); 128 } 129 tm_conf->nb_tc_node = 0; 130 if (tm_conf->root) { 131 rte_free(tm_conf->root); 132 tm_conf->root = NULL; 133 } 134 135 /* Remove all shaper profiles */ 136 while ((shaper_profile = 137 TAILQ_FIRST(&tm_conf->shaper_profile_list))) { 138 TAILQ_REMOVE(&tm_conf->shaper_profile_list, 139 shaper_profile, node); 140 rte_free(shaper_profile); 141 } 142 } 143 144 static inline uint8_t 145 ixgbe_tc_nb_get(struct rte_eth_dev *dev) 146 { 147 struct rte_eth_conf *eth_conf; 148 uint8_t nb_tcs = 0; 149 150 eth_conf = &dev->data->dev_conf; 151 if (eth_conf->txmode.mq_mode == ETH_MQ_TX_DCB) { 152 nb_tcs = eth_conf->tx_adv_conf.dcb_tx_conf.nb_tcs; 153 } else if (eth_conf->txmode.mq_mode == ETH_MQ_TX_VMDQ_DCB) { 154 if (eth_conf->tx_adv_conf.vmdq_dcb_tx_conf.nb_queue_pools == 155 ETH_32_POOLS) 156 nb_tcs = ETH_4_TCS; 157 else 158 nb_tcs = ETH_8_TCS; 159 } else { 160 nb_tcs = 1; 161 } 162 163 return nb_tcs; 164 } 165 166 static int 167 ixgbe_tm_capabilities_get(struct rte_eth_dev *dev, 168 struct rte_tm_capabilities *cap, 169 struct rte_tm_error *error) 170 { 171 struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); 172 uint8_t tc_nb = ixgbe_tc_nb_get(dev); 173 174 if (!cap || !error) 175 return -EINVAL; 176 177 if (tc_nb > hw->mac.max_tx_queues) 178 return -EINVAL; 179 180 error->type = RTE_TM_ERROR_TYPE_NONE; 181 182 /* set all the parameters to 0 first. */ 183 memset(cap, 0, sizeof(struct rte_tm_capabilities)); 184 185 /** 186 * here is the max capability not the current configuration. 187 */ 188 /* port + TCs + queues */ 189 cap->n_nodes_max = 1 + IXGBE_DCB_MAX_TRAFFIC_CLASS + 190 hw->mac.max_tx_queues; 191 cap->n_levels_max = 3; 192 cap->non_leaf_nodes_identical = 1; 193 cap->leaf_nodes_identical = 1; 194 cap->shaper_n_max = cap->n_nodes_max; 195 cap->shaper_private_n_max = cap->n_nodes_max; 196 cap->shaper_private_dual_rate_n_max = 0; 197 cap->shaper_private_rate_min = 0; 198 /* 10Gbps -> 1.25GBps */ 199 cap->shaper_private_rate_max = 1250000000ull; 200 cap->shaper_shared_n_max = 0; 201 cap->shaper_shared_n_nodes_per_shaper_max = 0; 202 cap->shaper_shared_n_shapers_per_node_max = 0; 203 cap->shaper_shared_dual_rate_n_max = 0; 204 cap->shaper_shared_rate_min = 0; 205 cap->shaper_shared_rate_max = 0; 206 cap->sched_n_children_max = hw->mac.max_tx_queues; 207 /** 208 * HW supports SP. But no plan to support it now. 209 * So, all the nodes should have the same priority. 210 */ 211 cap->sched_sp_n_priorities_max = 1; 212 cap->sched_wfq_n_children_per_group_max = 0; 213 cap->sched_wfq_n_groups_max = 0; 214 /** 215 * SW only supports fair round robin now. 216 * So, all the nodes should have the same weight. 217 */ 218 cap->sched_wfq_weight_max = 1; 219 cap->cman_head_drop_supported = 0; 220 cap->dynamic_update_mask = 0; 221 cap->shaper_pkt_length_adjust_min = RTE_TM_ETH_FRAMING_OVERHEAD; 222 cap->shaper_pkt_length_adjust_max = RTE_TM_ETH_FRAMING_OVERHEAD_FCS; 223 cap->cman_wred_context_n_max = 0; 224 cap->cman_wred_context_private_n_max = 0; 225 cap->cman_wred_context_shared_n_max = 0; 226 cap->cman_wred_context_shared_n_nodes_per_context_max = 0; 227 cap->cman_wred_context_shared_n_contexts_per_node_max = 0; 228 cap->stats_mask = 0; 229 230 return 0; 231 } 232 233 static inline struct ixgbe_tm_shaper_profile * 234 ixgbe_shaper_profile_search(struct rte_eth_dev *dev, 235 uint32_t shaper_profile_id) 236 { 237 struct ixgbe_tm_conf *tm_conf = 238 IXGBE_DEV_PRIVATE_TO_TM_CONF(dev->data->dev_private); 239 struct ixgbe_shaper_profile_list *shaper_profile_list = 240 &tm_conf->shaper_profile_list; 241 struct ixgbe_tm_shaper_profile *shaper_profile; 242 243 TAILQ_FOREACH(shaper_profile, shaper_profile_list, node) { 244 if (shaper_profile_id == shaper_profile->shaper_profile_id) 245 return shaper_profile; 246 } 247 248 return NULL; 249 } 250 251 static int 252 ixgbe_shaper_profile_param_check(struct rte_tm_shaper_params *profile, 253 struct rte_tm_error *error) 254 { 255 /* min rate not supported */ 256 if (profile->committed.rate) { 257 error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_RATE; 258 error->message = "committed rate not supported"; 259 return -EINVAL; 260 } 261 /* min bucket size not supported */ 262 if (profile->committed.size) { 263 error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_SIZE; 264 error->message = "committed bucket size not supported"; 265 return -EINVAL; 266 } 267 /* max bucket size not supported */ 268 if (profile->peak.size) { 269 error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE; 270 error->message = "peak bucket size not supported"; 271 return -EINVAL; 272 } 273 /* length adjustment not supported */ 274 if (profile->pkt_length_adjust) { 275 error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PKT_ADJUST_LEN; 276 error->message = "packet length adjustment not supported"; 277 return -EINVAL; 278 } 279 280 return 0; 281 } 282 283 static int 284 ixgbe_shaper_profile_add(struct rte_eth_dev *dev, 285 uint32_t shaper_profile_id, 286 struct rte_tm_shaper_params *profile, 287 struct rte_tm_error *error) 288 { 289 struct ixgbe_tm_conf *tm_conf = 290 IXGBE_DEV_PRIVATE_TO_TM_CONF(dev->data->dev_private); 291 struct ixgbe_tm_shaper_profile *shaper_profile; 292 int ret; 293 294 if (!profile || !error) 295 return -EINVAL; 296 297 ret = ixgbe_shaper_profile_param_check(profile, error); 298 if (ret) 299 return ret; 300 301 shaper_profile = ixgbe_shaper_profile_search(dev, shaper_profile_id); 302 303 if (shaper_profile) { 304 error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID; 305 error->message = "profile ID exist"; 306 return -EINVAL; 307 } 308 309 shaper_profile = rte_zmalloc("ixgbe_tm_shaper_profile", 310 sizeof(struct ixgbe_tm_shaper_profile), 311 0); 312 if (!shaper_profile) 313 return -ENOMEM; 314 shaper_profile->shaper_profile_id = shaper_profile_id; 315 rte_memcpy(&shaper_profile->profile, profile, 316 sizeof(struct rte_tm_shaper_params)); 317 TAILQ_INSERT_TAIL(&tm_conf->shaper_profile_list, 318 shaper_profile, node); 319 320 return 0; 321 } 322 323 static int 324 ixgbe_shaper_profile_del(struct rte_eth_dev *dev, 325 uint32_t shaper_profile_id, 326 struct rte_tm_error *error) 327 { 328 struct ixgbe_tm_conf *tm_conf = 329 IXGBE_DEV_PRIVATE_TO_TM_CONF(dev->data->dev_private); 330 struct ixgbe_tm_shaper_profile *shaper_profile; 331 332 if (!error) 333 return -EINVAL; 334 335 shaper_profile = ixgbe_shaper_profile_search(dev, shaper_profile_id); 336 337 if (!shaper_profile) { 338 error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID; 339 error->message = "profile ID not exist"; 340 return -EINVAL; 341 } 342 343 /* don't delete a profile if it's used by one or several nodes */ 344 if (shaper_profile->reference_count) { 345 error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE; 346 error->message = "profile in use"; 347 return -EINVAL; 348 } 349 350 TAILQ_REMOVE(&tm_conf->shaper_profile_list, shaper_profile, node); 351 rte_free(shaper_profile); 352 353 return 0; 354 } 355 356 static inline struct ixgbe_tm_node * 357 ixgbe_tm_node_search(struct rte_eth_dev *dev, uint32_t node_id, 358 enum ixgbe_tm_node_type *node_type) 359 { 360 struct ixgbe_tm_conf *tm_conf = 361 IXGBE_DEV_PRIVATE_TO_TM_CONF(dev->data->dev_private); 362 struct ixgbe_tm_node *tm_node; 363 364 if (tm_conf->root && tm_conf->root->id == node_id) { 365 *node_type = IXGBE_TM_NODE_TYPE_PORT; 366 return tm_conf->root; 367 } 368 369 TAILQ_FOREACH(tm_node, &tm_conf->tc_list, node) { 370 if (tm_node->id == node_id) { 371 *node_type = IXGBE_TM_NODE_TYPE_TC; 372 return tm_node; 373 } 374 } 375 376 TAILQ_FOREACH(tm_node, &tm_conf->queue_list, node) { 377 if (tm_node->id == node_id) { 378 *node_type = IXGBE_TM_NODE_TYPE_QUEUE; 379 return tm_node; 380 } 381 } 382 383 return NULL; 384 } 385 386 static void 387 ixgbe_queue_base_nb_get(struct rte_eth_dev *dev, uint16_t tc_node_no, 388 uint16_t *base, uint16_t *nb) 389 { 390 uint8_t nb_tcs = ixgbe_tc_nb_get(dev); 391 struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); 392 uint16_t vf_num = pci_dev->max_vfs; 393 394 *base = 0; 395 *nb = 0; 396 397 /* VT on */ 398 if (vf_num) { 399 /* no DCB */ 400 if (nb_tcs == 1) { 401 if (vf_num >= ETH_32_POOLS) { 402 *nb = 2; 403 *base = vf_num * 2; 404 } else if (vf_num >= ETH_16_POOLS) { 405 *nb = 4; 406 *base = vf_num * 4; 407 } else { 408 *nb = 8; 409 *base = vf_num * 8; 410 } 411 } else { 412 /* DCB */ 413 *nb = 1; 414 *base = vf_num * nb_tcs + tc_node_no; 415 } 416 } else { 417 /* VT off */ 418 if (nb_tcs == ETH_8_TCS) { 419 switch (tc_node_no) { 420 case 0: 421 *base = 0; 422 *nb = 32; 423 break; 424 case 1: 425 *base = 32; 426 *nb = 32; 427 break; 428 case 2: 429 *base = 64; 430 *nb = 16; 431 break; 432 case 3: 433 *base = 80; 434 *nb = 16; 435 break; 436 case 4: 437 *base = 96; 438 *nb = 8; 439 break; 440 case 5: 441 *base = 104; 442 *nb = 8; 443 break; 444 case 6: 445 *base = 112; 446 *nb = 8; 447 break; 448 case 7: 449 *base = 120; 450 *nb = 8; 451 break; 452 default: 453 return; 454 } 455 } else { 456 switch (tc_node_no) { 457 /** 458 * If no VF and no DCB, only 64 queues can be used. 459 * This case also be covered by this "case 0". 460 */ 461 case 0: 462 *base = 0; 463 *nb = 64; 464 break; 465 case 1: 466 *base = 64; 467 *nb = 32; 468 break; 469 case 2: 470 *base = 96; 471 *nb = 16; 472 break; 473 case 3: 474 *base = 112; 475 *nb = 16; 476 break; 477 default: 478 return; 479 } 480 } 481 } 482 } 483 484 static int 485 ixgbe_node_param_check(struct rte_eth_dev *dev, uint32_t node_id, 486 uint32_t priority, uint32_t weight, 487 struct rte_tm_node_params *params, 488 struct rte_tm_error *error) 489 { 490 if (node_id == RTE_TM_NODE_ID_NULL) { 491 error->type = RTE_TM_ERROR_TYPE_NODE_ID; 492 error->message = "invalid node id"; 493 return -EINVAL; 494 } 495 496 if (priority) { 497 error->type = RTE_TM_ERROR_TYPE_NODE_PRIORITY; 498 error->message = "priority should be 0"; 499 return -EINVAL; 500 } 501 502 if (weight != 1) { 503 error->type = RTE_TM_ERROR_TYPE_NODE_WEIGHT; 504 error->message = "weight must be 1"; 505 return -EINVAL; 506 } 507 508 /* not support shared shaper */ 509 if (params->shared_shaper_id) { 510 error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_SHAPER_ID; 511 error->message = "shared shaper not supported"; 512 return -EINVAL; 513 } 514 if (params->n_shared_shapers) { 515 error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS; 516 error->message = "shared shaper not supported"; 517 return -EINVAL; 518 } 519 520 /* for non-leaf node */ 521 if (node_id >= dev->data->nb_tx_queues) { 522 /* check the unsupported parameters */ 523 if (params->nonleaf.wfq_weight_mode) { 524 error->type = 525 RTE_TM_ERROR_TYPE_NODE_PARAMS_WFQ_WEIGHT_MODE; 526 error->message = "WFQ not supported"; 527 return -EINVAL; 528 } 529 if (params->nonleaf.n_sp_priorities != 1) { 530 error->type = 531 RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SP_PRIORITIES; 532 error->message = "SP priority not supported"; 533 return -EINVAL; 534 } else if (params->nonleaf.wfq_weight_mode && 535 !(*params->nonleaf.wfq_weight_mode)) { 536 error->type = 537 RTE_TM_ERROR_TYPE_NODE_PARAMS_WFQ_WEIGHT_MODE; 538 error->message = "WFP should be byte mode"; 539 return -EINVAL; 540 } 541 542 return 0; 543 } 544 545 /* for leaf node */ 546 /* check the unsupported parameters */ 547 if (params->leaf.cman) { 548 error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_CMAN; 549 error->message = "Congestion management not supported"; 550 return -EINVAL; 551 } 552 if (params->leaf.wred.wred_profile_id != 553 RTE_TM_WRED_PROFILE_ID_NONE) { 554 error->type = 555 RTE_TM_ERROR_TYPE_NODE_PARAMS_WRED_PROFILE_ID; 556 error->message = "WRED not supported"; 557 return -EINVAL; 558 } 559 if (params->leaf.wred.shared_wred_context_id) { 560 error->type = 561 RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_WRED_CONTEXT_ID; 562 error->message = "WRED not supported"; 563 return -EINVAL; 564 } 565 if (params->leaf.wred.n_shared_wred_contexts) { 566 error->type = 567 RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_WRED_CONTEXTS; 568 error->message = "WRED not supported"; 569 return -EINVAL; 570 } 571 572 return 0; 573 } 574 575 /** 576 * Now the TC and queue configuration is controlled by DCB. 577 * We need check if the node configuration follows the DCB configuration. 578 * In the future, we may use TM to cover DCB. 579 */ 580 static int 581 ixgbe_node_add(struct rte_eth_dev *dev, uint32_t node_id, 582 uint32_t parent_node_id, uint32_t priority, 583 uint32_t weight, uint32_t level_id, 584 struct rte_tm_node_params *params, 585 struct rte_tm_error *error) 586 { 587 struct ixgbe_tm_conf *tm_conf = 588 IXGBE_DEV_PRIVATE_TO_TM_CONF(dev->data->dev_private); 589 enum ixgbe_tm_node_type node_type = IXGBE_TM_NODE_TYPE_MAX; 590 enum ixgbe_tm_node_type parent_node_type = IXGBE_TM_NODE_TYPE_MAX; 591 struct ixgbe_tm_shaper_profile *shaper_profile = NULL; 592 struct ixgbe_tm_node *tm_node; 593 struct ixgbe_tm_node *parent_node; 594 uint8_t nb_tcs; 595 uint16_t q_base = 0; 596 uint16_t q_nb = 0; 597 int ret; 598 599 if (!params || !error) 600 return -EINVAL; 601 602 /* if already committed */ 603 if (tm_conf->committed) { 604 error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED; 605 error->message = "already committed"; 606 return -EINVAL; 607 } 608 609 ret = ixgbe_node_param_check(dev, node_id, priority, weight, 610 params, error); 611 if (ret) 612 return ret; 613 614 /* check if the node ID is already used */ 615 if (ixgbe_tm_node_search(dev, node_id, &node_type)) { 616 error->type = RTE_TM_ERROR_TYPE_NODE_ID; 617 error->message = "node id already used"; 618 return -EINVAL; 619 } 620 621 /* check the shaper profile id */ 622 if (params->shaper_profile_id != RTE_TM_SHAPER_PROFILE_ID_NONE) { 623 shaper_profile = ixgbe_shaper_profile_search( 624 dev, params->shaper_profile_id); 625 if (!shaper_profile) { 626 error->type = 627 RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID; 628 error->message = "shaper profile not exist"; 629 return -EINVAL; 630 } 631 } 632 633 /* root node if not have a parent */ 634 if (parent_node_id == RTE_TM_NODE_ID_NULL) { 635 /* check level */ 636 if (level_id != RTE_TM_NODE_LEVEL_ID_ANY && 637 level_id > IXGBE_TM_NODE_TYPE_PORT) { 638 error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS; 639 error->message = "Wrong level"; 640 return -EINVAL; 641 } 642 643 /* obviously no more than one root */ 644 if (tm_conf->root) { 645 error->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID; 646 error->message = "already have a root"; 647 return -EINVAL; 648 } 649 650 /* add the root node */ 651 tm_node = rte_zmalloc("ixgbe_tm_node", 652 sizeof(struct ixgbe_tm_node), 653 0); 654 if (!tm_node) 655 return -ENOMEM; 656 tm_node->id = node_id; 657 tm_node->priority = priority; 658 tm_node->weight = weight; 659 tm_node->reference_count = 0; 660 tm_node->no = 0; 661 tm_node->parent = NULL; 662 tm_node->shaper_profile = shaper_profile; 663 rte_memcpy(&tm_node->params, params, 664 sizeof(struct rte_tm_node_params)); 665 tm_conf->root = tm_node; 666 667 /* increase the reference counter of the shaper profile */ 668 if (shaper_profile) 669 shaper_profile->reference_count++; 670 671 return 0; 672 } 673 674 /* TC or queue node */ 675 /* check the parent node */ 676 parent_node = ixgbe_tm_node_search(dev, parent_node_id, 677 &parent_node_type); 678 if (!parent_node) { 679 error->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID; 680 error->message = "parent not exist"; 681 return -EINVAL; 682 } 683 if (parent_node_type != IXGBE_TM_NODE_TYPE_PORT && 684 parent_node_type != IXGBE_TM_NODE_TYPE_TC) { 685 error->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID; 686 error->message = "parent is not port or TC"; 687 return -EINVAL; 688 } 689 /* check level */ 690 if (level_id != RTE_TM_NODE_LEVEL_ID_ANY && 691 level_id != parent_node_type + 1) { 692 error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS; 693 error->message = "Wrong level"; 694 return -EINVAL; 695 } 696 697 /* check the node number */ 698 if (parent_node_type == IXGBE_TM_NODE_TYPE_PORT) { 699 /* check TC number */ 700 nb_tcs = ixgbe_tc_nb_get(dev); 701 if (tm_conf->nb_tc_node >= nb_tcs) { 702 error->type = RTE_TM_ERROR_TYPE_NODE_ID; 703 error->message = "too many TCs"; 704 return -EINVAL; 705 } 706 } else { 707 /* check queue number */ 708 if (tm_conf->nb_queue_node >= dev->data->nb_tx_queues) { 709 error->type = RTE_TM_ERROR_TYPE_NODE_ID; 710 error->message = "too many queues"; 711 return -EINVAL; 712 } 713 714 ixgbe_queue_base_nb_get(dev, parent_node->no, &q_base, &q_nb); 715 if (parent_node->reference_count >= q_nb) { 716 error->type = RTE_TM_ERROR_TYPE_NODE_ID; 717 error->message = "too many queues than TC supported"; 718 return -EINVAL; 719 } 720 721 /** 722 * check the node id. 723 * For queue, the node id means queue id. 724 */ 725 if (node_id >= dev->data->nb_tx_queues) { 726 error->type = RTE_TM_ERROR_TYPE_NODE_ID; 727 error->message = "too large queue id"; 728 return -EINVAL; 729 } 730 } 731 732 /* add the TC or queue node */ 733 tm_node = rte_zmalloc("ixgbe_tm_node", 734 sizeof(struct ixgbe_tm_node), 735 0); 736 if (!tm_node) 737 return -ENOMEM; 738 tm_node->id = node_id; 739 tm_node->priority = priority; 740 tm_node->weight = weight; 741 tm_node->reference_count = 0; 742 tm_node->parent = parent_node; 743 tm_node->shaper_profile = shaper_profile; 744 rte_memcpy(&tm_node->params, params, 745 sizeof(struct rte_tm_node_params)); 746 if (parent_node_type == IXGBE_TM_NODE_TYPE_PORT) { 747 tm_node->no = parent_node->reference_count; 748 TAILQ_INSERT_TAIL(&tm_conf->tc_list, 749 tm_node, node); 750 tm_conf->nb_tc_node++; 751 } else { 752 tm_node->no = q_base + parent_node->reference_count; 753 TAILQ_INSERT_TAIL(&tm_conf->queue_list, 754 tm_node, node); 755 tm_conf->nb_queue_node++; 756 } 757 tm_node->parent->reference_count++; 758 759 /* increase the reference counter of the shaper profile */ 760 if (shaper_profile) 761 shaper_profile->reference_count++; 762 763 return 0; 764 } 765 766 static int 767 ixgbe_node_delete(struct rte_eth_dev *dev, uint32_t node_id, 768 struct rte_tm_error *error) 769 { 770 struct ixgbe_tm_conf *tm_conf = 771 IXGBE_DEV_PRIVATE_TO_TM_CONF(dev->data->dev_private); 772 enum ixgbe_tm_node_type node_type = IXGBE_TM_NODE_TYPE_MAX; 773 struct ixgbe_tm_node *tm_node; 774 775 if (!error) 776 return -EINVAL; 777 778 /* if already committed */ 779 if (tm_conf->committed) { 780 error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED; 781 error->message = "already committed"; 782 return -EINVAL; 783 } 784 785 if (node_id == RTE_TM_NODE_ID_NULL) { 786 error->type = RTE_TM_ERROR_TYPE_NODE_ID; 787 error->message = "invalid node id"; 788 return -EINVAL; 789 } 790 791 /* check the if the node id exists */ 792 tm_node = ixgbe_tm_node_search(dev, node_id, &node_type); 793 if (!tm_node) { 794 error->type = RTE_TM_ERROR_TYPE_NODE_ID; 795 error->message = "no such node"; 796 return -EINVAL; 797 } 798 799 /* the node should have no child */ 800 if (tm_node->reference_count) { 801 error->type = RTE_TM_ERROR_TYPE_NODE_ID; 802 error->message = 803 "cannot delete a node which has children"; 804 return -EINVAL; 805 } 806 807 /* root node */ 808 if (node_type == IXGBE_TM_NODE_TYPE_PORT) { 809 if (tm_node->shaper_profile) 810 tm_node->shaper_profile->reference_count--; 811 rte_free(tm_node); 812 tm_conf->root = NULL; 813 return 0; 814 } 815 816 /* TC or queue node */ 817 if (tm_node->shaper_profile) 818 tm_node->shaper_profile->reference_count--; 819 tm_node->parent->reference_count--; 820 if (node_type == IXGBE_TM_NODE_TYPE_TC) { 821 TAILQ_REMOVE(&tm_conf->tc_list, tm_node, node); 822 tm_conf->nb_tc_node--; 823 } else { 824 TAILQ_REMOVE(&tm_conf->queue_list, tm_node, node); 825 tm_conf->nb_queue_node--; 826 } 827 rte_free(tm_node); 828 829 return 0; 830 } 831 832 static int 833 ixgbe_node_type_get(struct rte_eth_dev *dev, uint32_t node_id, 834 int *is_leaf, struct rte_tm_error *error) 835 { 836 enum ixgbe_tm_node_type node_type = IXGBE_TM_NODE_TYPE_MAX; 837 struct ixgbe_tm_node *tm_node; 838 839 if (!is_leaf || !error) 840 return -EINVAL; 841 842 if (node_id == RTE_TM_NODE_ID_NULL) { 843 error->type = RTE_TM_ERROR_TYPE_NODE_ID; 844 error->message = "invalid node id"; 845 return -EINVAL; 846 } 847 848 /* check if the node id exists */ 849 tm_node = ixgbe_tm_node_search(dev, node_id, &node_type); 850 if (!tm_node) { 851 error->type = RTE_TM_ERROR_TYPE_NODE_ID; 852 error->message = "no such node"; 853 return -EINVAL; 854 } 855 856 if (node_type == IXGBE_TM_NODE_TYPE_QUEUE) 857 *is_leaf = true; 858 else 859 *is_leaf = false; 860 861 return 0; 862 } 863 864 static int 865 ixgbe_level_capabilities_get(struct rte_eth_dev *dev, 866 uint32_t level_id, 867 struct rte_tm_level_capabilities *cap, 868 struct rte_tm_error *error) 869 { 870 struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); 871 872 if (!cap || !error) 873 return -EINVAL; 874 875 if (level_id >= IXGBE_TM_NODE_TYPE_MAX) { 876 error->type = RTE_TM_ERROR_TYPE_LEVEL_ID; 877 error->message = "too deep level"; 878 return -EINVAL; 879 } 880 881 /* root node */ 882 if (level_id == IXGBE_TM_NODE_TYPE_PORT) { 883 cap->n_nodes_max = 1; 884 cap->n_nodes_nonleaf_max = 1; 885 cap->n_nodes_leaf_max = 0; 886 } else if (level_id == IXGBE_TM_NODE_TYPE_TC) { 887 /* TC */ 888 cap->n_nodes_max = IXGBE_DCB_MAX_TRAFFIC_CLASS; 889 cap->n_nodes_nonleaf_max = IXGBE_DCB_MAX_TRAFFIC_CLASS; 890 cap->n_nodes_leaf_max = 0; 891 } else { 892 /* queue */ 893 cap->n_nodes_max = hw->mac.max_tx_queues; 894 cap->n_nodes_nonleaf_max = 0; 895 cap->n_nodes_leaf_max = hw->mac.max_tx_queues; 896 } 897 898 cap->non_leaf_nodes_identical = true; 899 cap->leaf_nodes_identical = true; 900 901 if (level_id != IXGBE_TM_NODE_TYPE_QUEUE) { 902 cap->nonleaf.shaper_private_supported = true; 903 cap->nonleaf.shaper_private_dual_rate_supported = false; 904 cap->nonleaf.shaper_private_rate_min = 0; 905 /* 10Gbps -> 1.25GBps */ 906 cap->nonleaf.shaper_private_rate_max = 1250000000ull; 907 cap->nonleaf.shaper_shared_n_max = 0; 908 if (level_id == IXGBE_TM_NODE_TYPE_PORT) 909 cap->nonleaf.sched_n_children_max = 910 IXGBE_DCB_MAX_TRAFFIC_CLASS; 911 else 912 cap->nonleaf.sched_n_children_max = 913 hw->mac.max_tx_queues; 914 cap->nonleaf.sched_sp_n_priorities_max = 1; 915 cap->nonleaf.sched_wfq_n_children_per_group_max = 0; 916 cap->nonleaf.sched_wfq_n_groups_max = 0; 917 cap->nonleaf.sched_wfq_weight_max = 1; 918 cap->nonleaf.stats_mask = 0; 919 920 return 0; 921 } 922 923 /* queue node */ 924 cap->leaf.shaper_private_supported = true; 925 cap->leaf.shaper_private_dual_rate_supported = false; 926 cap->leaf.shaper_private_rate_min = 0; 927 /* 10Gbps -> 1.25GBps */ 928 cap->leaf.shaper_private_rate_max = 1250000000ull; 929 cap->leaf.shaper_shared_n_max = 0; 930 cap->leaf.cman_head_drop_supported = false; 931 cap->leaf.cman_wred_context_private_supported = true; 932 cap->leaf.cman_wred_context_shared_n_max = 0; 933 cap->leaf.stats_mask = 0; 934 935 return 0; 936 } 937 938 static int 939 ixgbe_node_capabilities_get(struct rte_eth_dev *dev, 940 uint32_t node_id, 941 struct rte_tm_node_capabilities *cap, 942 struct rte_tm_error *error) 943 { 944 struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); 945 enum ixgbe_tm_node_type node_type = IXGBE_TM_NODE_TYPE_MAX; 946 struct ixgbe_tm_node *tm_node; 947 948 if (!cap || !error) 949 return -EINVAL; 950 951 if (node_id == RTE_TM_NODE_ID_NULL) { 952 error->type = RTE_TM_ERROR_TYPE_NODE_ID; 953 error->message = "invalid node id"; 954 return -EINVAL; 955 } 956 957 /* check if the node id exists */ 958 tm_node = ixgbe_tm_node_search(dev, node_id, &node_type); 959 if (!tm_node) { 960 error->type = RTE_TM_ERROR_TYPE_NODE_ID; 961 error->message = "no such node"; 962 return -EINVAL; 963 } 964 965 cap->shaper_private_supported = true; 966 cap->shaper_private_dual_rate_supported = false; 967 cap->shaper_private_rate_min = 0; 968 /* 10Gbps -> 1.25GBps */ 969 cap->shaper_private_rate_max = 1250000000ull; 970 cap->shaper_shared_n_max = 0; 971 972 if (node_type == IXGBE_TM_NODE_TYPE_QUEUE) { 973 cap->leaf.cman_head_drop_supported = false; 974 cap->leaf.cman_wred_context_private_supported = true; 975 cap->leaf.cman_wred_context_shared_n_max = 0; 976 } else { 977 if (node_type == IXGBE_TM_NODE_TYPE_PORT) 978 cap->nonleaf.sched_n_children_max = 979 IXGBE_DCB_MAX_TRAFFIC_CLASS; 980 else 981 cap->nonleaf.sched_n_children_max = 982 hw->mac.max_tx_queues; 983 cap->nonleaf.sched_sp_n_priorities_max = 1; 984 cap->nonleaf.sched_wfq_n_children_per_group_max = 0; 985 cap->nonleaf.sched_wfq_n_groups_max = 0; 986 cap->nonleaf.sched_wfq_weight_max = 1; 987 } 988 989 cap->stats_mask = 0; 990 991 return 0; 992 } 993 994 static int 995 ixgbe_hierarchy_commit(struct rte_eth_dev *dev, 996 int clear_on_fail, 997 struct rte_tm_error *error) 998 { 999 struct ixgbe_tm_conf *tm_conf = 1000 IXGBE_DEV_PRIVATE_TO_TM_CONF(dev->data->dev_private); 1001 struct ixgbe_tm_node *tm_node; 1002 uint64_t bw; 1003 int ret; 1004 1005 if (!error) 1006 return -EINVAL; 1007 1008 /* check the setting */ 1009 if (!tm_conf->root) 1010 goto done; 1011 1012 /* not support port max bandwidth yet */ 1013 if (tm_conf->root->shaper_profile && 1014 tm_conf->root->shaper_profile->profile.peak.rate) { 1015 error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE; 1016 error->message = "no port max bandwidth"; 1017 goto fail_clear; 1018 } 1019 1020 /* HW not support TC max bandwidth */ 1021 TAILQ_FOREACH(tm_node, &tm_conf->tc_list, node) { 1022 if (tm_node->shaper_profile && 1023 tm_node->shaper_profile->profile.peak.rate) { 1024 error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE; 1025 error->message = "no TC max bandwidth"; 1026 goto fail_clear; 1027 } 1028 } 1029 1030 /* queue max bandwidth */ 1031 TAILQ_FOREACH(tm_node, &tm_conf->queue_list, node) { 1032 if (tm_node->shaper_profile) 1033 bw = tm_node->shaper_profile->profile.peak.rate; 1034 else 1035 bw = 0; 1036 if (bw) { 1037 /* interpret Bps to Mbps */ 1038 bw = bw * 8 / 1000 / 1000; 1039 ret = ixgbe_set_queue_rate_limit(dev, tm_node->no, bw); 1040 if (ret) { 1041 error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE; 1042 error->message = 1043 "failed to set queue max bandwidth"; 1044 goto fail_clear; 1045 } 1046 } 1047 } 1048 1049 done: 1050 tm_conf->committed = true; 1051 return 0; 1052 1053 fail_clear: 1054 /* clear all the traffic manager configuration */ 1055 if (clear_on_fail) { 1056 ixgbe_tm_conf_uninit(dev); 1057 ixgbe_tm_conf_init(dev); 1058 } 1059 return -EINVAL; 1060 } 1061