1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2015 6WIND S.A. 3 * Copyright 2015 Mellanox Technologies, Ltd 4 */ 5 6 #include <stddef.h> 7 #include <unistd.h> 8 #include <string.h> 9 #include <stdint.h> 10 #include <stdlib.h> 11 #include <errno.h> 12 #include <net/if.h> 13 #include <sys/mman.h> 14 #include <linux/rtnetlink.h> 15 16 #include <rte_malloc.h> 17 #include <rte_ethdev_driver.h> 18 #include <rte_ethdev_pci.h> 19 #include <rte_pci.h> 20 #include <rte_bus_pci.h> 21 #include <rte_common.h> 22 #include <rte_kvargs.h> 23 #include <rte_rwlock.h> 24 #include <rte_spinlock.h> 25 #include <rte_string_fns.h> 26 #include <rte_alarm.h> 27 28 #include <mlx5_glue.h> 29 #include <mlx5_devx_cmds.h> 30 #include <mlx5_common.h> 31 #include <mlx5_common_os.h> 32 #include <mlx5_common_mp.h> 33 #include <mlx5_common_pci.h> 34 #include <mlx5_malloc.h> 35 36 #include "mlx5_defs.h" 37 #include "mlx5.h" 38 #include "mlx5_utils.h" 39 #include "mlx5_rxtx.h" 40 #include "mlx5_autoconf.h" 41 #include "mlx5_mr.h" 42 #include "mlx5_flow.h" 43 #include "rte_pmd_mlx5.h" 44 45 /* Device parameter to enable RX completion queue compression. */ 46 #define MLX5_RXQ_CQE_COMP_EN "rxq_cqe_comp_en" 47 48 /* Device parameter to enable RX completion entry padding to 128B. */ 49 #define MLX5_RXQ_CQE_PAD_EN "rxq_cqe_pad_en" 50 51 /* Device parameter to enable padding Rx packet to cacheline size. */ 52 #define MLX5_RXQ_PKT_PAD_EN "rxq_pkt_pad_en" 53 54 /* Device parameter to enable Multi-Packet Rx queue. */ 55 #define MLX5_RX_MPRQ_EN "mprq_en" 56 57 /* Device parameter to configure log 2 of the number of strides for MPRQ. */ 58 #define MLX5_RX_MPRQ_LOG_STRIDE_NUM "mprq_log_stride_num" 59 60 /* Device parameter to configure log 2 of the stride size for MPRQ. */ 61 #define MLX5_RX_MPRQ_LOG_STRIDE_SIZE "mprq_log_stride_size" 62 63 /* Device parameter to limit the size of memcpy'd packet for MPRQ. */ 64 #define MLX5_RX_MPRQ_MAX_MEMCPY_LEN "mprq_max_memcpy_len" 65 66 /* Device parameter to set the minimum number of Rx queues to enable MPRQ. */ 67 #define MLX5_RXQS_MIN_MPRQ "rxqs_min_mprq" 68 69 /* Device parameter to configure inline send. Deprecated, ignored.*/ 70 #define MLX5_TXQ_INLINE "txq_inline" 71 72 /* Device parameter to limit packet size to inline with ordinary SEND. */ 73 #define MLX5_TXQ_INLINE_MAX "txq_inline_max" 74 75 /* Device parameter to configure minimal data size to inline. */ 76 #define MLX5_TXQ_INLINE_MIN "txq_inline_min" 77 78 /* Device parameter to limit packet size to inline with Enhanced MPW. */ 79 #define MLX5_TXQ_INLINE_MPW "txq_inline_mpw" 80 81 /* 82 * Device parameter to configure the number of TX queues threshold for 83 * enabling inline send. 84 */ 85 #define MLX5_TXQS_MIN_INLINE "txqs_min_inline" 86 87 /* 88 * Device parameter to configure the number of TX queues threshold for 89 * enabling vectorized Tx, deprecated, ignored (no vectorized Tx routines). 90 */ 91 #define MLX5_TXQS_MAX_VEC "txqs_max_vec" 92 93 /* Device parameter to enable multi-packet send WQEs. */ 94 #define MLX5_TXQ_MPW_EN "txq_mpw_en" 95 96 /* 97 * Device parameter to force doorbell register mapping 98 * to non-cahed region eliminating the extra write memory barrier. 99 */ 100 #define MLX5_TX_DB_NC "tx_db_nc" 101 102 /* 103 * Device parameter to include 2 dsegs in the title WQEBB. 104 * Deprecated, ignored. 105 */ 106 #define MLX5_TXQ_MPW_HDR_DSEG_EN "txq_mpw_hdr_dseg_en" 107 108 /* 109 * Device parameter to limit the size of inlining packet. 110 * Deprecated, ignored. 111 */ 112 #define MLX5_TXQ_MAX_INLINE_LEN "txq_max_inline_len" 113 114 /* 115 * Device parameter to enable Tx scheduling on timestamps 116 * and specify the packet pacing granularity in nanoseconds. 117 */ 118 #define MLX5_TX_PP "tx_pp" 119 120 /* 121 * Device parameter to specify skew in nanoseconds on Tx datapath, 122 * it represents the time between SQ start WQE processing and 123 * appearing actual packet data on the wire. 124 */ 125 #define MLX5_TX_SKEW "tx_skew" 126 127 /* 128 * Device parameter to enable hardware Tx vector. 129 * Deprecated, ignored (no vectorized Tx routines anymore). 130 */ 131 #define MLX5_TX_VEC_EN "tx_vec_en" 132 133 /* Device parameter to enable hardware Rx vector. */ 134 #define MLX5_RX_VEC_EN "rx_vec_en" 135 136 /* Allow L3 VXLAN flow creation. */ 137 #define MLX5_L3_VXLAN_EN "l3_vxlan_en" 138 139 /* Activate DV E-Switch flow steering. */ 140 #define MLX5_DV_ESW_EN "dv_esw_en" 141 142 /* Activate DV flow steering. */ 143 #define MLX5_DV_FLOW_EN "dv_flow_en" 144 145 /* Enable extensive flow metadata support. */ 146 #define MLX5_DV_XMETA_EN "dv_xmeta_en" 147 148 /* Device parameter to let the user manage the lacp traffic of bonded device */ 149 #define MLX5_LACP_BY_USER "lacp_by_user" 150 151 /* Activate Netlink support in VF mode. */ 152 #define MLX5_VF_NL_EN "vf_nl_en" 153 154 /* Enable extending memsegs when creating a MR. */ 155 #define MLX5_MR_EXT_MEMSEG_EN "mr_ext_memseg_en" 156 157 /* Select port representors to instantiate. */ 158 #define MLX5_REPRESENTOR "representor" 159 160 /* Device parameter to configure the maximum number of dump files per queue. */ 161 #define MLX5_MAX_DUMP_FILES_NUM "max_dump_files_num" 162 163 /* Configure timeout of LRO session (in microseconds). */ 164 #define MLX5_LRO_TIMEOUT_USEC "lro_timeout_usec" 165 166 /* 167 * Device parameter to configure the total data buffer size for a single 168 * hairpin queue (logarithm value). 169 */ 170 #define MLX5_HP_BUF_SIZE "hp_buf_log_sz" 171 172 /* Flow memory reclaim mode. */ 173 #define MLX5_RECLAIM_MEM "reclaim_mem_mode" 174 175 /* The default memory allocator used in PMD. */ 176 #define MLX5_SYS_MEM_EN "sys_mem_en" 177 /* Decap will be used or not. */ 178 #define MLX5_DECAP_EN "decap_en" 179 180 /* Shared memory between primary and secondary processes. */ 181 struct mlx5_shared_data *mlx5_shared_data; 182 183 /** Driver-specific log messages type. */ 184 int mlx5_logtype; 185 186 static LIST_HEAD(, mlx5_dev_ctx_shared) mlx5_dev_ctx_list = 187 LIST_HEAD_INITIALIZER(); 188 static pthread_mutex_t mlx5_dev_ctx_list_mutex = PTHREAD_MUTEX_INITIALIZER; 189 190 static const struct mlx5_indexed_pool_config mlx5_ipool_cfg[] = { 191 #ifdef HAVE_IBV_FLOW_DV_SUPPORT 192 { 193 .size = sizeof(struct mlx5_flow_dv_encap_decap_resource), 194 .trunk_size = 64, 195 .grow_trunk = 3, 196 .grow_shift = 2, 197 .need_lock = 0, 198 .release_mem_en = 1, 199 .malloc = mlx5_malloc, 200 .free = mlx5_free, 201 .type = "mlx5_encap_decap_ipool", 202 }, 203 { 204 .size = sizeof(struct mlx5_flow_dv_push_vlan_action_resource), 205 .trunk_size = 64, 206 .grow_trunk = 3, 207 .grow_shift = 2, 208 .need_lock = 0, 209 .release_mem_en = 1, 210 .malloc = mlx5_malloc, 211 .free = mlx5_free, 212 .type = "mlx5_push_vlan_ipool", 213 }, 214 { 215 .size = sizeof(struct mlx5_flow_dv_tag_resource), 216 .trunk_size = 64, 217 .grow_trunk = 3, 218 .grow_shift = 2, 219 .need_lock = 0, 220 .release_mem_en = 1, 221 .malloc = mlx5_malloc, 222 .free = mlx5_free, 223 .type = "mlx5_tag_ipool", 224 }, 225 { 226 .size = sizeof(struct mlx5_flow_dv_port_id_action_resource), 227 .trunk_size = 64, 228 .grow_trunk = 3, 229 .grow_shift = 2, 230 .need_lock = 0, 231 .release_mem_en = 1, 232 .malloc = mlx5_malloc, 233 .free = mlx5_free, 234 .type = "mlx5_port_id_ipool", 235 }, 236 { 237 .size = sizeof(struct mlx5_flow_tbl_data_entry), 238 .trunk_size = 64, 239 .grow_trunk = 3, 240 .grow_shift = 2, 241 .need_lock = 0, 242 .release_mem_en = 1, 243 .malloc = mlx5_malloc, 244 .free = mlx5_free, 245 .type = "mlx5_jump_ipool", 246 }, 247 #endif 248 { 249 .size = sizeof(struct mlx5_flow_meter), 250 .trunk_size = 64, 251 .grow_trunk = 3, 252 .grow_shift = 2, 253 .need_lock = 0, 254 .release_mem_en = 1, 255 .malloc = mlx5_malloc, 256 .free = mlx5_free, 257 .type = "mlx5_meter_ipool", 258 }, 259 { 260 .size = sizeof(struct mlx5_flow_mreg_copy_resource), 261 .trunk_size = 64, 262 .grow_trunk = 3, 263 .grow_shift = 2, 264 .need_lock = 0, 265 .release_mem_en = 1, 266 .malloc = mlx5_malloc, 267 .free = mlx5_free, 268 .type = "mlx5_mcp_ipool", 269 }, 270 { 271 .size = (sizeof(struct mlx5_hrxq) + MLX5_RSS_HASH_KEY_LEN), 272 .trunk_size = 64, 273 .grow_trunk = 3, 274 .grow_shift = 2, 275 .need_lock = 0, 276 .release_mem_en = 1, 277 .malloc = mlx5_malloc, 278 .free = mlx5_free, 279 .type = "mlx5_hrxq_ipool", 280 }, 281 { 282 /* 283 * MLX5_IPOOL_MLX5_FLOW size varies for DV and VERBS flows. 284 * It set in run time according to PCI function configuration. 285 */ 286 .size = 0, 287 .trunk_size = 64, 288 .grow_trunk = 3, 289 .grow_shift = 2, 290 .need_lock = 0, 291 .release_mem_en = 1, 292 .malloc = mlx5_malloc, 293 .free = mlx5_free, 294 .type = "mlx5_flow_handle_ipool", 295 }, 296 { 297 .size = sizeof(struct rte_flow), 298 .trunk_size = 4096, 299 .need_lock = 1, 300 .release_mem_en = 1, 301 .malloc = mlx5_malloc, 302 .free = mlx5_free, 303 .type = "rte_flow_ipool", 304 }, 305 }; 306 307 308 #define MLX5_FLOW_MIN_ID_POOL_SIZE 512 309 #define MLX5_ID_GENERATION_ARRAY_FACTOR 16 310 311 #define MLX5_FLOW_TABLE_HLIST_ARRAY_SIZE 4096 312 313 /** 314 * Allocate ID pool structure. 315 * 316 * @param[in] max_id 317 * The maximum id can be allocated from the pool. 318 * 319 * @return 320 * Pointer to pool object, NULL value otherwise. 321 */ 322 struct mlx5_flow_id_pool * 323 mlx5_flow_id_pool_alloc(uint32_t max_id) 324 { 325 struct mlx5_flow_id_pool *pool; 326 void *mem; 327 328 pool = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*pool), 329 RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY); 330 if (!pool) { 331 DRV_LOG(ERR, "can't allocate id pool"); 332 rte_errno = ENOMEM; 333 return NULL; 334 } 335 mem = mlx5_malloc(MLX5_MEM_ZERO, 336 MLX5_FLOW_MIN_ID_POOL_SIZE * sizeof(uint32_t), 337 RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY); 338 if (!mem) { 339 DRV_LOG(ERR, "can't allocate mem for id pool"); 340 rte_errno = ENOMEM; 341 goto error; 342 } 343 pool->free_arr = mem; 344 pool->curr = pool->free_arr; 345 pool->last = pool->free_arr + MLX5_FLOW_MIN_ID_POOL_SIZE; 346 pool->base_index = 0; 347 pool->max_id = max_id; 348 return pool; 349 error: 350 mlx5_free(pool); 351 return NULL; 352 } 353 354 /** 355 * Release ID pool structure. 356 * 357 * @param[in] pool 358 * Pointer to flow id pool object to free. 359 */ 360 void 361 mlx5_flow_id_pool_release(struct mlx5_flow_id_pool *pool) 362 { 363 mlx5_free(pool->free_arr); 364 mlx5_free(pool); 365 } 366 367 /** 368 * Generate ID. 369 * 370 * @param[in] pool 371 * Pointer to flow id pool. 372 * @param[out] id 373 * The generated ID. 374 * 375 * @return 376 * 0 on success, error value otherwise. 377 */ 378 uint32_t 379 mlx5_flow_id_get(struct mlx5_flow_id_pool *pool, uint32_t *id) 380 { 381 if (pool->curr == pool->free_arr) { 382 if (pool->base_index == pool->max_id) { 383 rte_errno = ENOMEM; 384 DRV_LOG(ERR, "no free id"); 385 return -rte_errno; 386 } 387 *id = ++pool->base_index; 388 return 0; 389 } 390 *id = *(--pool->curr); 391 return 0; 392 } 393 394 /** 395 * Release ID. 396 * 397 * @param[in] pool 398 * Pointer to flow id pool. 399 * @param[out] id 400 * The generated ID. 401 * 402 * @return 403 * 0 on success, error value otherwise. 404 */ 405 uint32_t 406 mlx5_flow_id_release(struct mlx5_flow_id_pool *pool, uint32_t id) 407 { 408 uint32_t size; 409 uint32_t size2; 410 void *mem; 411 412 if (pool->curr == pool->last) { 413 size = pool->curr - pool->free_arr; 414 size2 = size * MLX5_ID_GENERATION_ARRAY_FACTOR; 415 MLX5_ASSERT(size2 > size); 416 mem = mlx5_malloc(0, size2 * sizeof(uint32_t), 0, 417 SOCKET_ID_ANY); 418 if (!mem) { 419 DRV_LOG(ERR, "can't allocate mem for id pool"); 420 rte_errno = ENOMEM; 421 return -rte_errno; 422 } 423 memcpy(mem, pool->free_arr, size * sizeof(uint32_t)); 424 mlx5_free(pool->free_arr); 425 pool->free_arr = mem; 426 pool->curr = pool->free_arr + size; 427 pool->last = pool->free_arr + size2; 428 } 429 *pool->curr = id; 430 pool->curr++; 431 return 0; 432 } 433 434 /** 435 * Initialize the shared aging list information per port. 436 * 437 * @param[in] sh 438 * Pointer to mlx5_dev_ctx_shared object. 439 */ 440 static void 441 mlx5_flow_aging_init(struct mlx5_dev_ctx_shared *sh) 442 { 443 uint32_t i; 444 struct mlx5_age_info *age_info; 445 446 for (i = 0; i < sh->max_port; i++) { 447 age_info = &sh->port[i].age_info; 448 age_info->flags = 0; 449 TAILQ_INIT(&age_info->aged_counters); 450 rte_spinlock_init(&age_info->aged_sl); 451 MLX5_AGE_SET(age_info, MLX5_AGE_TRIGGER); 452 } 453 } 454 455 /** 456 * Initialize the counters management structure. 457 * 458 * @param[in] sh 459 * Pointer to mlx5_dev_ctx_shared object to free 460 */ 461 static void 462 mlx5_flow_counters_mng_init(struct mlx5_dev_ctx_shared *sh) 463 { 464 int i; 465 466 memset(&sh->cmng, 0, sizeof(sh->cmng)); 467 TAILQ_INIT(&sh->cmng.flow_counters); 468 for (i = 0; i < MLX5_CCONT_TYPE_MAX; ++i) { 469 sh->cmng.ccont[i].min_id = MLX5_CNT_BATCH_OFFSET; 470 sh->cmng.ccont[i].max_id = -1; 471 sh->cmng.ccont[i].last_pool_idx = POOL_IDX_INVALID; 472 TAILQ_INIT(&sh->cmng.ccont[i].pool_list); 473 rte_spinlock_init(&sh->cmng.ccont[i].resize_sl); 474 TAILQ_INIT(&sh->cmng.ccont[i].counters); 475 rte_spinlock_init(&sh->cmng.ccont[i].csl); 476 } 477 } 478 479 /** 480 * Destroy all the resources allocated for a counter memory management. 481 * 482 * @param[in] mng 483 * Pointer to the memory management structure. 484 */ 485 static void 486 mlx5_flow_destroy_counter_stat_mem_mng(struct mlx5_counter_stats_mem_mng *mng) 487 { 488 uint8_t *mem = (uint8_t *)(uintptr_t)mng->raws[0].data; 489 490 LIST_REMOVE(mng, next); 491 claim_zero(mlx5_devx_cmd_destroy(mng->dm)); 492 claim_zero(mlx5_glue->devx_umem_dereg(mng->umem)); 493 mlx5_free(mem); 494 } 495 496 /** 497 * Close and release all the resources of the counters management. 498 * 499 * @param[in] sh 500 * Pointer to mlx5_dev_ctx_shared object to free. 501 */ 502 static void 503 mlx5_flow_counters_mng_close(struct mlx5_dev_ctx_shared *sh) 504 { 505 struct mlx5_counter_stats_mem_mng *mng; 506 int i; 507 int j; 508 int retries = 1024; 509 510 rte_errno = 0; 511 while (--retries) { 512 rte_eal_alarm_cancel(mlx5_flow_query_alarm, sh); 513 if (rte_errno != EINPROGRESS) 514 break; 515 rte_pause(); 516 } 517 for (i = 0; i < MLX5_CCONT_TYPE_MAX; ++i) { 518 struct mlx5_flow_counter_pool *pool; 519 uint32_t batch = !!(i > 1); 520 521 if (!sh->cmng.ccont[i].pools) 522 continue; 523 pool = TAILQ_FIRST(&sh->cmng.ccont[i].pool_list); 524 while (pool) { 525 if (batch && pool->min_dcs) 526 claim_zero(mlx5_devx_cmd_destroy 527 (pool->min_dcs)); 528 for (j = 0; j < MLX5_COUNTERS_PER_POOL; ++j) { 529 if (MLX5_POOL_GET_CNT(pool, j)->action) 530 claim_zero 531 (mlx5_glue->destroy_flow_action 532 (MLX5_POOL_GET_CNT 533 (pool, j)->action)); 534 if (!batch && MLX5_GET_POOL_CNT_EXT 535 (pool, j)->dcs) 536 claim_zero(mlx5_devx_cmd_destroy 537 (MLX5_GET_POOL_CNT_EXT 538 (pool, j)->dcs)); 539 } 540 TAILQ_REMOVE(&sh->cmng.ccont[i].pool_list, pool, next); 541 mlx5_free(pool); 542 pool = TAILQ_FIRST(&sh->cmng.ccont[i].pool_list); 543 } 544 mlx5_free(sh->cmng.ccont[i].pools); 545 } 546 mng = LIST_FIRST(&sh->cmng.mem_mngs); 547 while (mng) { 548 mlx5_flow_destroy_counter_stat_mem_mng(mng); 549 mng = LIST_FIRST(&sh->cmng.mem_mngs); 550 } 551 memset(&sh->cmng, 0, sizeof(sh->cmng)); 552 } 553 554 /** 555 * Initialize the flow resources' indexed mempool. 556 * 557 * @param[in] sh 558 * Pointer to mlx5_dev_ctx_shared object. 559 * @param[in] sh 560 * Pointer to user dev config. 561 */ 562 static void 563 mlx5_flow_ipool_create(struct mlx5_dev_ctx_shared *sh, 564 const struct mlx5_dev_config *config) 565 { 566 uint8_t i; 567 struct mlx5_indexed_pool_config cfg; 568 569 for (i = 0; i < MLX5_IPOOL_MAX; ++i) { 570 cfg = mlx5_ipool_cfg[i]; 571 switch (i) { 572 default: 573 break; 574 /* 575 * Set MLX5_IPOOL_MLX5_FLOW ipool size 576 * according to PCI function flow configuration. 577 */ 578 case MLX5_IPOOL_MLX5_FLOW: 579 cfg.size = config->dv_flow_en ? 580 sizeof(struct mlx5_flow_handle) : 581 MLX5_FLOW_HANDLE_VERBS_SIZE; 582 break; 583 } 584 if (config->reclaim_mode) 585 cfg.release_mem_en = 1; 586 sh->ipool[i] = mlx5_ipool_create(&cfg); 587 } 588 } 589 590 /** 591 * Release the flow resources' indexed mempool. 592 * 593 * @param[in] sh 594 * Pointer to mlx5_dev_ctx_shared object. 595 */ 596 static void 597 mlx5_flow_ipool_destroy(struct mlx5_dev_ctx_shared *sh) 598 { 599 uint8_t i; 600 601 for (i = 0; i < MLX5_IPOOL_MAX; ++i) 602 mlx5_ipool_destroy(sh->ipool[i]); 603 } 604 605 /* 606 * Check if dynamic flex parser for eCPRI already exists. 607 * 608 * @param dev 609 * Pointer to Ethernet device structure. 610 * 611 * @return 612 * true on exists, false on not. 613 */ 614 bool 615 mlx5_flex_parser_ecpri_exist(struct rte_eth_dev *dev) 616 { 617 struct mlx5_priv *priv = dev->data->dev_private; 618 struct mlx5_flex_parser_profiles *prf = 619 &priv->sh->fp[MLX5_FLEX_PARSER_ECPRI_0]; 620 621 return !!prf->obj; 622 } 623 624 /* 625 * Allocation of a flex parser for eCPRI. Once created, this parser related 626 * resources will be held until the device is closed. 627 * 628 * @param dev 629 * Pointer to Ethernet device structure. 630 * 631 * @return 632 * 0 on success, a negative errno value otherwise and rte_errno is set. 633 */ 634 int 635 mlx5_flex_parser_ecpri_alloc(struct rte_eth_dev *dev) 636 { 637 struct mlx5_priv *priv = dev->data->dev_private; 638 struct mlx5_flex_parser_profiles *prf = 639 &priv->sh->fp[MLX5_FLEX_PARSER_ECPRI_0]; 640 struct mlx5_devx_graph_node_attr node = { 641 .modify_field_select = 0, 642 }; 643 uint32_t ids[8]; 644 int ret; 645 646 if (!priv->config.hca_attr.parse_graph_flex_node) { 647 DRV_LOG(ERR, "Dynamic flex parser is not supported " 648 "for device %s.", priv->dev_data->name); 649 return -ENOTSUP; 650 } 651 node.header_length_mode = MLX5_GRAPH_NODE_LEN_FIXED; 652 /* 8 bytes now: 4B common header + 4B message body header. */ 653 node.header_length_base_value = 0x8; 654 /* After MAC layer: Ether / VLAN. */ 655 node.in[0].arc_parse_graph_node = MLX5_GRAPH_ARC_NODE_MAC; 656 /* Type of compared condition should be 0xAEFE in the L2 layer. */ 657 node.in[0].compare_condition_value = RTE_ETHER_TYPE_ECPRI; 658 /* Sample #0: type in common header. */ 659 node.sample[0].flow_match_sample_en = 1; 660 /* Fixed offset. */ 661 node.sample[0].flow_match_sample_offset_mode = 0x0; 662 /* Only the 2nd byte will be used. */ 663 node.sample[0].flow_match_sample_field_base_offset = 0x0; 664 /* Sample #1: message payload. */ 665 node.sample[1].flow_match_sample_en = 1; 666 /* Fixed offset. */ 667 node.sample[1].flow_match_sample_offset_mode = 0x0; 668 /* 669 * Only the first two bytes will be used right now, and its offset will 670 * start after the common header that with the length of a DW(u32). 671 */ 672 node.sample[1].flow_match_sample_field_base_offset = sizeof(uint32_t); 673 prf->obj = mlx5_devx_cmd_create_flex_parser(priv->sh->ctx, &node); 674 if (!prf->obj) { 675 DRV_LOG(ERR, "Failed to create flex parser node object."); 676 return (rte_errno == 0) ? -ENODEV : -rte_errno; 677 } 678 prf->num = 2; 679 ret = mlx5_devx_cmd_query_parse_samples(prf->obj, ids, prf->num); 680 if (ret) { 681 DRV_LOG(ERR, "Failed to query sample IDs."); 682 return (rte_errno == 0) ? -ENODEV : -rte_errno; 683 } 684 prf->offset[0] = 0x0; 685 prf->offset[1] = sizeof(uint32_t); 686 prf->ids[0] = ids[0]; 687 prf->ids[1] = ids[1]; 688 return 0; 689 } 690 691 /* 692 * Destroy the flex parser node, including the parser itself, input / output 693 * arcs and DW samples. Resources could be reused then. 694 * 695 * @param dev 696 * Pointer to Ethernet device structure. 697 */ 698 static void 699 mlx5_flex_parser_ecpri_release(struct rte_eth_dev *dev) 700 { 701 struct mlx5_priv *priv = dev->data->dev_private; 702 struct mlx5_flex_parser_profiles *prf = 703 &priv->sh->fp[MLX5_FLEX_PARSER_ECPRI_0]; 704 705 if (prf->obj) 706 mlx5_devx_cmd_destroy(prf->obj); 707 prf->obj = NULL; 708 } 709 710 /* 711 * Allocate Rx and Tx UARs in robust fashion. 712 * This routine handles the following UAR allocation issues: 713 * 714 * - tries to allocate the UAR with the most appropriate memory 715 * mapping type from the ones supported by the host 716 * 717 * - tries to allocate the UAR with non-NULL base address 718 * OFED 5.0.x and Upstream rdma_core before v29 returned the NULL as 719 * UAR base address if UAR was not the first object in the UAR page. 720 * It caused the PMD failure and we should try to get another UAR 721 * till we get the first one with non-NULL base address returned. 722 */ 723 static int 724 mlx5_alloc_rxtx_uars(struct mlx5_dev_ctx_shared *sh, 725 const struct mlx5_dev_config *config) 726 { 727 uint32_t uar_mapping, retry; 728 int err = 0; 729 730 for (retry = 0; retry < MLX5_ALLOC_UAR_RETRY; ++retry) { 731 #ifdef MLX5DV_UAR_ALLOC_TYPE_NC 732 /* Control the mapping type according to the settings. */ 733 uar_mapping = (config->dbnc == MLX5_TXDB_NCACHED) ? 734 MLX5DV_UAR_ALLOC_TYPE_NC : 735 MLX5DV_UAR_ALLOC_TYPE_BF; 736 #else 737 RTE_SET_USED(config); 738 /* 739 * It seems we have no way to control the memory mapping type 740 * for the UAR, the default "Write-Combining" type is supposed. 741 * The UAR initialization on queue creation queries the 742 * actual mapping type done by Verbs/kernel and setups the 743 * PMD datapath accordingly. 744 */ 745 uar_mapping = 0; 746 #endif 747 sh->tx_uar = mlx5_glue->devx_alloc_uar(sh->ctx, uar_mapping); 748 #ifdef MLX5DV_UAR_ALLOC_TYPE_NC 749 if (!sh->tx_uar && 750 uar_mapping == MLX5DV_UAR_ALLOC_TYPE_BF) { 751 if (config->dbnc == MLX5_TXDB_CACHED || 752 config->dbnc == MLX5_TXDB_HEURISTIC) 753 DRV_LOG(WARNING, "Devarg tx_db_nc setting " 754 "is not supported by DevX"); 755 /* 756 * In some environments like virtual machine 757 * the Write Combining mapped might be not supported 758 * and UAR allocation fails. We try "Non-Cached" 759 * mapping for the case. The tx_burst routines take 760 * the UAR mapping type into account on UAR setup 761 * on queue creation. 762 */ 763 DRV_LOG(WARNING, "Failed to allocate Tx DevX UAR (BF)"); 764 uar_mapping = MLX5DV_UAR_ALLOC_TYPE_NC; 765 sh->tx_uar = mlx5_glue->devx_alloc_uar 766 (sh->ctx, uar_mapping); 767 } else if (!sh->tx_uar && 768 uar_mapping == MLX5DV_UAR_ALLOC_TYPE_NC) { 769 if (config->dbnc == MLX5_TXDB_NCACHED) 770 DRV_LOG(WARNING, "Devarg tx_db_nc settings " 771 "is not supported by DevX"); 772 /* 773 * If Verbs/kernel does not support "Non-Cached" 774 * try the "Write-Combining". 775 */ 776 DRV_LOG(WARNING, "Failed to allocate Tx DevX UAR (NC)"); 777 uar_mapping = MLX5DV_UAR_ALLOC_TYPE_BF; 778 sh->tx_uar = mlx5_glue->devx_alloc_uar 779 (sh->ctx, uar_mapping); 780 } 781 #endif 782 if (!sh->tx_uar) { 783 DRV_LOG(ERR, "Failed to allocate Tx DevX UAR (BF/NC)"); 784 err = ENOMEM; 785 goto exit; 786 } 787 if (sh->tx_uar->base_addr) 788 break; 789 /* 790 * The UARs are allocated by rdma_core within the 791 * IB device context, on context closure all UARs 792 * will be freed, should be no memory/object leakage. 793 */ 794 DRV_LOG(WARNING, "Retrying to allocate Tx DevX UAR"); 795 sh->tx_uar = NULL; 796 } 797 /* Check whether we finally succeeded with valid UAR allocation. */ 798 if (!sh->tx_uar) { 799 DRV_LOG(ERR, "Failed to allocate Tx DevX UAR (NULL base)"); 800 err = ENOMEM; 801 goto exit; 802 } 803 for (retry = 0; retry < MLX5_ALLOC_UAR_RETRY; ++retry) { 804 uar_mapping = 0; 805 sh->devx_rx_uar = mlx5_glue->devx_alloc_uar 806 (sh->ctx, uar_mapping); 807 #ifdef MLX5DV_UAR_ALLOC_TYPE_NC 808 if (!sh->devx_rx_uar && 809 uar_mapping == MLX5DV_UAR_ALLOC_TYPE_BF) { 810 /* 811 * Rx UAR is used to control interrupts only, 812 * should be no datapath noticeable impact, 813 * can try "Non-Cached" mapping safely. 814 */ 815 DRV_LOG(WARNING, "Failed to allocate Rx DevX UAR (BF)"); 816 uar_mapping = MLX5DV_UAR_ALLOC_TYPE_NC; 817 sh->devx_rx_uar = mlx5_glue->devx_alloc_uar 818 (sh->ctx, uar_mapping); 819 } 820 #endif 821 if (!sh->devx_rx_uar) { 822 DRV_LOG(ERR, "Failed to allocate Rx DevX UAR (BF/NC)"); 823 err = ENOMEM; 824 goto exit; 825 } 826 if (sh->devx_rx_uar->base_addr) 827 break; 828 /* 829 * The UARs are allocated by rdma_core within the 830 * IB device context, on context closure all UARs 831 * will be freed, should be no memory/object leakage. 832 */ 833 DRV_LOG(WARNING, "Retrying to allocate Rx DevX UAR"); 834 sh->devx_rx_uar = NULL; 835 } 836 /* Check whether we finally succeeded with valid UAR allocation. */ 837 if (!sh->devx_rx_uar) { 838 DRV_LOG(ERR, "Failed to allocate Rx DevX UAR (NULL base)"); 839 err = ENOMEM; 840 } 841 exit: 842 return err; 843 } 844 845 /** 846 * Allocate shared device context. If there is multiport device the 847 * master and representors will share this context, if there is single 848 * port dedicated device, the context will be used by only given 849 * port due to unification. 850 * 851 * Routine first searches the context for the specified device name, 852 * if found the shared context assumed and reference counter is incremented. 853 * If no context found the new one is created and initialized with specified 854 * device context and parameters. 855 * 856 * @param[in] spawn 857 * Pointer to the device attributes (name, port, etc). 858 * @param[in] config 859 * Pointer to device configuration structure. 860 * 861 * @return 862 * Pointer to mlx5_dev_ctx_shared object on success, 863 * otherwise NULL and rte_errno is set. 864 */ 865 struct mlx5_dev_ctx_shared * 866 mlx5_alloc_shared_dev_ctx(const struct mlx5_dev_spawn_data *spawn, 867 const struct mlx5_dev_config *config) 868 { 869 struct mlx5_dev_ctx_shared *sh; 870 int err = 0; 871 uint32_t i; 872 struct mlx5_devx_tis_attr tis_attr = { 0 }; 873 874 MLX5_ASSERT(spawn); 875 /* Secondary process should not create the shared context. */ 876 MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY); 877 pthread_mutex_lock(&mlx5_dev_ctx_list_mutex); 878 /* Search for IB context by device name. */ 879 LIST_FOREACH(sh, &mlx5_dev_ctx_list, next) { 880 if (!strcmp(sh->ibdev_name, 881 mlx5_os_get_dev_device_name(spawn->phys_dev))) { 882 sh->refcnt++; 883 goto exit; 884 } 885 } 886 /* No device found, we have to create new shared context. */ 887 MLX5_ASSERT(spawn->max_port); 888 sh = mlx5_malloc(MLX5_MEM_ZERO | MLX5_MEM_RTE, 889 sizeof(struct mlx5_dev_ctx_shared) + 890 spawn->max_port * 891 sizeof(struct mlx5_dev_shared_port), 892 RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY); 893 if (!sh) { 894 DRV_LOG(ERR, "shared context allocation failure"); 895 rte_errno = ENOMEM; 896 goto exit; 897 } 898 err = mlx5_os_open_device(spawn, config, sh); 899 if (!sh->ctx) 900 goto error; 901 err = mlx5_os_get_dev_attr(sh->ctx, &sh->device_attr); 902 if (err) { 903 DRV_LOG(DEBUG, "mlx5_os_get_dev_attr() failed"); 904 goto error; 905 } 906 sh->refcnt = 1; 907 sh->max_port = spawn->max_port; 908 strncpy(sh->ibdev_name, mlx5_os_get_ctx_device_name(sh->ctx), 909 sizeof(sh->ibdev_name) - 1); 910 strncpy(sh->ibdev_path, mlx5_os_get_ctx_device_path(sh->ctx), 911 sizeof(sh->ibdev_path) - 1); 912 /* 913 * Setting port_id to max unallowed value means 914 * there is no interrupt subhandler installed for 915 * the given port index i. 916 */ 917 for (i = 0; i < sh->max_port; i++) { 918 sh->port[i].ih_port_id = RTE_MAX_ETHPORTS; 919 sh->port[i].devx_ih_port_id = RTE_MAX_ETHPORTS; 920 } 921 sh->pd = mlx5_glue->alloc_pd(sh->ctx); 922 if (sh->pd == NULL) { 923 DRV_LOG(ERR, "PD allocation failure"); 924 err = ENOMEM; 925 goto error; 926 } 927 if (sh->devx) { 928 err = mlx5_os_get_pdn(sh->pd, &sh->pdn); 929 if (err) { 930 DRV_LOG(ERR, "Fail to extract pdn from PD"); 931 goto error; 932 } 933 sh->td = mlx5_devx_cmd_create_td(sh->ctx); 934 if (!sh->td) { 935 DRV_LOG(ERR, "TD allocation failure"); 936 err = ENOMEM; 937 goto error; 938 } 939 tis_attr.transport_domain = sh->td->id; 940 sh->tis = mlx5_devx_cmd_create_tis(sh->ctx, &tis_attr); 941 if (!sh->tis) { 942 DRV_LOG(ERR, "TIS allocation failure"); 943 err = ENOMEM; 944 goto error; 945 } 946 err = mlx5_alloc_rxtx_uars(sh, config); 947 if (err) 948 goto error; 949 MLX5_ASSERT(sh->tx_uar && sh->tx_uar->base_addr); 950 MLX5_ASSERT(sh->devx_rx_uar && sh->devx_rx_uar->base_addr); 951 } 952 sh->flow_id_pool = mlx5_flow_id_pool_alloc 953 ((1 << HAIRPIN_FLOW_ID_BITS) - 1); 954 if (!sh->flow_id_pool) { 955 DRV_LOG(ERR, "can't create flow id pool"); 956 err = ENOMEM; 957 goto error; 958 } 959 #ifndef RTE_ARCH_64 960 /* Initialize UAR access locks for 32bit implementations. */ 961 rte_spinlock_init(&sh->uar_lock_cq); 962 for (i = 0; i < MLX5_UAR_PAGE_NUM_MAX; i++) 963 rte_spinlock_init(&sh->uar_lock[i]); 964 #endif 965 /* 966 * Once the device is added to the list of memory event 967 * callback, its global MR cache table cannot be expanded 968 * on the fly because of deadlock. If it overflows, lookup 969 * should be done by searching MR list linearly, which is slow. 970 * 971 * At this point the device is not added to the memory 972 * event list yet, context is just being created. 973 */ 974 err = mlx5_mr_btree_init(&sh->share_cache.cache, 975 MLX5_MR_BTREE_CACHE_N * 2, 976 spawn->pci_dev->device.numa_node); 977 if (err) { 978 err = rte_errno; 979 goto error; 980 } 981 mlx5_os_set_reg_mr_cb(&sh->share_cache.reg_mr_cb, 982 &sh->share_cache.dereg_mr_cb); 983 mlx5_os_dev_shared_handler_install(sh); 984 sh->cnt_id_tbl = mlx5_l3t_create(MLX5_L3T_TYPE_DWORD); 985 if (!sh->cnt_id_tbl) { 986 err = rte_errno; 987 goto error; 988 } 989 mlx5_flow_aging_init(sh); 990 mlx5_flow_counters_mng_init(sh); 991 mlx5_flow_ipool_create(sh, config); 992 /* Add device to memory callback list. */ 993 rte_rwlock_write_lock(&mlx5_shared_data->mem_event_rwlock); 994 LIST_INSERT_HEAD(&mlx5_shared_data->mem_event_cb_list, 995 sh, mem_event_cb); 996 rte_rwlock_write_unlock(&mlx5_shared_data->mem_event_rwlock); 997 /* Add context to the global device list. */ 998 LIST_INSERT_HEAD(&mlx5_dev_ctx_list, sh, next); 999 exit: 1000 pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex); 1001 return sh; 1002 error: 1003 pthread_mutex_destroy(&sh->txpp.mutex); 1004 pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex); 1005 MLX5_ASSERT(sh); 1006 if (sh->cnt_id_tbl) 1007 mlx5_l3t_destroy(sh->cnt_id_tbl); 1008 if (sh->tis) 1009 claim_zero(mlx5_devx_cmd_destroy(sh->tis)); 1010 if (sh->td) 1011 claim_zero(mlx5_devx_cmd_destroy(sh->td)); 1012 if (sh->devx_rx_uar) 1013 mlx5_glue->devx_free_uar(sh->devx_rx_uar); 1014 if (sh->tx_uar) 1015 mlx5_glue->devx_free_uar(sh->tx_uar); 1016 if (sh->pd) 1017 claim_zero(mlx5_glue->dealloc_pd(sh->pd)); 1018 if (sh->ctx) 1019 claim_zero(mlx5_glue->close_device(sh->ctx)); 1020 if (sh->flow_id_pool) 1021 mlx5_flow_id_pool_release(sh->flow_id_pool); 1022 mlx5_free(sh); 1023 MLX5_ASSERT(err > 0); 1024 rte_errno = err; 1025 return NULL; 1026 } 1027 1028 /** 1029 * Free shared IB device context. Decrement counter and if zero free 1030 * all allocated resources and close handles. 1031 * 1032 * @param[in] sh 1033 * Pointer to mlx5_dev_ctx_shared object to free 1034 */ 1035 void 1036 mlx5_free_shared_dev_ctx(struct mlx5_dev_ctx_shared *sh) 1037 { 1038 pthread_mutex_lock(&mlx5_dev_ctx_list_mutex); 1039 #ifdef RTE_LIBRTE_MLX5_DEBUG 1040 /* Check the object presence in the list. */ 1041 struct mlx5_dev_ctx_shared *lctx; 1042 1043 LIST_FOREACH(lctx, &mlx5_dev_ctx_list, next) 1044 if (lctx == sh) 1045 break; 1046 MLX5_ASSERT(lctx); 1047 if (lctx != sh) { 1048 DRV_LOG(ERR, "Freeing non-existing shared IB context"); 1049 goto exit; 1050 } 1051 #endif 1052 MLX5_ASSERT(sh); 1053 MLX5_ASSERT(sh->refcnt); 1054 /* Secondary process should not free the shared context. */ 1055 MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY); 1056 if (--sh->refcnt) 1057 goto exit; 1058 /* Remove from memory callback device list. */ 1059 rte_rwlock_write_lock(&mlx5_shared_data->mem_event_rwlock); 1060 LIST_REMOVE(sh, mem_event_cb); 1061 rte_rwlock_write_unlock(&mlx5_shared_data->mem_event_rwlock); 1062 /* Release created Memory Regions. */ 1063 mlx5_mr_release_cache(&sh->share_cache); 1064 /* Remove context from the global device list. */ 1065 LIST_REMOVE(sh, next); 1066 pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex); 1067 /* 1068 * Ensure there is no async event handler installed. 1069 * Only primary process handles async device events. 1070 **/ 1071 mlx5_flow_counters_mng_close(sh); 1072 mlx5_flow_ipool_destroy(sh); 1073 mlx5_os_dev_shared_handler_uninstall(sh); 1074 if (sh->cnt_id_tbl) { 1075 mlx5_l3t_destroy(sh->cnt_id_tbl); 1076 sh->cnt_id_tbl = NULL; 1077 } 1078 if (sh->tx_uar) { 1079 mlx5_glue->devx_free_uar(sh->tx_uar); 1080 sh->tx_uar = NULL; 1081 } 1082 if (sh->pd) 1083 claim_zero(mlx5_glue->dealloc_pd(sh->pd)); 1084 if (sh->tis) 1085 claim_zero(mlx5_devx_cmd_destroy(sh->tis)); 1086 if (sh->td) 1087 claim_zero(mlx5_devx_cmd_destroy(sh->td)); 1088 if (sh->devx_rx_uar) 1089 mlx5_glue->devx_free_uar(sh->devx_rx_uar); 1090 if (sh->ctx) 1091 claim_zero(mlx5_glue->close_device(sh->ctx)); 1092 if (sh->flow_id_pool) 1093 mlx5_flow_id_pool_release(sh->flow_id_pool); 1094 pthread_mutex_destroy(&sh->txpp.mutex); 1095 mlx5_free(sh); 1096 return; 1097 exit: 1098 pthread_mutex_unlock(&mlx5_dev_ctx_list_mutex); 1099 } 1100 1101 /** 1102 * Destroy table hash list and all the root entries per domain. 1103 * 1104 * @param[in] priv 1105 * Pointer to the private device data structure. 1106 */ 1107 void 1108 mlx5_free_table_hash_list(struct mlx5_priv *priv) 1109 { 1110 struct mlx5_dev_ctx_shared *sh = priv->sh; 1111 struct mlx5_flow_tbl_data_entry *tbl_data; 1112 union mlx5_flow_tbl_key table_key = { 1113 { 1114 .table_id = 0, 1115 .reserved = 0, 1116 .domain = 0, 1117 .direction = 0, 1118 } 1119 }; 1120 struct mlx5_hlist_entry *pos; 1121 1122 if (!sh->flow_tbls) 1123 return; 1124 pos = mlx5_hlist_lookup(sh->flow_tbls, table_key.v64); 1125 if (pos) { 1126 tbl_data = container_of(pos, struct mlx5_flow_tbl_data_entry, 1127 entry); 1128 MLX5_ASSERT(tbl_data); 1129 mlx5_hlist_remove(sh->flow_tbls, pos); 1130 mlx5_free(tbl_data); 1131 } 1132 table_key.direction = 1; 1133 pos = mlx5_hlist_lookup(sh->flow_tbls, table_key.v64); 1134 if (pos) { 1135 tbl_data = container_of(pos, struct mlx5_flow_tbl_data_entry, 1136 entry); 1137 MLX5_ASSERT(tbl_data); 1138 mlx5_hlist_remove(sh->flow_tbls, pos); 1139 mlx5_free(tbl_data); 1140 } 1141 table_key.direction = 0; 1142 table_key.domain = 1; 1143 pos = mlx5_hlist_lookup(sh->flow_tbls, table_key.v64); 1144 if (pos) { 1145 tbl_data = container_of(pos, struct mlx5_flow_tbl_data_entry, 1146 entry); 1147 MLX5_ASSERT(tbl_data); 1148 mlx5_hlist_remove(sh->flow_tbls, pos); 1149 mlx5_free(tbl_data); 1150 } 1151 mlx5_hlist_destroy(sh->flow_tbls, NULL, NULL); 1152 } 1153 1154 /** 1155 * Initialize flow table hash list and create the root tables entry 1156 * for each domain. 1157 * 1158 * @param[in] priv 1159 * Pointer to the private device data structure. 1160 * 1161 * @return 1162 * Zero on success, positive error code otherwise. 1163 */ 1164 int 1165 mlx5_alloc_table_hash_list(struct mlx5_priv *priv) 1166 { 1167 struct mlx5_dev_ctx_shared *sh = priv->sh; 1168 char s[MLX5_HLIST_NAMESIZE]; 1169 int err = 0; 1170 1171 MLX5_ASSERT(sh); 1172 snprintf(s, sizeof(s), "%s_flow_table", priv->sh->ibdev_name); 1173 sh->flow_tbls = mlx5_hlist_create(s, MLX5_FLOW_TABLE_HLIST_ARRAY_SIZE); 1174 if (!sh->flow_tbls) { 1175 DRV_LOG(ERR, "flow tables with hash creation failed."); 1176 err = ENOMEM; 1177 return err; 1178 } 1179 #ifndef HAVE_MLX5DV_DR 1180 /* 1181 * In case we have not DR support, the zero tables should be created 1182 * because DV expect to see them even if they cannot be created by 1183 * RDMA-CORE. 1184 */ 1185 union mlx5_flow_tbl_key table_key = { 1186 { 1187 .table_id = 0, 1188 .reserved = 0, 1189 .domain = 0, 1190 .direction = 0, 1191 } 1192 }; 1193 struct mlx5_flow_tbl_data_entry *tbl_data = mlx5_malloc(MLX5_MEM_ZERO, 1194 sizeof(*tbl_data), 0, 1195 SOCKET_ID_ANY); 1196 1197 if (!tbl_data) { 1198 err = ENOMEM; 1199 goto error; 1200 } 1201 tbl_data->entry.key = table_key.v64; 1202 err = mlx5_hlist_insert(sh->flow_tbls, &tbl_data->entry); 1203 if (err) 1204 goto error; 1205 rte_atomic32_init(&tbl_data->tbl.refcnt); 1206 rte_atomic32_inc(&tbl_data->tbl.refcnt); 1207 table_key.direction = 1; 1208 tbl_data = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*tbl_data), 0, 1209 SOCKET_ID_ANY); 1210 if (!tbl_data) { 1211 err = ENOMEM; 1212 goto error; 1213 } 1214 tbl_data->entry.key = table_key.v64; 1215 err = mlx5_hlist_insert(sh->flow_tbls, &tbl_data->entry); 1216 if (err) 1217 goto error; 1218 rte_atomic32_init(&tbl_data->tbl.refcnt); 1219 rte_atomic32_inc(&tbl_data->tbl.refcnt); 1220 table_key.direction = 0; 1221 table_key.domain = 1; 1222 tbl_data = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*tbl_data), 0, 1223 SOCKET_ID_ANY); 1224 if (!tbl_data) { 1225 err = ENOMEM; 1226 goto error; 1227 } 1228 tbl_data->entry.key = table_key.v64; 1229 err = mlx5_hlist_insert(sh->flow_tbls, &tbl_data->entry); 1230 if (err) 1231 goto error; 1232 rte_atomic32_init(&tbl_data->tbl.refcnt); 1233 rte_atomic32_inc(&tbl_data->tbl.refcnt); 1234 return err; 1235 error: 1236 mlx5_free_table_hash_list(priv); 1237 #endif /* HAVE_MLX5DV_DR */ 1238 return err; 1239 } 1240 1241 /** 1242 * Retrieve integer value from environment variable. 1243 * 1244 * @param[in] name 1245 * Environment variable name. 1246 * 1247 * @return 1248 * Integer value, 0 if the variable is not set. 1249 */ 1250 int 1251 mlx5_getenv_int(const char *name) 1252 { 1253 const char *val = getenv(name); 1254 1255 if (val == NULL) 1256 return 0; 1257 return atoi(val); 1258 } 1259 1260 /** 1261 * DPDK callback to add udp tunnel port 1262 * 1263 * @param[in] dev 1264 * A pointer to eth_dev 1265 * @param[in] udp_tunnel 1266 * A pointer to udp tunnel 1267 * 1268 * @return 1269 * 0 on valid udp ports and tunnels, -ENOTSUP otherwise. 1270 */ 1271 int 1272 mlx5_udp_tunnel_port_add(struct rte_eth_dev *dev __rte_unused, 1273 struct rte_eth_udp_tunnel *udp_tunnel) 1274 { 1275 MLX5_ASSERT(udp_tunnel != NULL); 1276 if (udp_tunnel->prot_type == RTE_TUNNEL_TYPE_VXLAN && 1277 udp_tunnel->udp_port == 4789) 1278 return 0; 1279 if (udp_tunnel->prot_type == RTE_TUNNEL_TYPE_VXLAN_GPE && 1280 udp_tunnel->udp_port == 4790) 1281 return 0; 1282 return -ENOTSUP; 1283 } 1284 1285 /** 1286 * Initialize process private data structure. 1287 * 1288 * @param dev 1289 * Pointer to Ethernet device structure. 1290 * 1291 * @return 1292 * 0 on success, a negative errno value otherwise and rte_errno is set. 1293 */ 1294 int 1295 mlx5_proc_priv_init(struct rte_eth_dev *dev) 1296 { 1297 struct mlx5_priv *priv = dev->data->dev_private; 1298 struct mlx5_proc_priv *ppriv; 1299 size_t ppriv_size; 1300 1301 /* 1302 * UAR register table follows the process private structure. BlueFlame 1303 * registers for Tx queues are stored in the table. 1304 */ 1305 ppriv_size = 1306 sizeof(struct mlx5_proc_priv) + priv->txqs_n * sizeof(void *); 1307 ppriv = mlx5_malloc(MLX5_MEM_RTE, ppriv_size, RTE_CACHE_LINE_SIZE, 1308 dev->device->numa_node); 1309 if (!ppriv) { 1310 rte_errno = ENOMEM; 1311 return -rte_errno; 1312 } 1313 ppriv->uar_table_sz = ppriv_size; 1314 dev->process_private = ppriv; 1315 return 0; 1316 } 1317 1318 /** 1319 * Un-initialize process private data structure. 1320 * 1321 * @param dev 1322 * Pointer to Ethernet device structure. 1323 */ 1324 static void 1325 mlx5_proc_priv_uninit(struct rte_eth_dev *dev) 1326 { 1327 if (!dev->process_private) 1328 return; 1329 mlx5_free(dev->process_private); 1330 dev->process_private = NULL; 1331 } 1332 1333 /** 1334 * DPDK callback to close the device. 1335 * 1336 * Destroy all queues and objects, free memory. 1337 * 1338 * @param dev 1339 * Pointer to Ethernet device structure. 1340 */ 1341 void 1342 mlx5_dev_close(struct rte_eth_dev *dev) 1343 { 1344 struct mlx5_priv *priv = dev->data->dev_private; 1345 unsigned int i; 1346 int ret; 1347 1348 if (rte_eal_process_type() == RTE_PROC_SECONDARY) { 1349 /* Check if process_private released. */ 1350 if (!dev->process_private) 1351 return; 1352 mlx5_tx_uar_uninit_secondary(dev); 1353 mlx5_proc_priv_uninit(dev); 1354 rte_eth_dev_release_port(dev); 1355 return; 1356 } 1357 if (!priv->sh) 1358 return; 1359 DRV_LOG(DEBUG, "port %u closing device \"%s\"", 1360 dev->data->port_id, 1361 ((priv->sh->ctx != NULL) ? 1362 mlx5_os_get_ctx_device_name(priv->sh->ctx) : "")); 1363 /* 1364 * If default mreg copy action is removed at the stop stage, 1365 * the search will return none and nothing will be done anymore. 1366 */ 1367 mlx5_flow_stop_default(dev); 1368 mlx5_traffic_disable(dev); 1369 /* 1370 * If all the flows are already flushed in the device stop stage, 1371 * then this will return directly without any action. 1372 */ 1373 mlx5_flow_list_flush(dev, &priv->flows, true); 1374 mlx5_flow_meter_flush(dev, NULL); 1375 /* Free the intermediate buffers for flow creation. */ 1376 mlx5_flow_free_intermediate(dev); 1377 /* Prevent crashes when queues are still in use. */ 1378 dev->rx_pkt_burst = removed_rx_burst; 1379 dev->tx_pkt_burst = removed_tx_burst; 1380 rte_wmb(); 1381 /* Disable datapath on secondary process. */ 1382 mlx5_mp_os_req_stop_rxtx(dev); 1383 /* Free the eCPRI flex parser resource. */ 1384 mlx5_flex_parser_ecpri_release(dev); 1385 if (priv->rxqs != NULL) { 1386 /* XXX race condition if mlx5_rx_burst() is still running. */ 1387 usleep(1000); 1388 for (i = 0; (i != priv->rxqs_n); ++i) 1389 mlx5_rxq_release(dev, i); 1390 priv->rxqs_n = 0; 1391 priv->rxqs = NULL; 1392 } 1393 if (priv->txqs != NULL) { 1394 /* XXX race condition if mlx5_tx_burst() is still running. */ 1395 usleep(1000); 1396 for (i = 0; (i != priv->txqs_n); ++i) 1397 mlx5_txq_release(dev, i); 1398 priv->txqs_n = 0; 1399 priv->txqs = NULL; 1400 } 1401 mlx5_proc_priv_uninit(dev); 1402 if (priv->mreg_cp_tbl) 1403 mlx5_hlist_destroy(priv->mreg_cp_tbl, NULL, NULL); 1404 mlx5_mprq_free_mp(dev); 1405 mlx5_os_free_shared_dr(priv); 1406 if (priv->rss_conf.rss_key != NULL) 1407 mlx5_free(priv->rss_conf.rss_key); 1408 if (priv->reta_idx != NULL) 1409 mlx5_free(priv->reta_idx); 1410 if (priv->config.vf) 1411 mlx5_nl_mac_addr_flush(priv->nl_socket_route, mlx5_ifindex(dev), 1412 dev->data->mac_addrs, 1413 MLX5_MAX_MAC_ADDRESSES, priv->mac_own); 1414 if (priv->nl_socket_route >= 0) 1415 close(priv->nl_socket_route); 1416 if (priv->nl_socket_rdma >= 0) 1417 close(priv->nl_socket_rdma); 1418 if (priv->vmwa_context) 1419 mlx5_vlan_vmwa_exit(priv->vmwa_context); 1420 ret = mlx5_hrxq_verify(dev); 1421 if (ret) 1422 DRV_LOG(WARNING, "port %u some hash Rx queue still remain", 1423 dev->data->port_id); 1424 ret = mlx5_ind_table_obj_verify(dev); 1425 if (ret) 1426 DRV_LOG(WARNING, "port %u some indirection table still remain", 1427 dev->data->port_id); 1428 ret = mlx5_rxq_obj_verify(dev); 1429 if (ret) 1430 DRV_LOG(WARNING, "port %u some Rx queue objects still remain", 1431 dev->data->port_id); 1432 ret = mlx5_rxq_verify(dev); 1433 if (ret) 1434 DRV_LOG(WARNING, "port %u some Rx queues still remain", 1435 dev->data->port_id); 1436 ret = mlx5_txq_obj_verify(dev); 1437 if (ret) 1438 DRV_LOG(WARNING, "port %u some Verbs Tx queue still remain", 1439 dev->data->port_id); 1440 ret = mlx5_txq_verify(dev); 1441 if (ret) 1442 DRV_LOG(WARNING, "port %u some Tx queues still remain", 1443 dev->data->port_id); 1444 ret = mlx5_flow_verify(dev); 1445 if (ret) 1446 DRV_LOG(WARNING, "port %u some flows still remain", 1447 dev->data->port_id); 1448 /* 1449 * Free the shared context in last turn, because the cleanup 1450 * routines above may use some shared fields, like 1451 * mlx5_nl_mac_addr_flush() uses ibdev_path for retrieveing 1452 * ifindex if Netlink fails. 1453 */ 1454 mlx5_free_shared_dev_ctx(priv->sh); 1455 if (priv->domain_id != RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID) { 1456 unsigned int c = 0; 1457 uint16_t port_id; 1458 1459 MLX5_ETH_FOREACH_DEV(port_id, priv->pci_dev) { 1460 struct mlx5_priv *opriv = 1461 rte_eth_devices[port_id].data->dev_private; 1462 1463 if (!opriv || 1464 opriv->domain_id != priv->domain_id || 1465 &rte_eth_devices[port_id] == dev) 1466 continue; 1467 ++c; 1468 break; 1469 } 1470 if (!c) 1471 claim_zero(rte_eth_switch_domain_free(priv->domain_id)); 1472 } 1473 memset(priv, 0, sizeof(*priv)); 1474 priv->domain_id = RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID; 1475 /* 1476 * Reset mac_addrs to NULL such that it is not freed as part of 1477 * rte_eth_dev_release_port(). mac_addrs is part of dev_private so 1478 * it is freed when dev_private is freed. 1479 */ 1480 dev->data->mac_addrs = NULL; 1481 } 1482 1483 /** 1484 * Verify and store value for device argument. 1485 * 1486 * @param[in] key 1487 * Key argument to verify. 1488 * @param[in] val 1489 * Value associated with key. 1490 * @param opaque 1491 * User data. 1492 * 1493 * @return 1494 * 0 on success, a negative errno value otherwise and rte_errno is set. 1495 */ 1496 static int 1497 mlx5_args_check(const char *key, const char *val, void *opaque) 1498 { 1499 struct mlx5_dev_config *config = opaque; 1500 unsigned long mod; 1501 signed long tmp; 1502 1503 /* No-op, port representors are processed in mlx5_dev_spawn(). */ 1504 if (!strcmp(MLX5_REPRESENTOR, key)) 1505 return 0; 1506 errno = 0; 1507 tmp = strtol(val, NULL, 0); 1508 if (errno) { 1509 rte_errno = errno; 1510 DRV_LOG(WARNING, "%s: \"%s\" is not a valid integer", key, val); 1511 return -rte_errno; 1512 } 1513 if (tmp < 0 && strcmp(MLX5_TX_PP, key) && strcmp(MLX5_TX_SKEW, key)) { 1514 /* Negative values are acceptable for some keys only. */ 1515 rte_errno = EINVAL; 1516 DRV_LOG(WARNING, "%s: invalid negative value \"%s\"", key, val); 1517 return -rte_errno; 1518 } 1519 mod = tmp >= 0 ? tmp : -tmp; 1520 if (strcmp(MLX5_RXQ_CQE_COMP_EN, key) == 0) { 1521 config->cqe_comp = !!tmp; 1522 } else if (strcmp(MLX5_RXQ_CQE_PAD_EN, key) == 0) { 1523 config->cqe_pad = !!tmp; 1524 } else if (strcmp(MLX5_RXQ_PKT_PAD_EN, key) == 0) { 1525 config->hw_padding = !!tmp; 1526 } else if (strcmp(MLX5_RX_MPRQ_EN, key) == 0) { 1527 config->mprq.enabled = !!tmp; 1528 } else if (strcmp(MLX5_RX_MPRQ_LOG_STRIDE_NUM, key) == 0) { 1529 config->mprq.stride_num_n = tmp; 1530 } else if (strcmp(MLX5_RX_MPRQ_LOG_STRIDE_SIZE, key) == 0) { 1531 config->mprq.stride_size_n = tmp; 1532 } else if (strcmp(MLX5_RX_MPRQ_MAX_MEMCPY_LEN, key) == 0) { 1533 config->mprq.max_memcpy_len = tmp; 1534 } else if (strcmp(MLX5_RXQS_MIN_MPRQ, key) == 0) { 1535 config->mprq.min_rxqs_num = tmp; 1536 } else if (strcmp(MLX5_TXQ_INLINE, key) == 0) { 1537 DRV_LOG(WARNING, "%s: deprecated parameter," 1538 " converted to txq_inline_max", key); 1539 config->txq_inline_max = tmp; 1540 } else if (strcmp(MLX5_TXQ_INLINE_MAX, key) == 0) { 1541 config->txq_inline_max = tmp; 1542 } else if (strcmp(MLX5_TXQ_INLINE_MIN, key) == 0) { 1543 config->txq_inline_min = tmp; 1544 } else if (strcmp(MLX5_TXQ_INLINE_MPW, key) == 0) { 1545 config->txq_inline_mpw = tmp; 1546 } else if (strcmp(MLX5_TXQS_MIN_INLINE, key) == 0) { 1547 config->txqs_inline = tmp; 1548 } else if (strcmp(MLX5_TXQS_MAX_VEC, key) == 0) { 1549 DRV_LOG(WARNING, "%s: deprecated parameter, ignored", key); 1550 } else if (strcmp(MLX5_TXQ_MPW_EN, key) == 0) { 1551 config->mps = !!tmp; 1552 } else if (strcmp(MLX5_TX_DB_NC, key) == 0) { 1553 if (tmp != MLX5_TXDB_CACHED && 1554 tmp != MLX5_TXDB_NCACHED && 1555 tmp != MLX5_TXDB_HEURISTIC) { 1556 DRV_LOG(ERR, "invalid Tx doorbell " 1557 "mapping parameter"); 1558 rte_errno = EINVAL; 1559 return -rte_errno; 1560 } 1561 config->dbnc = tmp; 1562 } else if (strcmp(MLX5_TXQ_MPW_HDR_DSEG_EN, key) == 0) { 1563 DRV_LOG(WARNING, "%s: deprecated parameter, ignored", key); 1564 } else if (strcmp(MLX5_TXQ_MAX_INLINE_LEN, key) == 0) { 1565 DRV_LOG(WARNING, "%s: deprecated parameter," 1566 " converted to txq_inline_mpw", key); 1567 config->txq_inline_mpw = tmp; 1568 } else if (strcmp(MLX5_TX_VEC_EN, key) == 0) { 1569 DRV_LOG(WARNING, "%s: deprecated parameter, ignored", key); 1570 } else if (strcmp(MLX5_TX_PP, key) == 0) { 1571 if (!mod) { 1572 DRV_LOG(ERR, "Zero Tx packet pacing parameter"); 1573 rte_errno = EINVAL; 1574 return -rte_errno; 1575 } 1576 config->tx_pp = tmp; 1577 } else if (strcmp(MLX5_TX_SKEW, key) == 0) { 1578 config->tx_skew = tmp; 1579 } else if (strcmp(MLX5_RX_VEC_EN, key) == 0) { 1580 config->rx_vec_en = !!tmp; 1581 } else if (strcmp(MLX5_L3_VXLAN_EN, key) == 0) { 1582 config->l3_vxlan_en = !!tmp; 1583 } else if (strcmp(MLX5_VF_NL_EN, key) == 0) { 1584 config->vf_nl_en = !!tmp; 1585 } else if (strcmp(MLX5_DV_ESW_EN, key) == 0) { 1586 config->dv_esw_en = !!tmp; 1587 } else if (strcmp(MLX5_DV_FLOW_EN, key) == 0) { 1588 config->dv_flow_en = !!tmp; 1589 } else if (strcmp(MLX5_DV_XMETA_EN, key) == 0) { 1590 if (tmp != MLX5_XMETA_MODE_LEGACY && 1591 tmp != MLX5_XMETA_MODE_META16 && 1592 tmp != MLX5_XMETA_MODE_META32) { 1593 DRV_LOG(ERR, "invalid extensive " 1594 "metadata parameter"); 1595 rte_errno = EINVAL; 1596 return -rte_errno; 1597 } 1598 config->dv_xmeta_en = tmp; 1599 } else if (strcmp(MLX5_LACP_BY_USER, key) == 0) { 1600 config->lacp_by_user = !!tmp; 1601 } else if (strcmp(MLX5_MR_EXT_MEMSEG_EN, key) == 0) { 1602 config->mr_ext_memseg_en = !!tmp; 1603 } else if (strcmp(MLX5_MAX_DUMP_FILES_NUM, key) == 0) { 1604 config->max_dump_files_num = tmp; 1605 } else if (strcmp(MLX5_LRO_TIMEOUT_USEC, key) == 0) { 1606 config->lro.timeout = tmp; 1607 } else if (strcmp(MLX5_CLASS_ARG_NAME, key) == 0) { 1608 DRV_LOG(DEBUG, "class argument is %s.", val); 1609 } else if (strcmp(MLX5_HP_BUF_SIZE, key) == 0) { 1610 config->log_hp_size = tmp; 1611 } else if (strcmp(MLX5_RECLAIM_MEM, key) == 0) { 1612 if (tmp != MLX5_RCM_NONE && 1613 tmp != MLX5_RCM_LIGHT && 1614 tmp != MLX5_RCM_AGGR) { 1615 DRV_LOG(ERR, "Unrecognize %s: \"%s\"", key, val); 1616 rte_errno = EINVAL; 1617 return -rte_errno; 1618 } 1619 config->reclaim_mode = tmp; 1620 } else if (strcmp(MLX5_SYS_MEM_EN, key) == 0) { 1621 config->sys_mem_en = !!tmp; 1622 } else if (strcmp(MLX5_DECAP_EN, key) == 0) { 1623 config->decap_en = !!tmp; 1624 } else { 1625 DRV_LOG(WARNING, "%s: unknown parameter", key); 1626 rte_errno = EINVAL; 1627 return -rte_errno; 1628 } 1629 return 0; 1630 } 1631 1632 /** 1633 * Parse device parameters. 1634 * 1635 * @param config 1636 * Pointer to device configuration structure. 1637 * @param devargs 1638 * Device arguments structure. 1639 * 1640 * @return 1641 * 0 on success, a negative errno value otherwise and rte_errno is set. 1642 */ 1643 int 1644 mlx5_args(struct mlx5_dev_config *config, struct rte_devargs *devargs) 1645 { 1646 const char **params = (const char *[]){ 1647 MLX5_RXQ_CQE_COMP_EN, 1648 MLX5_RXQ_CQE_PAD_EN, 1649 MLX5_RXQ_PKT_PAD_EN, 1650 MLX5_RX_MPRQ_EN, 1651 MLX5_RX_MPRQ_LOG_STRIDE_NUM, 1652 MLX5_RX_MPRQ_LOG_STRIDE_SIZE, 1653 MLX5_RX_MPRQ_MAX_MEMCPY_LEN, 1654 MLX5_RXQS_MIN_MPRQ, 1655 MLX5_TXQ_INLINE, 1656 MLX5_TXQ_INLINE_MIN, 1657 MLX5_TXQ_INLINE_MAX, 1658 MLX5_TXQ_INLINE_MPW, 1659 MLX5_TXQS_MIN_INLINE, 1660 MLX5_TXQS_MAX_VEC, 1661 MLX5_TXQ_MPW_EN, 1662 MLX5_TXQ_MPW_HDR_DSEG_EN, 1663 MLX5_TXQ_MAX_INLINE_LEN, 1664 MLX5_TX_DB_NC, 1665 MLX5_TX_PP, 1666 MLX5_TX_SKEW, 1667 MLX5_TX_VEC_EN, 1668 MLX5_RX_VEC_EN, 1669 MLX5_L3_VXLAN_EN, 1670 MLX5_VF_NL_EN, 1671 MLX5_DV_ESW_EN, 1672 MLX5_DV_FLOW_EN, 1673 MLX5_DV_XMETA_EN, 1674 MLX5_LACP_BY_USER, 1675 MLX5_MR_EXT_MEMSEG_EN, 1676 MLX5_REPRESENTOR, 1677 MLX5_MAX_DUMP_FILES_NUM, 1678 MLX5_LRO_TIMEOUT_USEC, 1679 MLX5_CLASS_ARG_NAME, 1680 MLX5_HP_BUF_SIZE, 1681 MLX5_RECLAIM_MEM, 1682 MLX5_SYS_MEM_EN, 1683 MLX5_DECAP_EN, 1684 NULL, 1685 }; 1686 struct rte_kvargs *kvlist; 1687 int ret = 0; 1688 int i; 1689 1690 if (devargs == NULL) 1691 return 0; 1692 /* Following UGLY cast is done to pass checkpatch. */ 1693 kvlist = rte_kvargs_parse(devargs->args, params); 1694 if (kvlist == NULL) { 1695 rte_errno = EINVAL; 1696 return -rte_errno; 1697 } 1698 /* Process parameters. */ 1699 for (i = 0; (params[i] != NULL); ++i) { 1700 if (rte_kvargs_count(kvlist, params[i])) { 1701 ret = rte_kvargs_process(kvlist, params[i], 1702 mlx5_args_check, config); 1703 if (ret) { 1704 rte_errno = EINVAL; 1705 rte_kvargs_free(kvlist); 1706 return -rte_errno; 1707 } 1708 } 1709 } 1710 rte_kvargs_free(kvlist); 1711 return 0; 1712 } 1713 1714 /** 1715 * Configures the minimal amount of data to inline into WQE 1716 * while sending packets. 1717 * 1718 * - the txq_inline_min has the maximal priority, if this 1719 * key is specified in devargs 1720 * - if DevX is enabled the inline mode is queried from the 1721 * device (HCA attributes and NIC vport context if needed). 1722 * - otherwise L2 mode (18 bytes) is assumed for ConnectX-4/4 Lx 1723 * and none (0 bytes) for other NICs 1724 * 1725 * @param spawn 1726 * Verbs device parameters (name, port, switch_info) to spawn. 1727 * @param config 1728 * Device configuration parameters. 1729 */ 1730 void 1731 mlx5_set_min_inline(struct mlx5_dev_spawn_data *spawn, 1732 struct mlx5_dev_config *config) 1733 { 1734 if (config->txq_inline_min != MLX5_ARG_UNSET) { 1735 /* Application defines size of inlined data explicitly. */ 1736 switch (spawn->pci_dev->id.device_id) { 1737 case PCI_DEVICE_ID_MELLANOX_CONNECTX4: 1738 case PCI_DEVICE_ID_MELLANOX_CONNECTX4VF: 1739 if (config->txq_inline_min < 1740 (int)MLX5_INLINE_HSIZE_L2) { 1741 DRV_LOG(DEBUG, 1742 "txq_inline_mix aligned to minimal" 1743 " ConnectX-4 required value %d", 1744 (int)MLX5_INLINE_HSIZE_L2); 1745 config->txq_inline_min = MLX5_INLINE_HSIZE_L2; 1746 } 1747 break; 1748 } 1749 goto exit; 1750 } 1751 if (config->hca_attr.eth_net_offloads) { 1752 /* We have DevX enabled, inline mode queried successfully. */ 1753 switch (config->hca_attr.wqe_inline_mode) { 1754 case MLX5_CAP_INLINE_MODE_L2: 1755 /* outer L2 header must be inlined. */ 1756 config->txq_inline_min = MLX5_INLINE_HSIZE_L2; 1757 goto exit; 1758 case MLX5_CAP_INLINE_MODE_NOT_REQUIRED: 1759 /* No inline data are required by NIC. */ 1760 config->txq_inline_min = MLX5_INLINE_HSIZE_NONE; 1761 config->hw_vlan_insert = 1762 config->hca_attr.wqe_vlan_insert; 1763 DRV_LOG(DEBUG, "Tx VLAN insertion is supported"); 1764 goto exit; 1765 case MLX5_CAP_INLINE_MODE_VPORT_CONTEXT: 1766 /* inline mode is defined by NIC vport context. */ 1767 if (!config->hca_attr.eth_virt) 1768 break; 1769 switch (config->hca_attr.vport_inline_mode) { 1770 case MLX5_INLINE_MODE_NONE: 1771 config->txq_inline_min = 1772 MLX5_INLINE_HSIZE_NONE; 1773 goto exit; 1774 case MLX5_INLINE_MODE_L2: 1775 config->txq_inline_min = 1776 MLX5_INLINE_HSIZE_L2; 1777 goto exit; 1778 case MLX5_INLINE_MODE_IP: 1779 config->txq_inline_min = 1780 MLX5_INLINE_HSIZE_L3; 1781 goto exit; 1782 case MLX5_INLINE_MODE_TCP_UDP: 1783 config->txq_inline_min = 1784 MLX5_INLINE_HSIZE_L4; 1785 goto exit; 1786 case MLX5_INLINE_MODE_INNER_L2: 1787 config->txq_inline_min = 1788 MLX5_INLINE_HSIZE_INNER_L2; 1789 goto exit; 1790 case MLX5_INLINE_MODE_INNER_IP: 1791 config->txq_inline_min = 1792 MLX5_INLINE_HSIZE_INNER_L3; 1793 goto exit; 1794 case MLX5_INLINE_MODE_INNER_TCP_UDP: 1795 config->txq_inline_min = 1796 MLX5_INLINE_HSIZE_INNER_L4; 1797 goto exit; 1798 } 1799 } 1800 } 1801 /* 1802 * We get here if we are unable to deduce 1803 * inline data size with DevX. Try PCI ID 1804 * to determine old NICs. 1805 */ 1806 switch (spawn->pci_dev->id.device_id) { 1807 case PCI_DEVICE_ID_MELLANOX_CONNECTX4: 1808 case PCI_DEVICE_ID_MELLANOX_CONNECTX4VF: 1809 case PCI_DEVICE_ID_MELLANOX_CONNECTX4LX: 1810 case PCI_DEVICE_ID_MELLANOX_CONNECTX4LXVF: 1811 config->txq_inline_min = MLX5_INLINE_HSIZE_L2; 1812 config->hw_vlan_insert = 0; 1813 break; 1814 case PCI_DEVICE_ID_MELLANOX_CONNECTX5: 1815 case PCI_DEVICE_ID_MELLANOX_CONNECTX5VF: 1816 case PCI_DEVICE_ID_MELLANOX_CONNECTX5EX: 1817 case PCI_DEVICE_ID_MELLANOX_CONNECTX5EXVF: 1818 /* 1819 * These NICs support VLAN insertion from WQE and 1820 * report the wqe_vlan_insert flag. But there is the bug 1821 * and PFC control may be broken, so disable feature. 1822 */ 1823 config->hw_vlan_insert = 0; 1824 config->txq_inline_min = MLX5_INLINE_HSIZE_NONE; 1825 break; 1826 default: 1827 config->txq_inline_min = MLX5_INLINE_HSIZE_NONE; 1828 break; 1829 } 1830 exit: 1831 DRV_LOG(DEBUG, "min tx inline configured: %d", config->txq_inline_min); 1832 } 1833 1834 /** 1835 * Configures the metadata mask fields in the shared context. 1836 * 1837 * @param [in] dev 1838 * Pointer to Ethernet device. 1839 */ 1840 void 1841 mlx5_set_metadata_mask(struct rte_eth_dev *dev) 1842 { 1843 struct mlx5_priv *priv = dev->data->dev_private; 1844 struct mlx5_dev_ctx_shared *sh = priv->sh; 1845 uint32_t meta, mark, reg_c0; 1846 1847 reg_c0 = ~priv->vport_meta_mask; 1848 switch (priv->config.dv_xmeta_en) { 1849 case MLX5_XMETA_MODE_LEGACY: 1850 meta = UINT32_MAX; 1851 mark = MLX5_FLOW_MARK_MASK; 1852 break; 1853 case MLX5_XMETA_MODE_META16: 1854 meta = reg_c0 >> rte_bsf32(reg_c0); 1855 mark = MLX5_FLOW_MARK_MASK; 1856 break; 1857 case MLX5_XMETA_MODE_META32: 1858 meta = UINT32_MAX; 1859 mark = (reg_c0 >> rte_bsf32(reg_c0)) & MLX5_FLOW_MARK_MASK; 1860 break; 1861 default: 1862 meta = 0; 1863 mark = 0; 1864 MLX5_ASSERT(false); 1865 break; 1866 } 1867 if (sh->dv_mark_mask && sh->dv_mark_mask != mark) 1868 DRV_LOG(WARNING, "metadata MARK mask mismatche %08X:%08X", 1869 sh->dv_mark_mask, mark); 1870 else 1871 sh->dv_mark_mask = mark; 1872 if (sh->dv_meta_mask && sh->dv_meta_mask != meta) 1873 DRV_LOG(WARNING, "metadata META mask mismatche %08X:%08X", 1874 sh->dv_meta_mask, meta); 1875 else 1876 sh->dv_meta_mask = meta; 1877 if (sh->dv_regc0_mask && sh->dv_regc0_mask != reg_c0) 1878 DRV_LOG(WARNING, "metadata reg_c0 mask mismatche %08X:%08X", 1879 sh->dv_meta_mask, reg_c0); 1880 else 1881 sh->dv_regc0_mask = reg_c0; 1882 DRV_LOG(DEBUG, "metadata mode %u", priv->config.dv_xmeta_en); 1883 DRV_LOG(DEBUG, "metadata MARK mask %08X", sh->dv_mark_mask); 1884 DRV_LOG(DEBUG, "metadata META mask %08X", sh->dv_meta_mask); 1885 DRV_LOG(DEBUG, "metadata reg_c0 mask %08X", sh->dv_regc0_mask); 1886 } 1887 1888 int 1889 rte_pmd_mlx5_get_dyn_flag_names(char *names[], unsigned int n) 1890 { 1891 static const char *const dynf_names[] = { 1892 RTE_PMD_MLX5_FINE_GRANULARITY_INLINE, 1893 RTE_MBUF_DYNFLAG_METADATA_NAME, 1894 RTE_MBUF_DYNFLAG_TX_TIMESTAMP_NAME 1895 }; 1896 unsigned int i; 1897 1898 if (n < RTE_DIM(dynf_names)) 1899 return -ENOMEM; 1900 for (i = 0; i < RTE_DIM(dynf_names); i++) { 1901 if (names[i] == NULL) 1902 return -EINVAL; 1903 strcpy(names[i], dynf_names[i]); 1904 } 1905 return RTE_DIM(dynf_names); 1906 } 1907 1908 /** 1909 * Comparison callback to sort device data. 1910 * 1911 * This is meant to be used with qsort(). 1912 * 1913 * @param a[in] 1914 * Pointer to pointer to first data object. 1915 * @param b[in] 1916 * Pointer to pointer to second data object. 1917 * 1918 * @return 1919 * 0 if both objects are equal, less than 0 if the first argument is less 1920 * than the second, greater than 0 otherwise. 1921 */ 1922 int 1923 mlx5_dev_check_sibling_config(struct mlx5_priv *priv, 1924 struct mlx5_dev_config *config) 1925 { 1926 struct mlx5_dev_ctx_shared *sh = priv->sh; 1927 struct mlx5_dev_config *sh_conf = NULL; 1928 uint16_t port_id; 1929 1930 MLX5_ASSERT(sh); 1931 /* Nothing to compare for the single/first device. */ 1932 if (sh->refcnt == 1) 1933 return 0; 1934 /* Find the device with shared context. */ 1935 MLX5_ETH_FOREACH_DEV(port_id, priv->pci_dev) { 1936 struct mlx5_priv *opriv = 1937 rte_eth_devices[port_id].data->dev_private; 1938 1939 if (opriv && opriv != priv && opriv->sh == sh) { 1940 sh_conf = &opriv->config; 1941 break; 1942 } 1943 } 1944 if (!sh_conf) 1945 return 0; 1946 if (sh_conf->dv_flow_en ^ config->dv_flow_en) { 1947 DRV_LOG(ERR, "\"dv_flow_en\" configuration mismatch" 1948 " for shared %s context", sh->ibdev_name); 1949 rte_errno = EINVAL; 1950 return rte_errno; 1951 } 1952 if (sh_conf->dv_xmeta_en ^ config->dv_xmeta_en) { 1953 DRV_LOG(ERR, "\"dv_xmeta_en\" configuration mismatch" 1954 " for shared %s context", sh->ibdev_name); 1955 rte_errno = EINVAL; 1956 return rte_errno; 1957 } 1958 return 0; 1959 } 1960 1961 /** 1962 * Look for the ethernet device belonging to mlx5 driver. 1963 * 1964 * @param[in] port_id 1965 * port_id to start looking for device. 1966 * @param[in] pci_dev 1967 * Pointer to the hint PCI device. When device is being probed 1968 * the its siblings (master and preceding representors might 1969 * not have assigned driver yet (because the mlx5_os_pci_probe() 1970 * is not completed yet, for this case match on hint PCI 1971 * device may be used to detect sibling device. 1972 * 1973 * @return 1974 * port_id of found device, RTE_MAX_ETHPORT if not found. 1975 */ 1976 uint16_t 1977 mlx5_eth_find_next(uint16_t port_id, struct rte_pci_device *pci_dev) 1978 { 1979 while (port_id < RTE_MAX_ETHPORTS) { 1980 struct rte_eth_dev *dev = &rte_eth_devices[port_id]; 1981 1982 if (dev->state != RTE_ETH_DEV_UNUSED && 1983 dev->device && 1984 (dev->device == &pci_dev->device || 1985 (dev->device->driver && 1986 dev->device->driver->name && 1987 !strcmp(dev->device->driver->name, MLX5_DRIVER_NAME)))) 1988 break; 1989 port_id++; 1990 } 1991 if (port_id >= RTE_MAX_ETHPORTS) 1992 return RTE_MAX_ETHPORTS; 1993 return port_id; 1994 } 1995 1996 /** 1997 * DPDK callback to remove a PCI device. 1998 * 1999 * This function removes all Ethernet devices belong to a given PCI device. 2000 * 2001 * @param[in] pci_dev 2002 * Pointer to the PCI device. 2003 * 2004 * @return 2005 * 0 on success, the function cannot fail. 2006 */ 2007 static int 2008 mlx5_pci_remove(struct rte_pci_device *pci_dev) 2009 { 2010 uint16_t port_id; 2011 2012 RTE_ETH_FOREACH_DEV_OF(port_id, &pci_dev->device) { 2013 /* 2014 * mlx5_dev_close() is not registered to secondary process, 2015 * call the close function explicitly for secondary process. 2016 */ 2017 if (rte_eal_process_type() == RTE_PROC_SECONDARY) 2018 mlx5_dev_close(&rte_eth_devices[port_id]); 2019 else 2020 rte_eth_dev_close(port_id); 2021 } 2022 return 0; 2023 } 2024 2025 static const struct rte_pci_id mlx5_pci_id_map[] = { 2026 { 2027 RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 2028 PCI_DEVICE_ID_MELLANOX_CONNECTX4) 2029 }, 2030 { 2031 RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 2032 PCI_DEVICE_ID_MELLANOX_CONNECTX4VF) 2033 }, 2034 { 2035 RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 2036 PCI_DEVICE_ID_MELLANOX_CONNECTX4LX) 2037 }, 2038 { 2039 RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 2040 PCI_DEVICE_ID_MELLANOX_CONNECTX4LXVF) 2041 }, 2042 { 2043 RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 2044 PCI_DEVICE_ID_MELLANOX_CONNECTX5) 2045 }, 2046 { 2047 RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 2048 PCI_DEVICE_ID_MELLANOX_CONNECTX5VF) 2049 }, 2050 { 2051 RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 2052 PCI_DEVICE_ID_MELLANOX_CONNECTX5EX) 2053 }, 2054 { 2055 RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 2056 PCI_DEVICE_ID_MELLANOX_CONNECTX5EXVF) 2057 }, 2058 { 2059 RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 2060 PCI_DEVICE_ID_MELLANOX_CONNECTX5BF) 2061 }, 2062 { 2063 RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 2064 PCI_DEVICE_ID_MELLANOX_CONNECTX5BFVF) 2065 }, 2066 { 2067 RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 2068 PCI_DEVICE_ID_MELLANOX_CONNECTX6) 2069 }, 2070 { 2071 RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 2072 PCI_DEVICE_ID_MELLANOX_CONNECTX6VF) 2073 }, 2074 { 2075 RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 2076 PCI_DEVICE_ID_MELLANOX_CONNECTX6DX) 2077 }, 2078 { 2079 RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 2080 PCI_DEVICE_ID_MELLANOX_CONNECTX6DXVF) 2081 }, 2082 { 2083 RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 2084 PCI_DEVICE_ID_MELLANOX_CONNECTX6DXBF) 2085 }, 2086 { 2087 RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 2088 PCI_DEVICE_ID_MELLANOX_CONNECTX6LX) 2089 }, 2090 { 2091 .vendor_id = 0 2092 } 2093 }; 2094 2095 static struct mlx5_pci_driver mlx5_driver = { 2096 .driver_class = MLX5_CLASS_NET, 2097 .pci_driver = { 2098 .driver = { 2099 .name = MLX5_DRIVER_NAME, 2100 }, 2101 .id_table = mlx5_pci_id_map, 2102 .probe = mlx5_os_pci_probe, 2103 .remove = mlx5_pci_remove, 2104 .dma_map = mlx5_dma_map, 2105 .dma_unmap = mlx5_dma_unmap, 2106 .drv_flags = PCI_DRV_FLAGS, 2107 }, 2108 }; 2109 2110 /* Initialize driver log type. */ 2111 RTE_LOG_REGISTER(mlx5_logtype, pmd.net.mlx5, NOTICE) 2112 2113 /** 2114 * Driver initialization routine. 2115 */ 2116 RTE_INIT(rte_mlx5_pmd_init) 2117 { 2118 mlx5_common_init(); 2119 /* Build the static tables for Verbs conversion. */ 2120 mlx5_set_ptype_table(); 2121 mlx5_set_cksum_table(); 2122 mlx5_set_swp_types_table(); 2123 if (mlx5_glue) 2124 mlx5_pci_driver_register(&mlx5_driver); 2125 } 2126 2127 RTE_PMD_EXPORT_NAME(net_mlx5, __COUNTER__); 2128 RTE_PMD_REGISTER_PCI_TABLE(net_mlx5, mlx5_pci_id_map); 2129 RTE_PMD_REGISTER_KMOD_DEP(net_mlx5, "* ib_uverbs & mlx5_core & mlx5_ib"); 2130