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