1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2020 Mellanox Technologies, Ltd 3 */ 4 5 #include <errno.h> 6 #include <stdalign.h> 7 #include <stddef.h> 8 #include <stdint.h> 9 #include <stdlib.h> 10 11 #include <rte_windows.h> 12 #include <ethdev_pci.h> 13 14 #include <mlx5_glue.h> 15 #include <mlx5_devx_cmds.h> 16 #include <mlx5_common.h> 17 #include <mlx5_common_mp.h> 18 #include <mlx5_common_mr.h> 19 #include <mlx5_malloc.h> 20 21 #include "mlx5_defs.h" 22 #include "mlx5.h" 23 #include "mlx5_common_os.h" 24 #include "mlx5_utils.h" 25 #include "mlx5_rxtx.h" 26 #include "mlx5_rx.h" 27 #include "mlx5_tx.h" 28 #include "mlx5_autoconf.h" 29 #include "mlx5_flow.h" 30 #include "mlx5_devx.h" 31 32 static const char *MZ_MLX5_PMD_SHARED_DATA = "mlx5_pmd_shared_data"; 33 34 /* Spinlock for mlx5_shared_data allocation. */ 35 static rte_spinlock_t mlx5_shared_data_lock = RTE_SPINLOCK_INITIALIZER; 36 37 /* rte flow indexed pool configuration. */ 38 static struct mlx5_indexed_pool_config icfg[] = { 39 { 40 .size = sizeof(struct rte_flow), 41 .trunk_size = 64, 42 .need_lock = 1, 43 .release_mem_en = 0, 44 .malloc = mlx5_malloc, 45 .free = mlx5_free, 46 .per_core_cache = 0, 47 .type = "ctl_flow_ipool", 48 }, 49 { 50 .size = sizeof(struct rte_flow), 51 .trunk_size = 64, 52 .grow_trunk = 3, 53 .grow_shift = 2, 54 .need_lock = 1, 55 .release_mem_en = 0, 56 .malloc = mlx5_malloc, 57 .free = mlx5_free, 58 .per_core_cache = 1 << 14, 59 .type = "rte_flow_ipool", 60 }, 61 { 62 .size = sizeof(struct rte_flow), 63 .trunk_size = 64, 64 .grow_trunk = 3, 65 .grow_shift = 2, 66 .need_lock = 1, 67 .release_mem_en = 0, 68 .malloc = mlx5_malloc, 69 .free = mlx5_free, 70 .per_core_cache = 0, 71 .type = "mcp_flow_ipool", 72 }, 73 }; 74 75 /** 76 * Initialize shared data between primary and secondary process. 77 * 78 * A memzone is reserved by primary process and secondary processes attach to 79 * the memzone. 80 * 81 * @return 82 * 0 on success, a negative errno value otherwise and rte_errno is set. 83 */ 84 static int 85 mlx5_init_shared_data(void) 86 { 87 const struct rte_memzone *mz; 88 int ret = 0; 89 90 rte_spinlock_lock(&mlx5_shared_data_lock); 91 if (mlx5_shared_data == NULL) { 92 /* Allocate shared memory. */ 93 mz = rte_memzone_reserve(MZ_MLX5_PMD_SHARED_DATA, 94 sizeof(*mlx5_shared_data), 95 SOCKET_ID_ANY, 0); 96 if (mz == NULL) { 97 DRV_LOG(ERR, 98 "Cannot allocate mlx5 shared data"); 99 ret = -rte_errno; 100 goto error; 101 } 102 mlx5_shared_data = mz->addr; 103 memset(mlx5_shared_data, 0, sizeof(*mlx5_shared_data)); 104 rte_spinlock_init(&mlx5_shared_data->lock); 105 } 106 error: 107 rte_spinlock_unlock(&mlx5_shared_data_lock); 108 return ret; 109 } 110 111 /** 112 * PMD global initialization. 113 * 114 * Independent from individual device, this function initializes global 115 * per-PMD data structures distinguishing primary and secondary processes. 116 * Hence, each initialization is called once per a process. 117 * 118 * @return 119 * 0 on success, a negative errno value otherwise and rte_errno is set. 120 */ 121 static int 122 mlx5_init_once(void) 123 { 124 if (mlx5_init_shared_data()) 125 return -rte_errno; 126 return 0; 127 } 128 129 /** 130 * Get mlx5 device attributes. 131 * 132 * @param cdev 133 * Pointer to mlx5 device. 134 * 135 * @param device_attr 136 * Pointer to mlx5 device attributes. 137 * 138 * @return 139 * 0 on success, non zero error number otherwise. 140 */ 141 int 142 mlx5_os_get_dev_attr(struct mlx5_common_device *cdev, 143 struct mlx5_dev_attr *device_attr) 144 { 145 struct mlx5_context *mlx5_ctx; 146 void *pv_iseg = NULL; 147 u32 cb_iseg = 0; 148 int err = 0; 149 150 if (!cdev || !cdev->ctx) 151 return -EINVAL; 152 mlx5_ctx = (struct mlx5_context *)cdev->ctx; 153 memset(device_attr, 0, sizeof(*device_attr)); 154 device_attr->max_cq = 1 << cdev->config.hca_attr.log_max_cq; 155 device_attr->max_qp = 1 << cdev->config.hca_attr.log_max_qp; 156 device_attr->max_qp_wr = 1 << cdev->config.hca_attr.log_max_qp_sz; 157 device_attr->max_cqe = 1 << cdev->config.hca_attr.log_max_cq_sz; 158 device_attr->max_mr = 1 << cdev->config.hca_attr.log_max_mrw_sz; 159 device_attr->max_pd = 1 << cdev->config.hca_attr.log_max_pd; 160 device_attr->max_srq = 1 << cdev->config.hca_attr.log_max_srq; 161 device_attr->max_srq_wr = 1 << cdev->config.hca_attr.log_max_srq_sz; 162 device_attr->max_tso = 1 << cdev->config.hca_attr.max_lso_cap; 163 if (cdev->config.hca_attr.rss_ind_tbl_cap) { 164 device_attr->max_rwq_indirection_table_size = 165 1 << cdev->config.hca_attr.rss_ind_tbl_cap; 166 } 167 device_attr->sw_parsing_offloads = 168 mlx5_get_supported_sw_parsing_offloads(&cdev->config.hca_attr); 169 device_attr->tunnel_offloads_caps = 170 mlx5_get_supported_tunneling_offloads(&cdev->config.hca_attr); 171 pv_iseg = mlx5_glue->query_hca_iseg(mlx5_ctx, &cb_iseg); 172 if (pv_iseg == NULL) { 173 DRV_LOG(ERR, "Failed to get device hca_iseg"); 174 return errno; 175 } 176 if (!err) { 177 snprintf(device_attr->fw_ver, 64, "%x.%x.%04x", 178 MLX5_GET(initial_seg, pv_iseg, fw_rev_major), 179 MLX5_GET(initial_seg, pv_iseg, fw_rev_minor), 180 MLX5_GET(initial_seg, pv_iseg, fw_rev_subminor)); 181 } 182 return err; 183 } 184 185 /** 186 * Initialize DR related data within private structure. 187 * Routine checks the reference counter and does actual 188 * resources creation/initialization only if counter is zero. 189 * 190 * @param[in] priv 191 * Pointer to the private device data structure. 192 * 193 * @return 194 * Zero on success, positive error code otherwise. 195 */ 196 static int 197 mlx5_alloc_shared_dr(struct mlx5_priv *priv) 198 { 199 struct mlx5_dev_ctx_shared *sh = priv->sh; 200 int err = 0; 201 202 if (!sh->flow_tbls) 203 err = mlx5_alloc_table_hash_list(priv); 204 else 205 DRV_LOG(DEBUG, "sh->flow_tbls[%p] already created, reuse", 206 (void *)sh->flow_tbls); 207 return err; 208 } 209 /** 210 * Destroy DR related data within private structure. 211 * 212 * @param[in] priv 213 * Pointer to the private device data structure. 214 */ 215 void 216 mlx5_os_free_shared_dr(struct mlx5_priv *priv) 217 { 218 mlx5_free_table_hash_list(priv); 219 } 220 221 /** 222 * Set the completion channel file descriptor interrupt as non-blocking. 223 * Currently it has no support under Windows. 224 * 225 * @param[in] rxq_obj 226 * Pointer to RQ channel object, which includes the channel fd 227 * 228 * @param[out] fd 229 * The file descriptor (representing the intetrrupt) used in this channel. 230 * 231 * @return 232 * 0 on successfully setting the fd to non-blocking, non-zero otherwise. 233 */ 234 int 235 mlx5_os_set_nonblock_channel_fd(int fd) 236 { 237 (void)fd; 238 DRV_LOG(WARNING, "%s: is not supported", __func__); 239 return -ENOTSUP; 240 } 241 242 /** 243 * DV flow counter mode detect and config. 244 * 245 * @param dev 246 * Pointer to rte_eth_dev structure. 247 * 248 */ 249 static void 250 mlx5_flow_counter_mode_config(struct rte_eth_dev *dev __rte_unused) 251 { 252 #ifdef HAVE_IBV_FLOW_DV_SUPPORT 253 struct mlx5_priv *priv = dev->data->dev_private; 254 struct mlx5_dev_ctx_shared *sh = priv->sh; 255 bool fallback; 256 257 #ifndef HAVE_IBV_DEVX_ASYNC 258 fallback = true; 259 #else 260 fallback = false; 261 if (!sh->devx || !priv->config.dv_flow_en || 262 !priv->config.hca_attr.flow_counters_dump || 263 !(priv->config.hca_attr.flow_counter_bulk_alloc_bitmap & 0x4) || 264 (mlx5_flow_dv_discover_counter_offset_support(dev) == -ENOTSUP)) 265 fallback = true; 266 #endif 267 if (fallback) 268 DRV_LOG(INFO, "Use fall-back DV counter management. Flow " 269 "counter dump:%d, bulk_alloc_bitmap:0x%hhx.", 270 priv->config.hca_attr.flow_counters_dump, 271 priv->config.hca_attr.flow_counter_bulk_alloc_bitmap); 272 /* Initialize fallback mode only on the port initializes sh. */ 273 if (sh->refcnt == 1) 274 sh->cmng.counter_fallback = fallback; 275 else if (fallback != sh->cmng.counter_fallback) 276 DRV_LOG(WARNING, "Port %d in sh has different fallback mode " 277 "with others:%d.", PORT_ID(priv), fallback); 278 #endif 279 } 280 281 /** 282 * Spawn an Ethernet device from DevX information. 283 * 284 * @param dpdk_dev 285 * Backing DPDK device. 286 * @param spawn 287 * Verbs device parameters (name, port, switch_info) to spawn. 288 * @param config 289 * Device configuration parameters. 290 * 291 * @return 292 * A valid Ethernet device object on success, NULL otherwise and rte_errno 293 * is set. The following errors are defined: 294 * 295 * EEXIST: device is already spawned 296 */ 297 static struct rte_eth_dev * 298 mlx5_dev_spawn(struct rte_device *dpdk_dev, 299 struct mlx5_dev_spawn_data *spawn, 300 struct mlx5_dev_config *config) 301 { 302 const struct mlx5_switch_info *switch_info = &spawn->info; 303 struct mlx5_dev_ctx_shared *sh = NULL; 304 struct mlx5_dev_attr device_attr; 305 struct rte_eth_dev *eth_dev = NULL; 306 struct mlx5_priv *priv = NULL; 307 int err = 0; 308 unsigned int cqe_comp; 309 struct rte_ether_addr mac; 310 char name[RTE_ETH_NAME_MAX_LEN]; 311 int own_domain_id = 0; 312 uint16_t port_id; 313 int i; 314 315 /* Build device name. */ 316 strlcpy(name, dpdk_dev->name, sizeof(name)); 317 /* check if the device is already spawned */ 318 if (rte_eth_dev_get_port_by_name(name, &port_id) == 0) { 319 rte_errno = EEXIST; 320 return NULL; 321 } 322 DRV_LOG(DEBUG, "naming Ethernet device \"%s\"", name); 323 /* 324 * Some parameters are needed in advance to create device context. We 325 * process the devargs here to get ones, and later process devargs 326 * again to override some hardware settings. 327 */ 328 err = mlx5_args(config, dpdk_dev->devargs); 329 if (err) { 330 err = rte_errno; 331 DRV_LOG(ERR, "failed to process device arguments: %s", 332 strerror(rte_errno)); 333 goto error; 334 } 335 sh = mlx5_alloc_shared_dev_ctx(spawn, config); 336 if (!sh) 337 return NULL; 338 /* Initialize the shutdown event in mlx5_dev_spawn to 339 * support mlx5_is_removed for Windows. 340 */ 341 err = mlx5_glue->devx_init_showdown_event(sh->cdev->ctx); 342 if (err) { 343 DRV_LOG(ERR, "failed to init showdown event: %s", 344 strerror(errno)); 345 goto error; 346 } 347 DRV_LOG(DEBUG, "MPW isn't supported"); 348 mlx5_os_get_dev_attr(sh->cdev, &device_attr); 349 config->swp = device_attr.sw_parsing_offloads & 350 (MLX5_SW_PARSING_CAP | MLX5_SW_PARSING_CSUM_CAP | 351 MLX5_SW_PARSING_TSO_CAP); 352 config->ind_table_max_size = 353 sh->device_attr.max_rwq_indirection_table_size; 354 cqe_comp = 0; 355 config->cqe_comp = cqe_comp; 356 config->tunnel_en = device_attr.tunnel_offloads_caps & 357 (MLX5_TUNNELED_OFFLOADS_VXLAN_CAP | 358 MLX5_TUNNELED_OFFLOADS_GRE_CAP | 359 MLX5_TUNNELED_OFFLOADS_GENEVE_CAP); 360 if (config->tunnel_en) { 361 DRV_LOG(DEBUG, "tunnel offloading is supported for %s%s%s", 362 config->tunnel_en & 363 MLX5_TUNNELED_OFFLOADS_VXLAN_CAP ? "[VXLAN]" : "", 364 config->tunnel_en & 365 MLX5_TUNNELED_OFFLOADS_GRE_CAP ? "[GRE]" : "", 366 config->tunnel_en & 367 MLX5_TUNNELED_OFFLOADS_GENEVE_CAP ? "[GENEVE]" : "" 368 ); 369 } else { 370 DRV_LOG(DEBUG, "tunnel offloading is not supported"); 371 } 372 DRV_LOG(DEBUG, "MPLS over GRE/UDP tunnel offloading is no supported"); 373 config->mpls_en = 0; 374 /* Allocate private eth device data. */ 375 priv = mlx5_malloc(MLX5_MEM_ZERO | MLX5_MEM_RTE, 376 sizeof(*priv), 377 RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY); 378 if (priv == NULL) { 379 DRV_LOG(ERR, "priv allocation failure"); 380 err = ENOMEM; 381 goto error; 382 } 383 priv->sh = sh; 384 priv->dev_port = spawn->phys_port; 385 priv->pci_dev = spawn->pci_dev; 386 priv->mtu = RTE_ETHER_MTU; 387 priv->mp_id.port_id = port_id; 388 strlcpy(priv->mp_id.name, MLX5_MP_NAME, RTE_MP_MAX_NAME_LEN); 389 priv->representor = !!switch_info->representor; 390 priv->master = !!switch_info->master; 391 priv->domain_id = RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID; 392 priv->vport_meta_tag = 0; 393 priv->vport_meta_mask = 0; 394 priv->pf_bond = spawn->pf_bond; 395 priv->vport_id = -1; 396 /* representor_id field keeps the unmodified VF index. */ 397 priv->representor_id = -1; 398 /* 399 * Look for sibling devices in order to reuse their switch domain 400 * if any, otherwise allocate one. 401 */ 402 MLX5_ETH_FOREACH_DEV(port_id, dpdk_dev) { 403 const struct mlx5_priv *opriv = 404 rte_eth_devices[port_id].data->dev_private; 405 406 if (!opriv || 407 opriv->sh != priv->sh || 408 opriv->domain_id == 409 RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID) 410 continue; 411 priv->domain_id = opriv->domain_id; 412 break; 413 } 414 if (priv->domain_id == RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID) { 415 err = rte_eth_switch_domain_alloc(&priv->domain_id); 416 if (err) { 417 err = rte_errno; 418 DRV_LOG(ERR, "unable to allocate switch domain: %s", 419 strerror(rte_errno)); 420 goto error; 421 } 422 own_domain_id = 1; 423 } 424 /* Override some values set by hardware configuration. */ 425 mlx5_args(config, dpdk_dev->devargs); 426 err = mlx5_dev_check_sibling_config(priv, config, dpdk_dev); 427 if (err) 428 goto error; 429 DRV_LOG(DEBUG, "counters are not supported"); 430 config->ind_table_max_size = 431 sh->device_attr.max_rwq_indirection_table_size; 432 /* 433 * Remove this check once DPDK supports larger/variable 434 * indirection tables. 435 */ 436 if (config->ind_table_max_size > (unsigned int)RTE_ETH_RSS_RETA_SIZE_512) 437 config->ind_table_max_size = RTE_ETH_RSS_RETA_SIZE_512; 438 DRV_LOG(DEBUG, "maximum Rx indirection table size is %u", 439 config->ind_table_max_size); 440 if (config->hw_padding) { 441 DRV_LOG(DEBUG, "Rx end alignment padding isn't supported"); 442 config->hw_padding = 0; 443 } 444 config->tso = (sh->device_attr.max_tso > 0); 445 if (config->tso) 446 config->tso_max_payload_sz = sh->device_attr.max_tso; 447 DRV_LOG(DEBUG, "%sMPS is %s.", 448 config->mps == MLX5_MPW_ENHANCED ? "enhanced " : 449 config->mps == MLX5_MPW ? "legacy " : "", 450 config->mps != MLX5_MPW_DISABLED ? "enabled" : "disabled"); 451 if (config->cqe_comp && !cqe_comp) { 452 DRV_LOG(WARNING, "Rx CQE compression isn't supported."); 453 config->cqe_comp = 0; 454 } 455 if (sh->devx) { 456 config->hca_attr = sh->cdev->config.hca_attr; 457 config->hw_csum = config->hca_attr.csum_cap; 458 DRV_LOG(DEBUG, "checksum offloading is %ssupported", 459 (config->hw_csum ? "" : "not ")); 460 config->hw_vlan_strip = config->hca_attr.vlan_cap; 461 DRV_LOG(DEBUG, "VLAN stripping is %ssupported", 462 (config->hw_vlan_strip ? "" : "not ")); 463 config->hw_fcs_strip = config->hca_attr.scatter_fcs; 464 } 465 if (sh->devx) { 466 uint32_t reg[MLX5_ST_SZ_DW(register_mtutc)]; 467 468 err = config->hca_attr.access_register_user ? 469 mlx5_devx_cmd_register_read 470 (sh->cdev->ctx, MLX5_REGISTER_ID_MTUTC, 0, 471 reg, MLX5_ST_SZ_DW(register_mtutc)) : ENOTSUP; 472 if (!err) { 473 uint32_t ts_mode; 474 475 /* MTUTC register is read successfully. */ 476 ts_mode = MLX5_GET(register_mtutc, reg, 477 time_stamp_mode); 478 if (ts_mode == MLX5_MTUTC_TIMESTAMP_MODE_REAL_TIME) 479 config->rt_timestamp = 1; 480 } else { 481 /* Kernel does not support register reading. */ 482 if (config->hca_attr.dev_freq_khz == 483 (NS_PER_S / MS_PER_S)) 484 config->rt_timestamp = 1; 485 } 486 } 487 if (config->mprq.enabled) { 488 DRV_LOG(WARNING, "Multi-Packet RQ isn't supported"); 489 config->mprq.enabled = 0; 490 } 491 if (config->max_dump_files_num == 0) 492 config->max_dump_files_num = 128; 493 eth_dev = rte_eth_dev_allocate(name); 494 if (eth_dev == NULL) { 495 DRV_LOG(ERR, "can not allocate rte ethdev"); 496 err = ENOMEM; 497 goto error; 498 } 499 if (priv->representor) { 500 eth_dev->data->dev_flags |= RTE_ETH_DEV_REPRESENTOR; 501 eth_dev->data->representor_id = priv->representor_id; 502 MLX5_ETH_FOREACH_DEV(port_id, dpdk_dev) { 503 struct mlx5_priv *opriv = 504 rte_eth_devices[port_id].data->dev_private; 505 if (opriv && 506 opriv->master && 507 opriv->domain_id == priv->domain_id && 508 opriv->sh == priv->sh) { 509 eth_dev->data->backer_port_id = port_id; 510 break; 511 } 512 } 513 if (port_id >= RTE_MAX_ETHPORTS) 514 eth_dev->data->backer_port_id = eth_dev->data->port_id; 515 } 516 /* 517 * Store associated network device interface index. This index 518 * is permanent throughout the lifetime of device. So, we may store 519 * the ifindex here and use the cached value further. 520 */ 521 MLX5_ASSERT(spawn->ifindex); 522 priv->if_index = spawn->ifindex; 523 eth_dev->data->dev_private = priv; 524 priv->dev_data = eth_dev->data; 525 eth_dev->data->mac_addrs = priv->mac; 526 eth_dev->device = dpdk_dev; 527 eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS; 528 /* Configure the first MAC address by default. */ 529 if (mlx5_get_mac(eth_dev, &mac.addr_bytes)) { 530 DRV_LOG(ERR, 531 "port %u cannot get MAC address, is mlx5_en" 532 " loaded? (errno: %s).", 533 eth_dev->data->port_id, strerror(rte_errno)); 534 err = ENODEV; 535 goto error; 536 } 537 DRV_LOG(INFO, 538 "port %u MAC address is " RTE_ETHER_ADDR_PRT_FMT, 539 eth_dev->data->port_id, RTE_ETHER_ADDR_BYTES(&mac)); 540 #ifdef RTE_LIBRTE_MLX5_DEBUG 541 { 542 char ifname[MLX5_NAMESIZE]; 543 544 if (mlx5_get_ifname(eth_dev, &ifname) == 0) 545 DRV_LOG(DEBUG, "port %u ifname is \"%s\"", 546 eth_dev->data->port_id, ifname); 547 else 548 DRV_LOG(DEBUG, "port %u ifname is unknown.", 549 eth_dev->data->port_id); 550 } 551 #endif 552 /* Get actual MTU if possible. */ 553 err = mlx5_get_mtu(eth_dev, &priv->mtu); 554 if (err) { 555 err = rte_errno; 556 goto error; 557 } 558 DRV_LOG(DEBUG, "port %u MTU is %u.", eth_dev->data->port_id, 559 priv->mtu); 560 /* Initialize burst functions to prevent crashes before link-up. */ 561 eth_dev->rx_pkt_burst = removed_rx_burst; 562 eth_dev->tx_pkt_burst = removed_tx_burst; 563 eth_dev->dev_ops = &mlx5_dev_ops; 564 eth_dev->rx_descriptor_status = mlx5_rx_descriptor_status; 565 eth_dev->tx_descriptor_status = mlx5_tx_descriptor_status; 566 eth_dev->rx_queue_count = mlx5_rx_queue_count; 567 /* Register MAC address. */ 568 claim_zero(mlx5_mac_addr_add(eth_dev, &mac, 0, 0)); 569 priv->ctrl_flows = 0; 570 TAILQ_INIT(&priv->flow_meters); 571 priv->mtr_profile_tbl = mlx5_l3t_create(MLX5_L3T_TYPE_PTR); 572 if (!priv->mtr_profile_tbl) 573 goto error; 574 /* Bring Ethernet device up. */ 575 DRV_LOG(DEBUG, "port %u forcing Ethernet interface up.", 576 eth_dev->data->port_id); 577 /* nl calls are unsupported - set to -1 not to fail on release */ 578 priv->nl_socket_rdma = -1; 579 priv->nl_socket_route = -1; 580 mlx5_set_link_up(eth_dev); 581 /* 582 * Even though the interrupt handler is not installed yet, 583 * interrupts will still trigger on the async_fd from 584 * Verbs context returned by ibv_open_device(). 585 */ 586 mlx5_link_update(eth_dev, 0); 587 config->dv_esw_en = 0; 588 /* Detect minimal data bytes to inline. */ 589 mlx5_set_min_inline(spawn, config); 590 /* Store device configuration on private structure. */ 591 priv->config = *config; 592 for (i = 0; i < MLX5_FLOW_TYPE_MAXI; i++) { 593 icfg[i].release_mem_en = !!config->reclaim_mode; 594 if (config->reclaim_mode) 595 icfg[i].per_core_cache = 0; 596 priv->flows[i] = mlx5_ipool_create(&icfg[i]); 597 if (!priv->flows[i]) 598 goto error; 599 } 600 /* Create context for virtual machine VLAN workaround. */ 601 priv->vmwa_context = NULL; 602 if (config->dv_flow_en) { 603 err = mlx5_alloc_shared_dr(priv); 604 if (err) 605 goto error; 606 } 607 /* No supported flow priority number detection. */ 608 priv->config.flow_prio = -1; 609 if (!priv->config.dv_esw_en && 610 priv->config.dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) { 611 DRV_LOG(WARNING, "metadata mode %u is not supported " 612 "(no E-Switch)", priv->config.dv_xmeta_en); 613 priv->config.dv_xmeta_en = MLX5_XMETA_MODE_LEGACY; 614 } 615 mlx5_set_metadata_mask(eth_dev); 616 if (priv->config.dv_xmeta_en != MLX5_XMETA_MODE_LEGACY && 617 !priv->sh->dv_regc0_mask) { 618 DRV_LOG(ERR, "metadata mode %u is not supported " 619 "(no metadata reg_c[0] is available).", 620 priv->config.dv_xmeta_en); 621 err = ENOTSUP; 622 goto error; 623 } 624 priv->hrxqs = mlx5_list_create("hrxq", eth_dev, true, 625 mlx5_hrxq_create_cb, mlx5_hrxq_match_cb, 626 mlx5_hrxq_remove_cb, mlx5_hrxq_clone_cb, 627 mlx5_hrxq_clone_free_cb); 628 /* Query availability of metadata reg_c's. */ 629 err = mlx5_flow_discover_mreg_c(eth_dev); 630 if (err < 0) { 631 err = -err; 632 goto error; 633 } 634 if (!mlx5_flow_ext_mreg_supported(eth_dev)) { 635 DRV_LOG(DEBUG, 636 "port %u extensive metadata register is not supported.", 637 eth_dev->data->port_id); 638 if (priv->config.dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) { 639 DRV_LOG(ERR, "metadata mode %u is not supported " 640 "(no metadata registers available).", 641 priv->config.dv_xmeta_en); 642 err = ENOTSUP; 643 goto error; 644 } 645 } 646 if (sh->devx && config->dv_flow_en) { 647 priv->obj_ops = devx_obj_ops; 648 } else { 649 DRV_LOG(ERR, "Flow mode %u is not supported " 650 "(Windows flow must be DevX with DV flow enabled).", 651 priv->config.dv_flow_en); 652 err = ENOTSUP; 653 goto error; 654 } 655 mlx5_flow_counter_mode_config(eth_dev); 656 return eth_dev; 657 error: 658 if (priv) { 659 if (priv->mtr_profile_tbl) 660 mlx5_l3t_destroy(priv->mtr_profile_tbl); 661 if (own_domain_id) 662 claim_zero(rte_eth_switch_domain_free(priv->domain_id)); 663 mlx5_free(priv); 664 if (eth_dev != NULL) 665 eth_dev->data->dev_private = NULL; 666 } 667 if (eth_dev != NULL) { 668 /* mac_addrs must not be freed alone because part of 669 * dev_private 670 **/ 671 eth_dev->data->mac_addrs = NULL; 672 rte_eth_dev_release_port(eth_dev); 673 } 674 if (sh) 675 mlx5_free_shared_dev_ctx(sh); 676 MLX5_ASSERT(err > 0); 677 rte_errno = err; 678 return NULL; 679 } 680 681 /** 682 * This function should share events between multiple ports of single IB 683 * device. Currently it has no support under Windows. 684 * 685 * @param sh 686 * Pointer to mlx5_dev_ctx_shared object. 687 */ 688 void 689 mlx5_os_dev_shared_handler_install(struct mlx5_dev_ctx_shared *sh) 690 { 691 (void)sh; 692 DRV_LOG(WARNING, "%s: is not supported", __func__); 693 } 694 695 /** 696 * This function should share events between multiple ports of single IB 697 * device. Currently it has no support under Windows. 698 * 699 * @param dev 700 * Pointer to mlx5_dev_ctx_shared object. 701 */ 702 void 703 mlx5_os_dev_shared_handler_uninstall(struct mlx5_dev_ctx_shared *sh) 704 { 705 (void)sh; 706 DRV_LOG(WARNING, "%s: is not supported", __func__); 707 } 708 709 /** 710 * Read statistics by a named counter. 711 * 712 * @param[in] priv 713 * Pointer to the private device data structure. 714 * @param[in] ctr_name 715 * Pointer to the name of the statistic counter to read 716 * @param[out] stat 717 * Pointer to read statistic value. 718 * @return 719 * 0 on success and stat is valud, 1 if failed to read the value 720 * rte_errno is set. 721 * 722 */ 723 int 724 mlx5_os_read_dev_stat(struct mlx5_priv *priv, const char *ctr_name, 725 uint64_t *stat) 726 { 727 RTE_SET_USED(priv); 728 RTE_SET_USED(ctr_name); 729 RTE_SET_USED(stat); 730 DRV_LOG(WARNING, "%s: is not supported", __func__); 731 return -ENOTSUP; 732 } 733 734 /** 735 * Flush device MAC addresses 736 * Currently it has no support under Windows. 737 * 738 * @param dev 739 * Pointer to Ethernet device structure. 740 * 741 */ 742 void 743 mlx5_os_mac_addr_flush(struct rte_eth_dev *dev) 744 { 745 (void)dev; 746 DRV_LOG(WARNING, "%s: is not supported", __func__); 747 } 748 749 /** 750 * Remove a MAC address from device 751 * Currently it has no support under Windows. 752 * 753 * @param dev 754 * Pointer to Ethernet device structure. 755 * @param index 756 * MAC address index. 757 */ 758 void 759 mlx5_os_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) 760 { 761 (void)dev; 762 (void)(index); 763 DRV_LOG(WARNING, "%s: is not supported", __func__); 764 } 765 766 /** 767 * Adds a MAC address to the device 768 * Currently it has no support under Windows. 769 * 770 * @param dev 771 * Pointer to Ethernet device structure. 772 * @param mac_addr 773 * MAC address to register. 774 * @param index 775 * MAC address index. 776 * 777 * @return 778 * 0 on success, a negative errno value otherwise 779 */ 780 int 781 mlx5_os_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac, 782 uint32_t index) 783 { 784 (void)index; 785 struct rte_ether_addr lmac; 786 787 if (mlx5_get_mac(dev, &lmac.addr_bytes)) { 788 DRV_LOG(ERR, 789 "port %u cannot get MAC address, is mlx5_en" 790 " loaded? (errno: %s)", 791 dev->data->port_id, strerror(rte_errno)); 792 return rte_errno; 793 } 794 if (!rte_is_same_ether_addr(&lmac, mac)) { 795 DRV_LOG(ERR, 796 "adding new mac address to device is unsupported"); 797 return -ENOTSUP; 798 } 799 return 0; 800 } 801 802 /** 803 * Modify a VF MAC address 804 * Currently it has no support under Windows. 805 * 806 * @param priv 807 * Pointer to device private data. 808 * @param mac_addr 809 * MAC address to modify into. 810 * @param iface_idx 811 * Net device interface index 812 * @param vf_index 813 * VF index 814 * 815 * @return 816 * 0 on success, a negative errno value otherwise 817 */ 818 int 819 mlx5_os_vf_mac_addr_modify(struct mlx5_priv *priv, 820 unsigned int iface_idx, 821 struct rte_ether_addr *mac_addr, 822 int vf_index) 823 { 824 (void)priv; 825 (void)iface_idx; 826 (void)mac_addr; 827 (void)vf_index; 828 DRV_LOG(WARNING, "%s: is not supported", __func__); 829 return -ENOTSUP; 830 } 831 832 /** 833 * Set device promiscuous mode 834 * Currently it has no support under Windows. 835 * 836 * @param dev 837 * Pointer to Ethernet device structure. 838 * @param enable 839 * 0 - promiscuous is disabled, otherwise - enabled 840 * 841 * @return 842 * 0 on success, a negative error value otherwise 843 */ 844 int 845 mlx5_os_set_promisc(struct rte_eth_dev *dev, int enable) 846 { 847 (void)dev; 848 (void)enable; 849 DRV_LOG(WARNING, "%s: is not supported", __func__); 850 return -ENOTSUP; 851 } 852 853 /** 854 * Set device allmulti mode 855 * 856 * @param dev 857 * Pointer to Ethernet device structure. 858 * @param enable 859 * 0 - all multicase is disabled, otherwise - enabled 860 * 861 * @return 862 * 0 on success, a negative error value otherwise 863 */ 864 int 865 mlx5_os_set_allmulti(struct rte_eth_dev *dev, int enable) 866 { 867 (void)dev; 868 (void)enable; 869 DRV_LOG(WARNING, "%s: is not supported", __func__); 870 return -ENOTSUP; 871 } 872 873 /** 874 * DPDK callback to register a PCI device. 875 * 876 * This function spawns Ethernet devices out of a given device. 877 * 878 * @param[in] dev 879 * Pointer to the common device. 880 * 881 * @return 882 * 0 on success, a negative errno value otherwise and rte_errno is set. 883 */ 884 int 885 mlx5_os_net_probe(struct mlx5_common_device *cdev) 886 { 887 struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(cdev->dev); 888 struct mlx5_dev_spawn_data spawn = { 889 .pf_bond = -1, 890 .max_port = 1, 891 .phys_port = 1, 892 .phys_dev_name = mlx5_os_get_ctx_device_name(cdev->ctx), 893 .pci_dev = pci_dev, 894 .cdev = cdev, 895 .ifindex = -1, /* Spawn will assign */ 896 .info = (struct mlx5_switch_info){ 897 .name_type = MLX5_PHYS_PORT_NAME_TYPE_UPLINK, 898 }, 899 }; 900 struct mlx5_dev_config dev_config = { 901 .rx_vec_en = 1, 902 .txq_inline_max = MLX5_ARG_UNSET, 903 .txq_inline_min = MLX5_ARG_UNSET, 904 .txq_inline_mpw = MLX5_ARG_UNSET, 905 .txqs_inline = MLX5_ARG_UNSET, 906 .mprq = { 907 .max_memcpy_len = MLX5_MPRQ_MEMCPY_DEFAULT_LEN, 908 .min_rxqs_num = MLX5_MPRQ_MIN_RXQS, 909 }, 910 .dv_flow_en = 1, 911 .log_hp_size = MLX5_ARG_UNSET, 912 }; 913 int ret; 914 uint32_t restore; 915 916 if (rte_eal_process_type() == RTE_PROC_SECONDARY) { 917 DRV_LOG(ERR, "Secondary process is not supported on Windows."); 918 return -ENOTSUP; 919 } 920 ret = mlx5_init_once(); 921 if (ret) { 922 DRV_LOG(ERR, "unable to init PMD global data: %s", 923 strerror(rte_errno)); 924 return -rte_errno; 925 } 926 /* Device specific configuration. */ 927 switch (pci_dev->id.device_id) { 928 case PCI_DEVICE_ID_MELLANOX_CONNECTX4VF: 929 case PCI_DEVICE_ID_MELLANOX_CONNECTX4LXVF: 930 case PCI_DEVICE_ID_MELLANOX_CONNECTX5VF: 931 case PCI_DEVICE_ID_MELLANOX_CONNECTX5EXVF: 932 case PCI_DEVICE_ID_MELLANOX_CONNECTX5BFVF: 933 case PCI_DEVICE_ID_MELLANOX_CONNECTX6VF: 934 case PCI_DEVICE_ID_MELLANOX_CONNECTXVF: 935 dev_config.vf = 1; 936 break; 937 default: 938 dev_config.vf = 0; 939 break; 940 } 941 spawn.eth_dev = mlx5_dev_spawn(cdev->dev, &spawn, &dev_config); 942 if (!spawn.eth_dev) 943 return -rte_errno; 944 restore = spawn.eth_dev->data->dev_flags; 945 rte_eth_copy_pci_info(spawn.eth_dev, pci_dev); 946 /* Restore non-PCI flags cleared by the above call. */ 947 spawn.eth_dev->data->dev_flags |= restore; 948 rte_eth_dev_probing_finish(spawn.eth_dev); 949 return 0; 950 } 951 952 /** 953 * Cleanup resources when the last device is closed. 954 */ 955 void 956 mlx5_os_net_cleanup(void) 957 { 958 } 959 960 const struct mlx5_flow_driver_ops mlx5_flow_verbs_drv_ops = {0}; 961