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