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