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 const struct mlx5_indexed_pool_config default_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 static void 76 mlx5_queue_counter_id_prepare(struct rte_eth_dev *dev) 77 { 78 struct mlx5_priv *priv = dev->data->dev_private; 79 void *ctx = priv->sh->cdev->ctx; 80 81 priv->q_counters = mlx5_devx_cmd_queue_counter_alloc(ctx); 82 if (!priv->q_counters) { 83 DRV_LOG(ERR, "Port %d queue counter object cannot be created " 84 "by DevX - imissed counter will be unavailable", 85 dev->data->port_id); 86 priv->q_counters_allocation_failure = 1; 87 return; 88 } 89 priv->counter_set_id = priv->q_counters->id; 90 } 91 92 /** 93 * Initialize shared data between primary and secondary process. 94 * 95 * A memzone is reserved by primary process and secondary processes attach to 96 * the memzone. 97 * 98 * @return 99 * 0 on success, a negative errno value otherwise and rte_errno is set. 100 */ 101 static int 102 mlx5_init_shared_data(void) 103 { 104 const struct rte_memzone *mz; 105 int ret = 0; 106 107 rte_spinlock_lock(&mlx5_shared_data_lock); 108 if (mlx5_shared_data == NULL) { 109 /* Allocate shared memory. */ 110 mz = rte_memzone_reserve(MZ_MLX5_PMD_SHARED_DATA, 111 sizeof(*mlx5_shared_data), 112 SOCKET_ID_ANY, 0); 113 if (mz == NULL) { 114 DRV_LOG(ERR, 115 "Cannot allocate mlx5 shared data"); 116 ret = -rte_errno; 117 goto error; 118 } 119 mlx5_shared_data = mz->addr; 120 memset(mlx5_shared_data, 0, sizeof(*mlx5_shared_data)); 121 rte_spinlock_init(&mlx5_shared_data->lock); 122 } 123 error: 124 rte_spinlock_unlock(&mlx5_shared_data_lock); 125 return ret; 126 } 127 128 /** 129 * PMD global initialization. 130 * 131 * Independent from individual device, this function initializes global 132 * per-PMD data structures distinguishing primary and secondary processes. 133 * Hence, each initialization is called once per a process. 134 * 135 * @return 136 * 0 on success, a negative errno value otherwise and rte_errno is set. 137 */ 138 static int 139 mlx5_init_once(void) 140 { 141 if (mlx5_init_shared_data()) 142 return -rte_errno; 143 return 0; 144 } 145 146 /** 147 * Get mlx5 device capabilities. 148 * 149 * @param sh 150 * Pointer to shared device context. 151 * 152 * @return 153 * 0 on success, a negative errno value otherwise and rte_errno is set. 154 */ 155 int 156 mlx5_os_capabilities_prepare(struct mlx5_dev_ctx_shared *sh) 157 { 158 struct mlx5_hca_attr *hca_attr = &sh->cdev->config.hca_attr; 159 struct mlx5_context *mlx5_ctx = sh->cdev->ctx; 160 void *pv_iseg = NULL; 161 u32 cb_iseg = 0; 162 163 MLX5_ASSERT(sh->cdev->config.devx); 164 MLX5_ASSERT(mlx5_dev_is_pci(sh->cdev->dev)); 165 pv_iseg = mlx5_glue->query_hca_iseg(mlx5_ctx, &cb_iseg); 166 if (pv_iseg == NULL) { 167 DRV_LOG(ERR, "Failed to get device hca_iseg."); 168 rte_errno = errno; 169 return -rte_errno; 170 } 171 memset(&sh->dev_cap, 0, sizeof(struct mlx5_dev_cap)); 172 sh->dev_cap.vf = mlx5_dev_is_vf_pci(RTE_DEV_TO_PCI(sh->cdev->dev)); 173 sh->dev_cap.max_cq = 1 << hca_attr->log_max_cq; 174 sh->dev_cap.max_qp = 1 << hca_attr->log_max_qp; 175 sh->dev_cap.max_qp_wr = 1 << hca_attr->log_max_qp_sz; 176 sh->dev_cap.dv_flow_en = 1; 177 DRV_LOG(DEBUG, "MPW isn't supported."); 178 DRV_LOG(DEBUG, "MPLS over GRE/UDP tunnel offloading is no supported."); 179 sh->dev_cap.hw_csum = hca_attr->csum_cap; 180 DRV_LOG(DEBUG, "Checksum offloading is %ssupported.", 181 (sh->dev_cap.hw_csum ? "" : "not ")); 182 sh->dev_cap.hw_vlan_strip = hca_attr->vlan_cap; 183 DRV_LOG(DEBUG, "VLAN stripping is %ssupported.", 184 (sh->dev_cap.hw_vlan_strip ? "" : "not ")); 185 sh->dev_cap.hw_fcs_strip = hca_attr->scatter_fcs; 186 sh->dev_cap.tso = ((1 << hca_attr->max_lso_cap) > 0); 187 if (sh->dev_cap.tso) 188 sh->dev_cap.tso_max_payload_sz = 1 << hca_attr->max_lso_cap; 189 DRV_LOG(DEBUG, "Counters are not supported."); 190 if (hca_attr->striding_rq) { 191 sh->dev_cap.mprq.enabled = 1; 192 sh->dev_cap.mprq.log_min_stride_size = 193 MLX5_MIN_SINGLE_STRIDE_LOG_NUM_BYTES; 194 sh->dev_cap.mprq.log_max_stride_size = 195 MLX5_MAX_SINGLE_STRIDE_LOG_NUM_BYTES; 196 if (hca_attr->ext_stride_num_range) 197 sh->dev_cap.mprq.log_min_stride_num = 198 MLX5_EXT_MIN_SINGLE_WQE_LOG_NUM_STRIDES; 199 else 200 sh->dev_cap.mprq.log_min_stride_num = 201 MLX5_MIN_SINGLE_WQE_LOG_NUM_STRIDES; 202 sh->dev_cap.mprq.log_max_stride_num = 203 MLX5_MAX_SINGLE_WQE_LOG_NUM_STRIDES; 204 DRV_LOG(DEBUG, "\tmin_single_stride_log_num_of_bytes: %u", 205 sh->dev_cap.mprq.log_min_stride_size); 206 DRV_LOG(DEBUG, "\tmax_single_stride_log_num_of_bytes: %u", 207 sh->dev_cap.mprq.log_max_stride_size); 208 DRV_LOG(DEBUG, "\tmin_single_wqe_log_num_of_strides: %u", 209 sh->dev_cap.mprq.log_min_stride_num); 210 DRV_LOG(DEBUG, "\tmax_single_wqe_log_num_of_strides: %u", 211 sh->dev_cap.mprq.log_max_stride_num); 212 DRV_LOG(DEBUG, "\tmin_stride_wqe_log_size: %u", 213 sh->dev_cap.mprq.log_min_stride_wqe_size); 214 DRV_LOG(DEBUG, "Device supports Multi-Packet RQ."); 215 } 216 if (hca_attr->rss_ind_tbl_cap) { 217 /* 218 * DPDK doesn't support larger/variable indirection tables. 219 * Once DPDK supports it, take max size from device attr. 220 */ 221 sh->dev_cap.ind_table_max_size = 222 RTE_MIN((uint32_t)1 << hca_attr->rss_ind_tbl_cap, 223 (uint32_t)RTE_ETH_RSS_RETA_SIZE_512); 224 DRV_LOG(DEBUG, "Maximum Rx indirection table size is %u", 225 sh->dev_cap.ind_table_max_size); 226 } 227 if (hca_attr->enhanced_multi_pkt_send_wqe) 228 sh->dev_cap.mps = MLX5_MPW_ENHANCED; 229 else if (hca_attr->multi_pkt_send_wqe && 230 sh->dev_cap.mps != MLX5_ARG_UNSET) 231 sh->dev_cap.mps = MLX5_MPW; 232 else 233 sh->dev_cap.mps = MLX5_MPW_DISABLED; 234 sh->dev_cap.swp = mlx5_get_supported_sw_parsing_offloads(hca_attr); 235 sh->dev_cap.tunnel_en = mlx5_get_supported_tunneling_offloads(hca_attr); 236 if (sh->dev_cap.tunnel_en) { 237 DRV_LOG(DEBUG, "Tunnel offloading is supported for %s%s%s", 238 sh->dev_cap.tunnel_en & 239 MLX5_TUNNELED_OFFLOADS_VXLAN_CAP ? "[VXLAN]" : "", 240 sh->dev_cap.tunnel_en & 241 MLX5_TUNNELED_OFFLOADS_GRE_CAP ? "[GRE]" : "", 242 sh->dev_cap.tunnel_en & 243 MLX5_TUNNELED_OFFLOADS_GENEVE_CAP ? "[GENEVE]" : ""); 244 } else { 245 DRV_LOG(DEBUG, "Tunnel offloading is not supported."); 246 } 247 sh->dev_cap.cqe_comp = 0; 248 #if (RTE_CACHE_LINE_SIZE == 128) 249 if (hca_attr->cqe_compression_128) 250 sh->dev_cap.cqe_comp = 1; 251 DRV_LOG(DEBUG, "Rx CQE 128B compression is %ssupported.", 252 sh->dev_cap.cqe_comp ? "" : "not "); 253 #else 254 if (hca_attr->cqe_compression) 255 sh->dev_cap.cqe_comp = 1; 256 DRV_LOG(DEBUG, "Rx CQE compression is %ssupported.", 257 sh->dev_cap.cqe_comp ? "" : "not "); 258 #endif 259 snprintf(sh->dev_cap.fw_ver, 64, "%x.%x.%04x", 260 MLX5_GET(initial_seg, pv_iseg, fw_rev_major), 261 MLX5_GET(initial_seg, pv_iseg, fw_rev_minor), 262 MLX5_GET(initial_seg, pv_iseg, fw_rev_subminor)); 263 DRV_LOG(DEBUG, "Packet pacing is not supported."); 264 mlx5_rt_timestamp_config(sh, hca_attr); 265 return 0; 266 } 267 268 /** 269 * Initialize DR related data within private structure. 270 * Routine checks the reference counter and does actual 271 * resources creation/initialization only if counter is zero. 272 * 273 * @param[in] priv 274 * Pointer to the private device data structure. 275 * 276 * @return 277 * Zero on success, positive error code otherwise. 278 */ 279 static int 280 mlx5_alloc_shared_dr(struct mlx5_priv *priv) 281 { 282 struct mlx5_dev_ctx_shared *sh = priv->sh; 283 int err = 0; 284 285 if (!sh->flow_tbls) 286 err = mlx5_alloc_table_hash_list(priv); 287 else 288 DRV_LOG(DEBUG, "sh->flow_tbls[%p] already created, reuse", 289 (void *)sh->flow_tbls); 290 return err; 291 } 292 /** 293 * Destroy DR related data within private structure. 294 * 295 * @param[in] priv 296 * Pointer to the private device data structure. 297 */ 298 void 299 mlx5_os_free_shared_dr(struct mlx5_priv *priv) 300 { 301 mlx5_free_table_hash_list(priv); 302 } 303 304 /** 305 * Set the completion channel file descriptor interrupt as non-blocking. 306 * Currently it has no support under Windows. 307 * 308 * @param[in] rxq_obj 309 * Pointer to RQ channel object, which includes the channel fd 310 * 311 * @param[out] fd 312 * The file descriptor (representing the interrupt) used in this channel. 313 * 314 * @return 315 * 0 on successfully setting the fd to non-blocking, non-zero otherwise. 316 */ 317 int 318 mlx5_os_set_nonblock_channel_fd(int fd) 319 { 320 (void)fd; 321 DRV_LOG(WARNING, "%s: is not supported", __func__); 322 return -ENOTSUP; 323 } 324 325 /** 326 * Spawn an Ethernet device from DevX information. 327 * 328 * @param dpdk_dev 329 * Backing DPDK device. 330 * @param spawn 331 * Verbs device parameters (name, port, switch_info) to spawn. 332 * @param mkvlist 333 * Pointer to mlx5 kvargs control, can be NULL if there is no devargs. 334 * 335 * @return 336 * A valid Ethernet device object on success, NULL otherwise and rte_errno 337 * is set. The following errors are defined: 338 * 339 * EEXIST: device is already spawned 340 */ 341 static struct rte_eth_dev * 342 mlx5_dev_spawn(struct rte_device *dpdk_dev, 343 struct mlx5_dev_spawn_data *spawn, 344 struct mlx5_kvargs_ctrl *mkvlist) 345 { 346 const struct mlx5_switch_info *switch_info = &spawn->info; 347 struct mlx5_dev_ctx_shared *sh = NULL; 348 struct rte_eth_dev *eth_dev = NULL; 349 struct mlx5_priv *priv = NULL; 350 int err = 0; 351 struct rte_ether_addr mac; 352 char name[RTE_ETH_NAME_MAX_LEN]; 353 int own_domain_id = 0; 354 uint16_t port_id; 355 int i; 356 struct mlx5_indexed_pool_config icfg[RTE_DIM(default_icfg)]; 357 358 memcpy(icfg, default_icfg, sizeof(icfg)); 359 /* Build device name. */ 360 strlcpy(name, dpdk_dev->name, sizeof(name)); 361 /* check if the device is already spawned */ 362 if (rte_eth_dev_get_port_by_name(name, &port_id) == 0) { 363 rte_errno = EEXIST; 364 return NULL; 365 } 366 DRV_LOG(DEBUG, "naming Ethernet device \"%s\"", name); 367 sh = mlx5_alloc_shared_dev_ctx(spawn, mkvlist); 368 if (!sh) 369 return NULL; 370 if (!sh->config.dv_flow_en) { 371 DRV_LOG(ERR, "Windows flow mode must be DV flow enable."); 372 err = ENOTSUP; 373 goto error; 374 } 375 if (sh->config.vf_nl_en) { 376 DRV_LOG(DEBUG, "VF netlink isn't supported."); 377 sh->config.vf_nl_en = 0; 378 } 379 /* Initialize the shutdown event in mlx5_dev_spawn to 380 * support mlx5_is_removed for Windows. 381 */ 382 err = mlx5_glue->devx_init_showdown_event(sh->cdev->ctx); 383 if (err) { 384 DRV_LOG(ERR, "failed to init showdown event: %s", 385 strerror(errno)); 386 goto error; 387 } 388 /* Allocate private eth device data. */ 389 priv = mlx5_malloc(MLX5_MEM_ZERO | MLX5_MEM_RTE, 390 sizeof(*priv), 391 RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY); 392 if (priv == NULL) { 393 DRV_LOG(ERR, "priv allocation failure"); 394 err = ENOMEM; 395 goto error; 396 } 397 priv->sh = sh; 398 priv->dev_port = spawn->phys_port; 399 priv->pci_dev = spawn->pci_dev; 400 priv->mtu = RTE_ETHER_MTU; 401 priv->mp_id.port_id = port_id; 402 strlcpy(priv->mp_id.name, MLX5_MP_NAME, RTE_MP_MAX_NAME_LEN); 403 priv->representor = !!switch_info->representor; 404 priv->master = !!switch_info->master; 405 priv->domain_id = RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID; 406 priv->vport_meta_tag = 0; 407 priv->vport_meta_mask = 0; 408 priv->pf_bond = spawn->pf_bond; 409 priv->vport_id = -1; 410 /* representor_id field keeps the unmodified VF index. */ 411 priv->representor_id = -1; 412 /* 413 * Look for sibling devices in order to reuse their switch domain 414 * if any, otherwise allocate one. 415 */ 416 MLX5_ETH_FOREACH_DEV(port_id, dpdk_dev) { 417 const struct mlx5_priv *opriv = 418 rte_eth_devices[port_id].data->dev_private; 419 420 if (!opriv || 421 opriv->sh != priv->sh || 422 opriv->domain_id == 423 RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID) 424 continue; 425 priv->domain_id = opriv->domain_id; 426 break; 427 } 428 if (priv->domain_id == RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID) { 429 err = rte_eth_switch_domain_alloc(&priv->domain_id); 430 if (err) { 431 err = rte_errno; 432 DRV_LOG(ERR, "unable to allocate switch domain: %s", 433 strerror(rte_errno)); 434 goto error; 435 } 436 own_domain_id = 1; 437 } 438 /* Process parameters and store port configuration on priv structure. */ 439 err = mlx5_port_args_config(priv, mkvlist, &priv->config); 440 if (err) { 441 err = rte_errno; 442 DRV_LOG(ERR, "Failed to process port configure: %s", 443 strerror(rte_errno)); 444 goto error; 445 } 446 eth_dev = rte_eth_dev_allocate(name); 447 if (eth_dev == NULL) { 448 DRV_LOG(ERR, "can not allocate rte ethdev"); 449 err = ENOMEM; 450 goto error; 451 } 452 if (priv->representor) { 453 eth_dev->data->dev_flags |= RTE_ETH_DEV_REPRESENTOR; 454 eth_dev->data->representor_id = priv->representor_id; 455 MLX5_ETH_FOREACH_DEV(port_id, dpdk_dev) { 456 struct mlx5_priv *opriv = 457 rte_eth_devices[port_id].data->dev_private; 458 if (opriv && 459 opriv->master && 460 opriv->domain_id == priv->domain_id && 461 opriv->sh == priv->sh) { 462 eth_dev->data->backer_port_id = port_id; 463 break; 464 } 465 } 466 if (port_id >= RTE_MAX_ETHPORTS) 467 eth_dev->data->backer_port_id = eth_dev->data->port_id; 468 } 469 /* 470 * Store associated network device interface index. This index 471 * is permanent throughout the lifetime of device. So, we may store 472 * the ifindex here and use the cached value further. 473 */ 474 MLX5_ASSERT(spawn->ifindex); 475 priv->if_index = spawn->ifindex; 476 eth_dev->data->dev_private = priv; 477 priv->dev_data = eth_dev->data; 478 eth_dev->data->mac_addrs = priv->mac; 479 eth_dev->device = dpdk_dev; 480 eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS; 481 /* Configure the first MAC address by default. */ 482 if (mlx5_get_mac(eth_dev, &mac.addr_bytes)) { 483 DRV_LOG(ERR, 484 "port %u cannot get MAC address, is mlx5_en" 485 " loaded? (errno: %s).", 486 eth_dev->data->port_id, strerror(rte_errno)); 487 err = ENODEV; 488 goto error; 489 } 490 DRV_LOG(INFO, 491 "port %u MAC address is " RTE_ETHER_ADDR_PRT_FMT, 492 eth_dev->data->port_id, RTE_ETHER_ADDR_BYTES(&mac)); 493 #ifdef RTE_LIBRTE_MLX5_DEBUG 494 { 495 char ifname[MLX5_NAMESIZE]; 496 497 if (mlx5_get_ifname(eth_dev, &ifname) == 0) 498 DRV_LOG(DEBUG, "port %u ifname is \"%s\"", 499 eth_dev->data->port_id, ifname); 500 else 501 DRV_LOG(DEBUG, "port %u ifname is unknown.", 502 eth_dev->data->port_id); 503 } 504 #endif 505 /* Get actual MTU if possible. */ 506 err = mlx5_get_mtu(eth_dev, &priv->mtu); 507 if (err) { 508 err = rte_errno; 509 goto error; 510 } 511 DRV_LOG(DEBUG, "port %u MTU is %u.", eth_dev->data->port_id, 512 priv->mtu); 513 /* Initialize burst functions to prevent crashes before link-up. */ 514 eth_dev->rx_pkt_burst = rte_eth_pkt_burst_dummy; 515 eth_dev->tx_pkt_burst = rte_eth_pkt_burst_dummy; 516 eth_dev->dev_ops = &mlx5_dev_ops; 517 eth_dev->rx_descriptor_status = mlx5_rx_descriptor_status; 518 eth_dev->tx_descriptor_status = mlx5_tx_descriptor_status; 519 eth_dev->rx_queue_count = mlx5_rx_queue_count; 520 /* Register MAC address. */ 521 claim_zero(mlx5_mac_addr_add(eth_dev, &mac, 0, 0)); 522 priv->ctrl_flows = 0; 523 TAILQ_INIT(&priv->flow_meters); 524 if (priv->mtr_en) { 525 priv->mtr_profile_tbl = mlx5_l3t_create(MLX5_L3T_TYPE_PTR); 526 if (!priv->mtr_profile_tbl) 527 goto error; 528 } 529 /* Bring Ethernet device up. */ 530 DRV_LOG(DEBUG, "port %u forcing Ethernet interface up.", 531 eth_dev->data->port_id); 532 /* nl calls are unsupported - set to -1 not to fail on release */ 533 priv->nl_socket_rdma = -1; 534 priv->nl_socket_route = -1; 535 mlx5_set_link_up(eth_dev); 536 /* 537 * Even though the interrupt handler is not installed yet, 538 * interrupts will still trigger on the async_fd from 539 * Verbs context returned by ibv_open_device(). 540 */ 541 mlx5_link_update(eth_dev, 0); 542 for (i = 0; i < MLX5_FLOW_TYPE_MAXI; i++) { 543 icfg[i].release_mem_en = !!sh->config.reclaim_mode; 544 if (sh->config.reclaim_mode) 545 icfg[i].per_core_cache = 0; 546 #ifdef HAVE_MLX5_HWS_SUPPORT 547 if (priv->sh->config.dv_flow_en == 2) 548 icfg[i].size = sizeof(struct rte_flow_hw) + sizeof(struct rte_flow_nt2hws); 549 #endif 550 priv->flows[i] = mlx5_ipool_create(&icfg[i]); 551 if (!priv->flows[i]) 552 goto error; 553 } 554 /* Create context for virtual machine VLAN workaround. */ 555 priv->vmwa_context = NULL; 556 if (sh->config.dv_flow_en) { 557 err = mlx5_alloc_shared_dr(priv); 558 if (err) 559 goto error; 560 } 561 /* No supported flow priority number detection. */ 562 priv->sh->flow_max_priority = -1; 563 mlx5_set_metadata_mask(eth_dev); 564 if (sh->config.dv_xmeta_en != MLX5_XMETA_MODE_LEGACY && 565 !priv->sh->dv_regc0_mask) { 566 DRV_LOG(ERR, "metadata mode %u is not supported " 567 "(no metadata reg_c[0] is available).", 568 sh->config.dv_xmeta_en); 569 err = ENOTSUP; 570 goto error; 571 } 572 priv->hrxqs = mlx5_list_create("hrxq", eth_dev, true, 573 mlx5_hrxq_create_cb, mlx5_hrxq_match_cb, 574 mlx5_hrxq_remove_cb, mlx5_hrxq_clone_cb, 575 mlx5_hrxq_clone_free_cb); 576 /* Query availability of metadata reg_c's. */ 577 if (!priv->sh->metadata_regc_check_flag) { 578 err = mlx5_flow_discover_mreg_c(eth_dev); 579 if (err < 0) { 580 err = -err; 581 goto error; 582 } 583 } 584 if (!mlx5_flow_ext_mreg_supported(eth_dev)) { 585 DRV_LOG(DEBUG, 586 "port %u extensive metadata register is not supported.", 587 eth_dev->data->port_id); 588 if (sh->config.dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) { 589 DRV_LOG(ERR, "metadata mode %u is not supported " 590 "(no metadata registers available).", 591 sh->config.dv_xmeta_en); 592 err = ENOTSUP; 593 goto error; 594 } 595 } 596 if (sh->cdev->config.devx) { 597 priv->obj_ops = devx_obj_ops; 598 } else { 599 DRV_LOG(ERR, "Windows flow must be DevX."); 600 err = ENOTSUP; 601 goto error; 602 } 603 mlx5_flow_counter_mode_config(eth_dev); 604 mlx5_queue_counter_id_prepare(eth_dev); 605 rte_spinlock_init(&priv->hw_ctrl_lock); 606 LIST_INIT(&priv->hw_ctrl_flows); 607 LIST_INIT(&priv->hw_ext_ctrl_flows); 608 return eth_dev; 609 error: 610 if (priv) { 611 if (priv->mtr_profile_tbl) 612 mlx5_l3t_destroy(priv->mtr_profile_tbl); 613 if (own_domain_id) 614 claim_zero(rte_eth_switch_domain_free(priv->domain_id)); 615 mlx5_free(priv); 616 if (eth_dev != NULL) 617 eth_dev->data->dev_private = NULL; 618 } 619 if (eth_dev != NULL) { 620 /* mac_addrs must not be freed alone because part of 621 * dev_private 622 **/ 623 eth_dev->data->mac_addrs = NULL; 624 rte_eth_dev_release_port(eth_dev); 625 } 626 if (sh) 627 mlx5_free_shared_dev_ctx(sh); 628 MLX5_ASSERT(err > 0); 629 rte_errno = err; 630 return NULL; 631 } 632 633 /** 634 * This function should share events between multiple ports of single IB 635 * device. Currently it has no support under Windows. 636 * 637 * @param sh 638 * Pointer to mlx5_dev_ctx_shared object. 639 */ 640 void 641 mlx5_os_dev_shared_handler_install(struct mlx5_dev_ctx_shared *sh) 642 { 643 (void)sh; 644 DRV_LOG(WARNING, "%s: is not supported", __func__); 645 } 646 647 /** 648 * This function should share events between multiple ports of single IB 649 * device. Currently it has no support under Windows. 650 * 651 * @param dev 652 * Pointer to mlx5_dev_ctx_shared object. 653 */ 654 void 655 mlx5_os_dev_shared_handler_uninstall(struct mlx5_dev_ctx_shared *sh) 656 { 657 (void)sh; 658 DRV_LOG(WARNING, "%s: is not supported", __func__); 659 } 660 661 /** 662 * Read statistics by a named counter. 663 * 664 * @param[in] priv 665 * Pointer to the private device data structure. 666 * @param[in] ctr_name 667 * Pointer to the name of the statistic counter to read 668 * @param[out] stat 669 * Pointer to read statistic value. 670 * @return 671 * 0 on success and stat is valid, non-zero if failed to read the value 672 * or counter is not supported. 673 * rte_errno is set. 674 * 675 */ 676 int 677 mlx5_os_read_dev_stat(struct mlx5_priv *priv, const char *ctr_name, 678 uint64_t *stat) 679 { 680 if (priv->q_counters != NULL && strcmp(ctr_name, "out_of_buffer") == 0) 681 return mlx5_devx_cmd_queue_counter_query 682 (priv->q_counters, 0, (uint32_t *)stat); 683 DRV_LOG(WARNING, "%s: is not supported for the %s counter", 684 __func__, ctr_name); 685 return -ENOTSUP; 686 } 687 688 /** 689 * Flush device MAC addresses 690 * Currently it has no support under Windows. 691 * 692 * @param dev 693 * Pointer to Ethernet device structure. 694 * 695 */ 696 void 697 mlx5_os_mac_addr_flush(struct rte_eth_dev *dev) 698 { 699 (void)dev; 700 DRV_LOG(WARNING, "%s: is not supported", __func__); 701 } 702 703 /** 704 * Remove a MAC address from device 705 * Currently it has no support under Windows. 706 * 707 * @param dev 708 * Pointer to Ethernet device structure. 709 * @param index 710 * MAC address index. 711 */ 712 void 713 mlx5_os_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) 714 { 715 (void)dev; 716 (void)(index); 717 DRV_LOG(WARNING, "%s: is not supported", __func__); 718 } 719 720 /** 721 * Adds a MAC address to the device 722 * Currently it has no support under Windows. 723 * 724 * @param dev 725 * Pointer to Ethernet device structure. 726 * @param mac_addr 727 * MAC address to register. 728 * @param index 729 * MAC address index. 730 * 731 * @return 732 * 0 on success, a negative errno value otherwise 733 */ 734 int 735 mlx5_os_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac, 736 uint32_t index) 737 { 738 (void)index; 739 struct rte_ether_addr lmac; 740 741 if (mlx5_get_mac(dev, &lmac.addr_bytes)) { 742 DRV_LOG(ERR, 743 "port %u cannot get MAC address, is mlx5_en" 744 " loaded? (errno: %s)", 745 dev->data->port_id, strerror(rte_errno)); 746 return rte_errno; 747 } 748 if (!rte_is_same_ether_addr(&lmac, mac)) { 749 DRV_LOG(ERR, 750 "adding new mac address to device is unsupported"); 751 return -ENOTSUP; 752 } 753 return 0; 754 } 755 756 /** 757 * Modify a VF MAC address 758 * Currently it has no support under Windows. 759 * 760 * @param priv 761 * Pointer to device private data. 762 * @param mac_addr 763 * MAC address to modify into. 764 * @param iface_idx 765 * Net device interface index 766 * @param vf_index 767 * VF index 768 * 769 * @return 770 * 0 on success, a negative errno value otherwise 771 */ 772 int 773 mlx5_os_vf_mac_addr_modify(struct mlx5_priv *priv, 774 unsigned int iface_idx, 775 struct rte_ether_addr *mac_addr, 776 int vf_index) 777 { 778 (void)priv; 779 (void)iface_idx; 780 (void)mac_addr; 781 (void)vf_index; 782 DRV_LOG(WARNING, "%s: is not supported", __func__); 783 return -ENOTSUP; 784 } 785 786 /** 787 * Set device promiscuous mode 788 * 789 * @param dev 790 * Pointer to Ethernet device structure. 791 * @param enable 792 * 0 - promiscuous is disabled, otherwise - enabled 793 * 794 * @return 795 * 0 on success, a negative error value otherwise 796 */ 797 int 798 mlx5_os_set_promisc(struct rte_eth_dev *dev, int enable) 799 { 800 struct mlx5_priv *priv = dev->data->dev_private; 801 802 return mlx5_glue->devx_set_promisc_vport(priv->sh->cdev->ctx, ALL_PROMISC, enable); 803 } 804 805 /** 806 * Set device allmulti mode 807 * 808 * @param dev 809 * Pointer to Ethernet device structure. 810 * @param enable 811 * 0 - all multicase is disabled, otherwise - enabled 812 * 813 * @return 814 * 0 on success, a negative error value otherwise 815 */ 816 int 817 mlx5_os_set_allmulti(struct rte_eth_dev *dev, int enable) 818 { 819 struct mlx5_priv *priv = dev->data->dev_private; 820 821 return mlx5_glue->devx_set_promisc_vport(priv->sh->cdev->ctx, MC_PROMISC, enable); 822 } 823 824 /** 825 * DPDK callback to register a PCI device. 826 * 827 * This function spawns Ethernet devices out of a given device. 828 * 829 * @param[in] cdev 830 * Pointer to the common device. 831 * @param[in, out] mkvlist 832 * Pointer to mlx5 kvargs control, can be NULL if there is no devargs. 833 * 834 * @return 835 * 0 on success, a negative errno value otherwise and rte_errno is set. 836 */ 837 int 838 mlx5_os_net_probe(struct mlx5_common_device *cdev, 839 struct mlx5_kvargs_ctrl *mkvlist) 840 { 841 struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(cdev->dev); 842 struct mlx5_dev_spawn_data spawn = { 843 .pf_bond = -1, 844 .max_port = 1, 845 .phys_port = 1, 846 .phys_dev_name = mlx5_os_get_ctx_device_name(cdev->ctx), 847 .pci_dev = pci_dev, 848 .cdev = cdev, 849 .ifindex = -1, /* Spawn will assign */ 850 .info = (struct mlx5_switch_info){ 851 .name_type = MLX5_PHYS_PORT_NAME_TYPE_UPLINK, 852 }, 853 }; 854 int ret; 855 uint32_t restore; 856 857 if (rte_eal_process_type() == RTE_PROC_SECONDARY) { 858 DRV_LOG(ERR, "Secondary process is not supported on Windows."); 859 return -ENOTSUP; 860 } 861 ret = mlx5_init_once(); 862 if (ret) { 863 DRV_LOG(ERR, "unable to init PMD global data: %s", 864 strerror(rte_errno)); 865 return -rte_errno; 866 } 867 spawn.eth_dev = mlx5_dev_spawn(cdev->dev, &spawn, mkvlist); 868 if (!spawn.eth_dev) 869 return -rte_errno; 870 restore = spawn.eth_dev->data->dev_flags; 871 rte_eth_copy_pci_info(spawn.eth_dev, pci_dev); 872 /* Restore non-PCI flags cleared by the above call. */ 873 spawn.eth_dev->data->dev_flags |= restore; 874 rte_eth_dev_probing_finish(spawn.eth_dev); 875 return 0; 876 } 877 878 /** 879 * Cleanup resources when the last device is closed. 880 */ 881 void 882 mlx5_os_net_cleanup(void) 883 { 884 } 885 886 const struct mlx5_flow_driver_ops mlx5_flow_verbs_drv_ops = {0}; 887