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 <errno.h> 8 #include <string.h> 9 #include <stdint.h> 10 #include <unistd.h> 11 #include <inttypes.h> 12 13 #include <rte_mbuf.h> 14 #include <rte_malloc.h> 15 #include <ethdev_driver.h> 16 #include <rte_bus_pci.h> 17 #include <rte_common.h> 18 #include <rte_eal_paging.h> 19 20 #include <mlx5_common.h> 21 #include <mlx5_common_mr.h> 22 #include <mlx5_malloc.h> 23 24 #include "mlx5_defs.h" 25 #include "mlx5_utils.h" 26 #include "mlx5.h" 27 #include "mlx5_tx.h" 28 #include "mlx5_rxtx.h" 29 #include "mlx5_autoconf.h" 30 31 /** 32 * Allocate TX queue elements. 33 * 34 * @param txq_ctrl 35 * Pointer to TX queue structure. 36 */ 37 void 38 txq_alloc_elts(struct mlx5_txq_ctrl *txq_ctrl) 39 { 40 const unsigned int elts_n = 1 << txq_ctrl->txq.elts_n; 41 unsigned int i; 42 43 for (i = 0; (i != elts_n); ++i) 44 txq_ctrl->txq.elts[i] = NULL; 45 DRV_LOG(DEBUG, "port %u Tx queue %u allocated and configured %u WRs", 46 PORT_ID(txq_ctrl->priv), txq_ctrl->txq.idx, elts_n); 47 txq_ctrl->txq.elts_head = 0; 48 txq_ctrl->txq.elts_tail = 0; 49 txq_ctrl->txq.elts_comp = 0; 50 } 51 52 /** 53 * Free TX queue elements. 54 * 55 * @param txq_ctrl 56 * Pointer to TX queue structure. 57 */ 58 void 59 txq_free_elts(struct mlx5_txq_ctrl *txq_ctrl) 60 { 61 const uint16_t elts_n = 1 << txq_ctrl->txq.elts_n; 62 const uint16_t elts_m = elts_n - 1; 63 uint16_t elts_head = txq_ctrl->txq.elts_head; 64 uint16_t elts_tail = txq_ctrl->txq.elts_tail; 65 struct rte_mbuf *(*elts)[elts_n] = &txq_ctrl->txq.elts; 66 67 DRV_LOG(DEBUG, "port %u Tx queue %u freeing WRs", 68 PORT_ID(txq_ctrl->priv), txq_ctrl->txq.idx); 69 txq_ctrl->txq.elts_head = 0; 70 txq_ctrl->txq.elts_tail = 0; 71 txq_ctrl->txq.elts_comp = 0; 72 73 while (elts_tail != elts_head) { 74 struct rte_mbuf *elt = (*elts)[elts_tail & elts_m]; 75 76 MLX5_ASSERT(elt != NULL); 77 rte_pktmbuf_free_seg(elt); 78 #ifdef RTE_LIBRTE_MLX5_DEBUG 79 /* Poisoning. */ 80 memset(&(*elts)[elts_tail & elts_m], 81 0x77, 82 sizeof((*elts)[elts_tail & elts_m])); 83 #endif 84 ++elts_tail; 85 } 86 } 87 88 /** 89 * Returns the per-port supported offloads. 90 * 91 * @param dev 92 * Pointer to Ethernet device. 93 * 94 * @return 95 * Supported Tx offloads. 96 */ 97 uint64_t 98 mlx5_get_tx_port_offloads(struct rte_eth_dev *dev) 99 { 100 struct mlx5_priv *priv = dev->data->dev_private; 101 uint64_t offloads = (DEV_TX_OFFLOAD_MULTI_SEGS | 102 DEV_TX_OFFLOAD_VLAN_INSERT); 103 struct mlx5_dev_config *config = &priv->config; 104 105 if (config->hw_csum) 106 offloads |= (DEV_TX_OFFLOAD_IPV4_CKSUM | 107 DEV_TX_OFFLOAD_UDP_CKSUM | 108 DEV_TX_OFFLOAD_TCP_CKSUM); 109 if (config->tso) 110 offloads |= DEV_TX_OFFLOAD_TCP_TSO; 111 if (config->tx_pp) 112 offloads |= DEV_TX_OFFLOAD_SEND_ON_TIMESTAMP; 113 if (config->swp) { 114 if (config->hw_csum) 115 offloads |= DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM; 116 if (config->tso) 117 offloads |= (DEV_TX_OFFLOAD_IP_TNL_TSO | 118 DEV_TX_OFFLOAD_UDP_TNL_TSO); 119 } 120 if (config->tunnel_en) { 121 if (config->hw_csum) 122 offloads |= DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM; 123 if (config->tso) 124 offloads |= (DEV_TX_OFFLOAD_VXLAN_TNL_TSO | 125 DEV_TX_OFFLOAD_GRE_TNL_TSO | 126 DEV_TX_OFFLOAD_GENEVE_TNL_TSO); 127 } 128 if (!config->mprq.enabled) 129 offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; 130 return offloads; 131 } 132 133 /* Fetches and drops all SW-owned and error CQEs to synchronize CQ. */ 134 static void 135 txq_sync_cq(struct mlx5_txq_data *txq) 136 { 137 volatile struct mlx5_cqe *cqe; 138 int ret, i; 139 140 i = txq->cqe_s; 141 do { 142 cqe = &txq->cqes[txq->cq_ci & txq->cqe_m]; 143 ret = check_cqe(cqe, txq->cqe_s, txq->cq_ci); 144 if (unlikely(ret != MLX5_CQE_STATUS_SW_OWN)) { 145 if (likely(ret != MLX5_CQE_STATUS_ERR)) { 146 /* No new CQEs in completion queue. */ 147 MLX5_ASSERT(ret == MLX5_CQE_STATUS_HW_OWN); 148 break; 149 } 150 } 151 ++txq->cq_ci; 152 } while (--i); 153 /* Move all CQEs to HW ownership. */ 154 for (i = 0; i < txq->cqe_s; i++) { 155 cqe = &txq->cqes[i]; 156 cqe->op_own = MLX5_CQE_INVALIDATE; 157 } 158 /* Resync CQE and WQE (WQ in reset state). */ 159 rte_io_wmb(); 160 *txq->cq_db = rte_cpu_to_be_32(txq->cq_ci); 161 txq->cq_pi = txq->cq_ci; 162 rte_io_wmb(); 163 } 164 165 /** 166 * Tx queue stop. Device queue goes to the idle state, 167 * all involved mbufs are freed from elts/WQ. 168 * 169 * @param dev 170 * Pointer to Ethernet device structure. 171 * @param idx 172 * Tx queue index. 173 * 174 * @return 175 * 0 on success, a negative errno value otherwise and rte_errno is set. 176 */ 177 int 178 mlx5_tx_queue_stop_primary(struct rte_eth_dev *dev, uint16_t idx) 179 { 180 struct mlx5_priv *priv = dev->data->dev_private; 181 struct mlx5_txq_data *txq = (*priv->txqs)[idx]; 182 struct mlx5_txq_ctrl *txq_ctrl = 183 container_of(txq, struct mlx5_txq_ctrl, txq); 184 int ret; 185 186 MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY); 187 /* Move QP to RESET state. */ 188 ret = priv->obj_ops.txq_obj_modify(txq_ctrl->obj, MLX5_TXQ_MOD_RDY2RST, 189 (uint8_t)priv->dev_port); 190 if (ret) 191 return ret; 192 /* Handle all send completions. */ 193 txq_sync_cq(txq); 194 /* Free elts stored in the SQ. */ 195 txq_free_elts(txq_ctrl); 196 /* Prevent writing new pkts to SQ by setting no free WQE.*/ 197 txq->wqe_ci = txq->wqe_s; 198 txq->wqe_pi = 0; 199 txq->elts_comp = 0; 200 /* Set the actual queue state. */ 201 dev->data->tx_queue_state[idx] = RTE_ETH_QUEUE_STATE_STOPPED; 202 return 0; 203 } 204 205 /** 206 * Tx queue stop. Device queue goes to the idle state, 207 * all involved mbufs are freed from elts/WQ. 208 * 209 * @param dev 210 * Pointer to Ethernet device structure. 211 * @param idx 212 * Tx queue index. 213 * 214 * @return 215 * 0 on success, a negative errno value otherwise and rte_errno is set. 216 */ 217 int 218 mlx5_tx_queue_stop(struct rte_eth_dev *dev, uint16_t idx) 219 { 220 int ret; 221 222 if (rte_eth_dev_is_tx_hairpin_queue(dev, idx)) { 223 DRV_LOG(ERR, "Hairpin queue can't be stopped"); 224 rte_errno = EINVAL; 225 return -EINVAL; 226 } 227 if (dev->data->tx_queue_state[idx] == RTE_ETH_QUEUE_STATE_STOPPED) 228 return 0; 229 if (rte_eal_process_type() == RTE_PROC_SECONDARY) { 230 ret = mlx5_mp_os_req_queue_control(dev, idx, 231 MLX5_MP_REQ_QUEUE_TX_STOP); 232 } else { 233 ret = mlx5_tx_queue_stop_primary(dev, idx); 234 } 235 return ret; 236 } 237 238 /** 239 * Rx queue start. Device queue goes to the ready state, 240 * all required mbufs are allocated and WQ is replenished. 241 * 242 * @param dev 243 * Pointer to Ethernet device structure. 244 * @param idx 245 * RX queue index. 246 * 247 * @return 248 * 0 on success, a negative errno value otherwise and rte_errno is set. 249 */ 250 int 251 mlx5_tx_queue_start_primary(struct rte_eth_dev *dev, uint16_t idx) 252 { 253 struct mlx5_priv *priv = dev->data->dev_private; 254 struct mlx5_txq_data *txq = (*priv->txqs)[idx]; 255 struct mlx5_txq_ctrl *txq_ctrl = 256 container_of(txq, struct mlx5_txq_ctrl, txq); 257 int ret; 258 259 MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY); 260 ret = priv->obj_ops.txq_obj_modify(txq_ctrl->obj, 261 MLX5_TXQ_MOD_RST2RDY, 262 (uint8_t)priv->dev_port); 263 if (ret) 264 return ret; 265 txq_ctrl->txq.wqe_ci = 0; 266 txq_ctrl->txq.wqe_pi = 0; 267 txq_ctrl->txq.elts_comp = 0; 268 /* Set the actual queue state. */ 269 dev->data->tx_queue_state[idx] = RTE_ETH_QUEUE_STATE_STARTED; 270 return 0; 271 } 272 273 /** 274 * Rx queue start. Device queue goes to the ready state, 275 * all required mbufs are allocated and WQ is replenished. 276 * 277 * @param dev 278 * Pointer to Ethernet device structure. 279 * @param idx 280 * RX queue index. 281 * 282 * @return 283 * 0 on success, a negative errno value otherwise and rte_errno is set. 284 */ 285 int 286 mlx5_tx_queue_start(struct rte_eth_dev *dev, uint16_t idx) 287 { 288 int ret; 289 290 if (rte_eth_dev_is_tx_hairpin_queue(dev, idx)) { 291 DRV_LOG(ERR, "Hairpin queue can't be started"); 292 rte_errno = EINVAL; 293 return -EINVAL; 294 } 295 if (dev->data->tx_queue_state[idx] == RTE_ETH_QUEUE_STATE_STARTED) 296 return 0; 297 if (rte_eal_process_type() == RTE_PROC_SECONDARY) { 298 ret = mlx5_mp_os_req_queue_control(dev, idx, 299 MLX5_MP_REQ_QUEUE_TX_START); 300 } else { 301 ret = mlx5_tx_queue_start_primary(dev, idx); 302 } 303 return ret; 304 } 305 306 /** 307 * Tx queue presetup checks. 308 * 309 * @param dev 310 * Pointer to Ethernet device structure. 311 * @param idx 312 * Tx queue index. 313 * @param desc 314 * Number of descriptors to configure in queue. 315 * 316 * @return 317 * 0 on success, a negative errno value otherwise and rte_errno is set. 318 */ 319 static int 320 mlx5_tx_queue_pre_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t *desc) 321 { 322 struct mlx5_priv *priv = dev->data->dev_private; 323 324 if (*desc <= MLX5_TX_COMP_THRESH) { 325 DRV_LOG(WARNING, 326 "port %u number of descriptors requested for Tx queue" 327 " %u must be higher than MLX5_TX_COMP_THRESH, using %u" 328 " instead of %u", dev->data->port_id, idx, 329 MLX5_TX_COMP_THRESH + 1, *desc); 330 *desc = MLX5_TX_COMP_THRESH + 1; 331 } 332 if (!rte_is_power_of_2(*desc)) { 333 *desc = 1 << log2above(*desc); 334 DRV_LOG(WARNING, 335 "port %u increased number of descriptors in Tx queue" 336 " %u to the next power of two (%d)", 337 dev->data->port_id, idx, *desc); 338 } 339 DRV_LOG(DEBUG, "port %u configuring queue %u for %u descriptors", 340 dev->data->port_id, idx, *desc); 341 if (idx >= priv->txqs_n) { 342 DRV_LOG(ERR, "port %u Tx queue index out of range (%u >= %u)", 343 dev->data->port_id, idx, priv->txqs_n); 344 rte_errno = EOVERFLOW; 345 return -rte_errno; 346 } 347 if (!mlx5_txq_releasable(dev, idx)) { 348 rte_errno = EBUSY; 349 DRV_LOG(ERR, "port %u unable to release queue index %u", 350 dev->data->port_id, idx); 351 return -rte_errno; 352 } 353 mlx5_txq_release(dev, idx); 354 return 0; 355 } 356 357 /** 358 * DPDK callback to configure a TX queue. 359 * 360 * @param dev 361 * Pointer to Ethernet device structure. 362 * @param idx 363 * TX queue index. 364 * @param desc 365 * Number of descriptors to configure in queue. 366 * @param socket 367 * NUMA socket on which memory must be allocated. 368 * @param[in] conf 369 * Thresholds parameters. 370 * 371 * @return 372 * 0 on success, a negative errno value otherwise and rte_errno is set. 373 */ 374 int 375 mlx5_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, 376 unsigned int socket, const struct rte_eth_txconf *conf) 377 { 378 struct mlx5_priv *priv = dev->data->dev_private; 379 struct mlx5_txq_data *txq = (*priv->txqs)[idx]; 380 struct mlx5_txq_ctrl *txq_ctrl = 381 container_of(txq, struct mlx5_txq_ctrl, txq); 382 int res; 383 384 res = mlx5_tx_queue_pre_setup(dev, idx, &desc); 385 if (res) 386 return res; 387 txq_ctrl = mlx5_txq_new(dev, idx, desc, socket, conf); 388 if (!txq_ctrl) { 389 DRV_LOG(ERR, "port %u unable to allocate queue index %u", 390 dev->data->port_id, idx); 391 return -rte_errno; 392 } 393 DRV_LOG(DEBUG, "port %u adding Tx queue %u to list", 394 dev->data->port_id, idx); 395 (*priv->txqs)[idx] = &txq_ctrl->txq; 396 return 0; 397 } 398 399 /** 400 * DPDK callback to configure a TX hairpin queue. 401 * 402 * @param dev 403 * Pointer to Ethernet device structure. 404 * @param idx 405 * TX queue index. 406 * @param desc 407 * Number of descriptors to configure in queue. 408 * @param[in] hairpin_conf 409 * The hairpin binding configuration. 410 * 411 * @return 412 * 0 on success, a negative errno value otherwise and rte_errno is set. 413 */ 414 int 415 mlx5_tx_hairpin_queue_setup(struct rte_eth_dev *dev, uint16_t idx, 416 uint16_t desc, 417 const struct rte_eth_hairpin_conf *hairpin_conf) 418 { 419 struct mlx5_priv *priv = dev->data->dev_private; 420 struct mlx5_txq_data *txq = (*priv->txqs)[idx]; 421 struct mlx5_txq_ctrl *txq_ctrl = 422 container_of(txq, struct mlx5_txq_ctrl, txq); 423 int res; 424 425 res = mlx5_tx_queue_pre_setup(dev, idx, &desc); 426 if (res) 427 return res; 428 if (hairpin_conf->peer_count != 1) { 429 rte_errno = EINVAL; 430 DRV_LOG(ERR, "port %u unable to setup Tx hairpin queue index %u" 431 " peer count is %u", dev->data->port_id, 432 idx, hairpin_conf->peer_count); 433 return -rte_errno; 434 } 435 if (hairpin_conf->peers[0].port == dev->data->port_id) { 436 if (hairpin_conf->peers[0].queue >= priv->rxqs_n) { 437 rte_errno = EINVAL; 438 DRV_LOG(ERR, "port %u unable to setup Tx hairpin queue" 439 " index %u, Rx %u is larger than %u", 440 dev->data->port_id, idx, 441 hairpin_conf->peers[0].queue, priv->txqs_n); 442 return -rte_errno; 443 } 444 } else { 445 if (hairpin_conf->manual_bind == 0 || 446 hairpin_conf->tx_explicit == 0) { 447 rte_errno = EINVAL; 448 DRV_LOG(ERR, "port %u unable to setup Tx hairpin queue" 449 " index %u peer port %u with attributes %u %u", 450 dev->data->port_id, idx, 451 hairpin_conf->peers[0].port, 452 hairpin_conf->manual_bind, 453 hairpin_conf->tx_explicit); 454 return -rte_errno; 455 } 456 } 457 txq_ctrl = mlx5_txq_hairpin_new(dev, idx, desc, hairpin_conf); 458 if (!txq_ctrl) { 459 DRV_LOG(ERR, "port %u unable to allocate queue index %u", 460 dev->data->port_id, idx); 461 return -rte_errno; 462 } 463 DRV_LOG(DEBUG, "port %u adding Tx queue %u to list", 464 dev->data->port_id, idx); 465 (*priv->txqs)[idx] = &txq_ctrl->txq; 466 dev->data->tx_queue_state[idx] = RTE_ETH_QUEUE_STATE_HAIRPIN; 467 return 0; 468 } 469 470 /** 471 * DPDK callback to release a TX queue. 472 * 473 * @param dpdk_txq 474 * Generic TX queue pointer. 475 */ 476 void 477 mlx5_tx_queue_release(void *dpdk_txq) 478 { 479 struct mlx5_txq_data *txq = (struct mlx5_txq_data *)dpdk_txq; 480 struct mlx5_txq_ctrl *txq_ctrl; 481 struct mlx5_priv *priv; 482 unsigned int i; 483 484 if (txq == NULL) 485 return; 486 txq_ctrl = container_of(txq, struct mlx5_txq_ctrl, txq); 487 priv = txq_ctrl->priv; 488 for (i = 0; (i != priv->txqs_n); ++i) 489 if ((*priv->txqs)[i] == txq) { 490 DRV_LOG(DEBUG, "port %u removing Tx queue %u from list", 491 PORT_ID(priv), txq->idx); 492 mlx5_txq_release(ETH_DEV(priv), i); 493 break; 494 } 495 } 496 497 /** 498 * Configure the doorbell register non-cached attribute. 499 * 500 * @param txq_ctrl 501 * Pointer to Tx queue control structure. 502 * @param page_size 503 * Systme page size 504 */ 505 static void 506 txq_uar_ncattr_init(struct mlx5_txq_ctrl *txq_ctrl, size_t page_size) 507 { 508 struct mlx5_priv *priv = txq_ctrl->priv; 509 off_t cmd; 510 511 txq_ctrl->txq.db_heu = priv->config.dbnc == MLX5_TXDB_HEURISTIC; 512 txq_ctrl->txq.db_nc = 0; 513 /* Check the doorbell register mapping type. */ 514 cmd = txq_ctrl->uar_mmap_offset / page_size; 515 cmd >>= MLX5_UAR_MMAP_CMD_SHIFT; 516 cmd &= MLX5_UAR_MMAP_CMD_MASK; 517 if (cmd == MLX5_MMAP_GET_NC_PAGES_CMD) 518 txq_ctrl->txq.db_nc = 1; 519 } 520 521 /** 522 * Initialize Tx UAR registers for primary process. 523 * 524 * @param txq_ctrl 525 * Pointer to Tx queue control structure. 526 */ 527 void 528 txq_uar_init(struct mlx5_txq_ctrl *txq_ctrl) 529 { 530 struct mlx5_priv *priv = txq_ctrl->priv; 531 struct mlx5_proc_priv *ppriv = MLX5_PROC_PRIV(PORT_ID(priv)); 532 #ifndef RTE_ARCH_64 533 unsigned int lock_idx; 534 #endif 535 const size_t page_size = rte_mem_page_size(); 536 if (page_size == (size_t)-1) { 537 DRV_LOG(ERR, "Failed to get mem page size"); 538 rte_errno = ENOMEM; 539 } 540 541 if (txq_ctrl->type != MLX5_TXQ_TYPE_STANDARD) 542 return; 543 MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY); 544 MLX5_ASSERT(ppriv); 545 ppriv->uar_table[txq_ctrl->txq.idx] = txq_ctrl->bf_reg; 546 txq_uar_ncattr_init(txq_ctrl, page_size); 547 #ifndef RTE_ARCH_64 548 /* Assign an UAR lock according to UAR page number */ 549 lock_idx = (txq_ctrl->uar_mmap_offset / page_size) & 550 MLX5_UAR_PAGE_NUM_MASK; 551 txq_ctrl->txq.uar_lock = &priv->sh->uar_lock[lock_idx]; 552 #endif 553 } 554 555 /** 556 * Remap UAR register of a Tx queue for secondary process. 557 * 558 * Remapped address is stored at the table in the process private structure of 559 * the device, indexed by queue index. 560 * 561 * @param txq_ctrl 562 * Pointer to Tx queue control structure. 563 * @param fd 564 * Verbs file descriptor to map UAR pages. 565 * 566 * @return 567 * 0 on success, a negative errno value otherwise and rte_errno is set. 568 */ 569 static int 570 txq_uar_init_secondary(struct mlx5_txq_ctrl *txq_ctrl, int fd) 571 { 572 struct mlx5_priv *priv = txq_ctrl->priv; 573 struct mlx5_proc_priv *ppriv = MLX5_PROC_PRIV(PORT_ID(priv)); 574 struct mlx5_txq_data *txq = &txq_ctrl->txq; 575 void *addr; 576 uintptr_t uar_va; 577 uintptr_t offset; 578 const size_t page_size = rte_mem_page_size(); 579 if (page_size == (size_t)-1) { 580 DRV_LOG(ERR, "Failed to get mem page size"); 581 rte_errno = ENOMEM; 582 return -rte_errno; 583 } 584 585 if (txq_ctrl->type != MLX5_TXQ_TYPE_STANDARD) 586 return 0; 587 MLX5_ASSERT(ppriv); 588 /* 589 * As rdma-core, UARs are mapped in size of OS page 590 * size. Ref to libmlx5 function: mlx5_init_context() 591 */ 592 uar_va = (uintptr_t)txq_ctrl->bf_reg; 593 offset = uar_va & (page_size - 1); /* Offset in page. */ 594 addr = rte_mem_map(NULL, page_size, RTE_PROT_WRITE, RTE_MAP_SHARED, 595 fd, txq_ctrl->uar_mmap_offset); 596 if (!addr) { 597 DRV_LOG(ERR, 598 "port %u mmap failed for BF reg of txq %u", 599 txq->port_id, txq->idx); 600 rte_errno = ENXIO; 601 return -rte_errno; 602 } 603 addr = RTE_PTR_ADD(addr, offset); 604 ppriv->uar_table[txq->idx] = addr; 605 txq_uar_ncattr_init(txq_ctrl, page_size); 606 return 0; 607 } 608 609 /** 610 * Unmap UAR register of a Tx queue for secondary process. 611 * 612 * @param txq_ctrl 613 * Pointer to Tx queue control structure. 614 */ 615 static void 616 txq_uar_uninit_secondary(struct mlx5_txq_ctrl *txq_ctrl) 617 { 618 struct mlx5_proc_priv *ppriv = MLX5_PROC_PRIV(PORT_ID(txq_ctrl->priv)); 619 void *addr; 620 const size_t page_size = rte_mem_page_size(); 621 if (page_size == (size_t)-1) { 622 DRV_LOG(ERR, "Failed to get mem page size"); 623 rte_errno = ENOMEM; 624 } 625 626 if (txq_ctrl->type != MLX5_TXQ_TYPE_STANDARD) 627 return; 628 addr = ppriv->uar_table[txq_ctrl->txq.idx]; 629 rte_mem_unmap(RTE_PTR_ALIGN_FLOOR(addr, page_size), page_size); 630 } 631 632 /** 633 * Deinitialize Tx UAR registers for secondary process. 634 * 635 * @param dev 636 * Pointer to Ethernet device. 637 */ 638 void 639 mlx5_tx_uar_uninit_secondary(struct rte_eth_dev *dev) 640 { 641 struct mlx5_proc_priv *ppriv = (struct mlx5_proc_priv *) 642 dev->process_private; 643 const size_t page_size = rte_mem_page_size(); 644 void *addr; 645 unsigned int i; 646 647 if (page_size == (size_t)-1) { 648 DRV_LOG(ERR, "Failed to get mem page size"); 649 return; 650 } 651 MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_SECONDARY); 652 for (i = 0; i != ppriv->uar_table_sz; ++i) { 653 if (!ppriv->uar_table[i]) 654 continue; 655 addr = ppriv->uar_table[i]; 656 rte_mem_unmap(RTE_PTR_ALIGN_FLOOR(addr, page_size), page_size); 657 658 } 659 } 660 661 /** 662 * Initialize Tx UAR registers for secondary process. 663 * 664 * @param dev 665 * Pointer to Ethernet device. 666 * @param fd 667 * Verbs file descriptor to map UAR pages. 668 * 669 * @return 670 * 0 on success, a negative errno value otherwise and rte_errno is set. 671 */ 672 int 673 mlx5_tx_uar_init_secondary(struct rte_eth_dev *dev, int fd) 674 { 675 struct mlx5_priv *priv = dev->data->dev_private; 676 struct mlx5_txq_data *txq; 677 struct mlx5_txq_ctrl *txq_ctrl; 678 unsigned int i; 679 int ret; 680 681 MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_SECONDARY); 682 for (i = 0; i != priv->txqs_n; ++i) { 683 if (!(*priv->txqs)[i]) 684 continue; 685 txq = (*priv->txqs)[i]; 686 txq_ctrl = container_of(txq, struct mlx5_txq_ctrl, txq); 687 if (txq_ctrl->type != MLX5_TXQ_TYPE_STANDARD) 688 continue; 689 MLX5_ASSERT(txq->idx == (uint16_t)i); 690 ret = txq_uar_init_secondary(txq_ctrl, fd); 691 if (ret) 692 goto error; 693 } 694 return 0; 695 error: 696 /* Rollback. */ 697 do { 698 if (!(*priv->txqs)[i]) 699 continue; 700 txq = (*priv->txqs)[i]; 701 txq_ctrl = container_of(txq, struct mlx5_txq_ctrl, txq); 702 txq_uar_uninit_secondary(txq_ctrl); 703 } while (i--); 704 return -rte_errno; 705 } 706 707 /** 708 * Verify the Verbs Tx queue list is empty 709 * 710 * @param dev 711 * Pointer to Ethernet device. 712 * 713 * @return 714 * The number of object not released. 715 */ 716 int 717 mlx5_txq_obj_verify(struct rte_eth_dev *dev) 718 { 719 struct mlx5_priv *priv = dev->data->dev_private; 720 int ret = 0; 721 struct mlx5_txq_obj *txq_obj; 722 723 LIST_FOREACH(txq_obj, &priv->txqsobj, next) { 724 DRV_LOG(DEBUG, "port %u Verbs Tx queue %u still referenced", 725 dev->data->port_id, txq_obj->txq_ctrl->txq.idx); 726 ++ret; 727 } 728 return ret; 729 } 730 731 /** 732 * Calculate the total number of WQEBB for Tx queue. 733 * 734 * Simplified version of calc_sq_size() in rdma-core. 735 * 736 * @param txq_ctrl 737 * Pointer to Tx queue control structure. 738 * 739 * @return 740 * The number of WQEBB. 741 */ 742 static int 743 txq_calc_wqebb_cnt(struct mlx5_txq_ctrl *txq_ctrl) 744 { 745 unsigned int wqe_size; 746 const unsigned int desc = 1 << txq_ctrl->txq.elts_n; 747 748 wqe_size = MLX5_WQE_CSEG_SIZE + 749 MLX5_WQE_ESEG_SIZE + 750 MLX5_WSEG_SIZE - 751 MLX5_ESEG_MIN_INLINE_SIZE + 752 txq_ctrl->max_inline_data; 753 return rte_align32pow2(wqe_size * desc) / MLX5_WQE_SIZE; 754 } 755 756 /** 757 * Calculate the maximal inline data size for Tx queue. 758 * 759 * @param txq_ctrl 760 * Pointer to Tx queue control structure. 761 * 762 * @return 763 * The maximal inline data size. 764 */ 765 static unsigned int 766 txq_calc_inline_max(struct mlx5_txq_ctrl *txq_ctrl) 767 { 768 const unsigned int desc = 1 << txq_ctrl->txq.elts_n; 769 struct mlx5_priv *priv = txq_ctrl->priv; 770 unsigned int wqe_size; 771 772 wqe_size = priv->sh->device_attr.max_qp_wr / desc; 773 if (!wqe_size) 774 return 0; 775 /* 776 * This calculation is derived from tthe source of 777 * mlx5_calc_send_wqe() in rdma_core library. 778 */ 779 wqe_size = wqe_size * MLX5_WQE_SIZE - 780 MLX5_WQE_CSEG_SIZE - 781 MLX5_WQE_ESEG_SIZE - 782 MLX5_WSEG_SIZE - 783 MLX5_WSEG_SIZE + 784 MLX5_DSEG_MIN_INLINE_SIZE; 785 return wqe_size; 786 } 787 788 /** 789 * Set Tx queue parameters from device configuration. 790 * 791 * @param txq_ctrl 792 * Pointer to Tx queue control structure. 793 */ 794 static void 795 txq_set_params(struct mlx5_txq_ctrl *txq_ctrl) 796 { 797 struct mlx5_priv *priv = txq_ctrl->priv; 798 struct mlx5_dev_config *config = &priv->config; 799 unsigned int inlen_send; /* Inline data for ordinary SEND.*/ 800 unsigned int inlen_empw; /* Inline data for enhanced MPW. */ 801 unsigned int inlen_mode; /* Minimal required Inline data. */ 802 unsigned int txqs_inline; /* Min Tx queues to enable inline. */ 803 uint64_t dev_txoff = priv->dev_data->dev_conf.txmode.offloads; 804 bool tso = txq_ctrl->txq.offloads & (DEV_TX_OFFLOAD_TCP_TSO | 805 DEV_TX_OFFLOAD_VXLAN_TNL_TSO | 806 DEV_TX_OFFLOAD_GRE_TNL_TSO | 807 DEV_TX_OFFLOAD_IP_TNL_TSO | 808 DEV_TX_OFFLOAD_UDP_TNL_TSO); 809 bool vlan_inline; 810 unsigned int temp; 811 812 txq_ctrl->txq.fast_free = 813 !!((txq_ctrl->txq.offloads & DEV_TX_OFFLOAD_MBUF_FAST_FREE) && 814 !(txq_ctrl->txq.offloads & DEV_TX_OFFLOAD_MULTI_SEGS) && 815 !config->mprq.enabled); 816 if (config->txqs_inline == MLX5_ARG_UNSET) 817 txqs_inline = 818 #if defined(RTE_ARCH_ARM64) 819 (priv->pci_dev && priv->pci_dev->id.device_id == 820 PCI_DEVICE_ID_MELLANOX_CONNECTX5BF) ? 821 MLX5_INLINE_MAX_TXQS_BLUEFIELD : 822 #endif 823 MLX5_INLINE_MAX_TXQS; 824 else 825 txqs_inline = (unsigned int)config->txqs_inline; 826 inlen_send = (config->txq_inline_max == MLX5_ARG_UNSET) ? 827 MLX5_SEND_DEF_INLINE_LEN : 828 (unsigned int)config->txq_inline_max; 829 inlen_empw = (config->txq_inline_mpw == MLX5_ARG_UNSET) ? 830 MLX5_EMPW_DEF_INLINE_LEN : 831 (unsigned int)config->txq_inline_mpw; 832 inlen_mode = (config->txq_inline_min == MLX5_ARG_UNSET) ? 833 0 : (unsigned int)config->txq_inline_min; 834 if (config->mps != MLX5_MPW_ENHANCED && config->mps != MLX5_MPW) 835 inlen_empw = 0; 836 /* 837 * If there is requested minimal amount of data to inline 838 * we MUST enable inlining. This is a case for ConnectX-4 839 * which usually requires L2 inlined for correct operating 840 * and ConnectX-4 Lx which requires L2-L4 inlined to 841 * support E-Switch Flows. 842 */ 843 if (inlen_mode) { 844 if (inlen_mode <= MLX5_ESEG_MIN_INLINE_SIZE) { 845 /* 846 * Optimize minimal inlining for single 847 * segment packets to fill one WQEBB 848 * without gaps. 849 */ 850 temp = MLX5_ESEG_MIN_INLINE_SIZE; 851 } else { 852 temp = inlen_mode - MLX5_ESEG_MIN_INLINE_SIZE; 853 temp = RTE_ALIGN(temp, MLX5_WSEG_SIZE) + 854 MLX5_ESEG_MIN_INLINE_SIZE; 855 temp = RTE_MIN(temp, MLX5_SEND_MAX_INLINE_LEN); 856 } 857 if (temp != inlen_mode) { 858 DRV_LOG(INFO, 859 "port %u minimal required inline setting" 860 " aligned from %u to %u", 861 PORT_ID(priv), inlen_mode, temp); 862 inlen_mode = temp; 863 } 864 } 865 /* 866 * If port is configured to support VLAN insertion and device 867 * does not support this feature by HW (for NICs before ConnectX-5 868 * or in case of wqe_vlan_insert flag is not set) we must enable 869 * data inline on all queues because it is supported by single 870 * tx_burst routine. 871 */ 872 txq_ctrl->txq.vlan_en = config->hw_vlan_insert; 873 vlan_inline = (dev_txoff & DEV_TX_OFFLOAD_VLAN_INSERT) && 874 !config->hw_vlan_insert; 875 /* 876 * If there are few Tx queues it is prioritized 877 * to save CPU cycles and disable data inlining at all. 878 */ 879 if (inlen_send && priv->txqs_n >= txqs_inline) { 880 /* 881 * The data sent with ordinal MLX5_OPCODE_SEND 882 * may be inlined in Ethernet Segment, align the 883 * length accordingly to fit entire WQEBBs. 884 */ 885 temp = RTE_MAX(inlen_send, 886 MLX5_ESEG_MIN_INLINE_SIZE + MLX5_WQE_DSEG_SIZE); 887 temp -= MLX5_ESEG_MIN_INLINE_SIZE + MLX5_WQE_DSEG_SIZE; 888 temp = RTE_ALIGN(temp, MLX5_WQE_SIZE); 889 temp += MLX5_ESEG_MIN_INLINE_SIZE + MLX5_WQE_DSEG_SIZE; 890 temp = RTE_MIN(temp, MLX5_WQE_SIZE_MAX + 891 MLX5_ESEG_MIN_INLINE_SIZE - 892 MLX5_WQE_CSEG_SIZE - 893 MLX5_WQE_ESEG_SIZE - 894 MLX5_WQE_DSEG_SIZE * 2); 895 temp = RTE_MIN(temp, MLX5_SEND_MAX_INLINE_LEN); 896 temp = RTE_MAX(temp, inlen_mode); 897 if (temp != inlen_send) { 898 DRV_LOG(INFO, 899 "port %u ordinary send inline setting" 900 " aligned from %u to %u", 901 PORT_ID(priv), inlen_send, temp); 902 inlen_send = temp; 903 } 904 /* 905 * Not aligned to cache lines, but to WQEs. 906 * First bytes of data (initial alignment) 907 * is going to be copied explicitly at the 908 * beginning of inlining buffer in Ethernet 909 * Segment. 910 */ 911 MLX5_ASSERT(inlen_send >= MLX5_ESEG_MIN_INLINE_SIZE); 912 MLX5_ASSERT(inlen_send <= MLX5_WQE_SIZE_MAX + 913 MLX5_ESEG_MIN_INLINE_SIZE - 914 MLX5_WQE_CSEG_SIZE - 915 MLX5_WQE_ESEG_SIZE - 916 MLX5_WQE_DSEG_SIZE * 2); 917 } else if (inlen_mode) { 918 /* 919 * If minimal inlining is requested we must 920 * enable inlining in general, despite the 921 * number of configured queues. Ignore the 922 * txq_inline_max devarg, this is not 923 * full-featured inline. 924 */ 925 inlen_send = inlen_mode; 926 inlen_empw = 0; 927 } else if (vlan_inline) { 928 /* 929 * Hardware does not report offload for 930 * VLAN insertion, we must enable data inline 931 * to implement feature by software. 932 */ 933 inlen_send = MLX5_ESEG_MIN_INLINE_SIZE; 934 inlen_empw = 0; 935 } else { 936 inlen_send = 0; 937 inlen_empw = 0; 938 } 939 txq_ctrl->txq.inlen_send = inlen_send; 940 txq_ctrl->txq.inlen_mode = inlen_mode; 941 txq_ctrl->txq.inlen_empw = 0; 942 if (inlen_send && inlen_empw && priv->txqs_n >= txqs_inline) { 943 /* 944 * The data sent with MLX5_OPCODE_ENHANCED_MPSW 945 * may be inlined in Data Segment, align the 946 * length accordingly to fit entire WQEBBs. 947 */ 948 temp = RTE_MAX(inlen_empw, 949 MLX5_WQE_SIZE + MLX5_DSEG_MIN_INLINE_SIZE); 950 temp -= MLX5_DSEG_MIN_INLINE_SIZE; 951 temp = RTE_ALIGN(temp, MLX5_WQE_SIZE); 952 temp += MLX5_DSEG_MIN_INLINE_SIZE; 953 temp = RTE_MIN(temp, MLX5_WQE_SIZE_MAX + 954 MLX5_DSEG_MIN_INLINE_SIZE - 955 MLX5_WQE_CSEG_SIZE - 956 MLX5_WQE_ESEG_SIZE - 957 MLX5_WQE_DSEG_SIZE); 958 temp = RTE_MIN(temp, MLX5_EMPW_MAX_INLINE_LEN); 959 if (temp != inlen_empw) { 960 DRV_LOG(INFO, 961 "port %u enhanced empw inline setting" 962 " aligned from %u to %u", 963 PORT_ID(priv), inlen_empw, temp); 964 inlen_empw = temp; 965 } 966 MLX5_ASSERT(inlen_empw >= MLX5_ESEG_MIN_INLINE_SIZE); 967 MLX5_ASSERT(inlen_empw <= MLX5_WQE_SIZE_MAX + 968 MLX5_DSEG_MIN_INLINE_SIZE - 969 MLX5_WQE_CSEG_SIZE - 970 MLX5_WQE_ESEG_SIZE - 971 MLX5_WQE_DSEG_SIZE); 972 txq_ctrl->txq.inlen_empw = inlen_empw; 973 } 974 txq_ctrl->max_inline_data = RTE_MAX(inlen_send, inlen_empw); 975 if (tso) { 976 txq_ctrl->max_tso_header = MLX5_MAX_TSO_HEADER; 977 txq_ctrl->max_inline_data = RTE_MAX(txq_ctrl->max_inline_data, 978 MLX5_MAX_TSO_HEADER); 979 txq_ctrl->txq.tso_en = 1; 980 } 981 txq_ctrl->txq.tunnel_en = config->tunnel_en | config->swp; 982 txq_ctrl->txq.swp_en = ((DEV_TX_OFFLOAD_IP_TNL_TSO | 983 DEV_TX_OFFLOAD_UDP_TNL_TSO | 984 DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM) & 985 txq_ctrl->txq.offloads) && config->swp; 986 } 987 988 /** 989 * Adjust Tx queue data inline parameters for large queue sizes. 990 * The data inline feature requires multiple WQEs to fit the packets, 991 * and if the large amount of Tx descriptors is requested by application 992 * the total WQE amount may exceed the hardware capabilities. If the 993 * default inline setting are used we can try to adjust these ones and 994 * meet the hardware requirements and not exceed the queue size. 995 * 996 * @param txq_ctrl 997 * Pointer to Tx queue control structure. 998 * 999 * @return 1000 * Zero on success, otherwise the parameters can not be adjusted. 1001 */ 1002 static int 1003 txq_adjust_params(struct mlx5_txq_ctrl *txq_ctrl) 1004 { 1005 struct mlx5_priv *priv = txq_ctrl->priv; 1006 struct mlx5_dev_config *config = &priv->config; 1007 unsigned int max_inline; 1008 1009 max_inline = txq_calc_inline_max(txq_ctrl); 1010 if (!txq_ctrl->txq.inlen_send) { 1011 /* 1012 * Inline data feature is not engaged at all. 1013 * There is nothing to adjust. 1014 */ 1015 return 0; 1016 } 1017 if (txq_ctrl->max_inline_data <= max_inline) { 1018 /* 1019 * The requested inline data length does not 1020 * exceed queue capabilities. 1021 */ 1022 return 0; 1023 } 1024 if (txq_ctrl->txq.inlen_mode > max_inline) { 1025 DRV_LOG(ERR, 1026 "minimal data inline requirements (%u) are not" 1027 " satisfied (%u) on port %u, try the smaller" 1028 " Tx queue size (%d)", 1029 txq_ctrl->txq.inlen_mode, max_inline, 1030 priv->dev_data->port_id, 1031 priv->sh->device_attr.max_qp_wr); 1032 goto error; 1033 } 1034 if (txq_ctrl->txq.inlen_send > max_inline && 1035 config->txq_inline_max != MLX5_ARG_UNSET && 1036 config->txq_inline_max > (int)max_inline) { 1037 DRV_LOG(ERR, 1038 "txq_inline_max requirements (%u) are not" 1039 " satisfied (%u) on port %u, try the smaller" 1040 " Tx queue size (%d)", 1041 txq_ctrl->txq.inlen_send, max_inline, 1042 priv->dev_data->port_id, 1043 priv->sh->device_attr.max_qp_wr); 1044 goto error; 1045 } 1046 if (txq_ctrl->txq.inlen_empw > max_inline && 1047 config->txq_inline_mpw != MLX5_ARG_UNSET && 1048 config->txq_inline_mpw > (int)max_inline) { 1049 DRV_LOG(ERR, 1050 "txq_inline_mpw requirements (%u) are not" 1051 " satisfied (%u) on port %u, try the smaller" 1052 " Tx queue size (%d)", 1053 txq_ctrl->txq.inlen_empw, max_inline, 1054 priv->dev_data->port_id, 1055 priv->sh->device_attr.max_qp_wr); 1056 goto error; 1057 } 1058 if (txq_ctrl->txq.tso_en && max_inline < MLX5_MAX_TSO_HEADER) { 1059 DRV_LOG(ERR, 1060 "tso header inline requirements (%u) are not" 1061 " satisfied (%u) on port %u, try the smaller" 1062 " Tx queue size (%d)", 1063 MLX5_MAX_TSO_HEADER, max_inline, 1064 priv->dev_data->port_id, 1065 priv->sh->device_attr.max_qp_wr); 1066 goto error; 1067 } 1068 if (txq_ctrl->txq.inlen_send > max_inline) { 1069 DRV_LOG(WARNING, 1070 "adjust txq_inline_max (%u->%u)" 1071 " due to large Tx queue on port %u", 1072 txq_ctrl->txq.inlen_send, max_inline, 1073 priv->dev_data->port_id); 1074 txq_ctrl->txq.inlen_send = max_inline; 1075 } 1076 if (txq_ctrl->txq.inlen_empw > max_inline) { 1077 DRV_LOG(WARNING, 1078 "adjust txq_inline_mpw (%u->%u)" 1079 "due to large Tx queue on port %u", 1080 txq_ctrl->txq.inlen_empw, max_inline, 1081 priv->dev_data->port_id); 1082 txq_ctrl->txq.inlen_empw = max_inline; 1083 } 1084 txq_ctrl->max_inline_data = RTE_MAX(txq_ctrl->txq.inlen_send, 1085 txq_ctrl->txq.inlen_empw); 1086 MLX5_ASSERT(txq_ctrl->max_inline_data <= max_inline); 1087 MLX5_ASSERT(txq_ctrl->txq.inlen_mode <= max_inline); 1088 MLX5_ASSERT(txq_ctrl->txq.inlen_mode <= txq_ctrl->txq.inlen_send); 1089 MLX5_ASSERT(txq_ctrl->txq.inlen_mode <= txq_ctrl->txq.inlen_empw || 1090 !txq_ctrl->txq.inlen_empw); 1091 return 0; 1092 error: 1093 rte_errno = ENOMEM; 1094 return -ENOMEM; 1095 } 1096 1097 /** 1098 * Create a DPDK Tx queue. 1099 * 1100 * @param dev 1101 * Pointer to Ethernet device. 1102 * @param idx 1103 * TX queue index. 1104 * @param desc 1105 * Number of descriptors to configure in queue. 1106 * @param socket 1107 * NUMA socket on which memory must be allocated. 1108 * @param[in] conf 1109 * Thresholds parameters. 1110 * 1111 * @return 1112 * A DPDK queue object on success, NULL otherwise and rte_errno is set. 1113 */ 1114 struct mlx5_txq_ctrl * 1115 mlx5_txq_new(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, 1116 unsigned int socket, const struct rte_eth_txconf *conf) 1117 { 1118 struct mlx5_priv *priv = dev->data->dev_private; 1119 struct mlx5_txq_ctrl *tmpl; 1120 1121 tmpl = mlx5_malloc(MLX5_MEM_RTE | MLX5_MEM_ZERO, sizeof(*tmpl) + 1122 desc * sizeof(struct rte_mbuf *), 0, socket); 1123 if (!tmpl) { 1124 rte_errno = ENOMEM; 1125 return NULL; 1126 } 1127 if (mlx5_mr_btree_init(&tmpl->txq.mr_ctrl.cache_bh, 1128 MLX5_MR_BTREE_CACHE_N, socket)) { 1129 /* rte_errno is already set. */ 1130 goto error; 1131 } 1132 /* Save pointer of global generation number to check memory event. */ 1133 tmpl->txq.mr_ctrl.dev_gen_ptr = &priv->sh->share_cache.dev_gen; 1134 MLX5_ASSERT(desc > MLX5_TX_COMP_THRESH); 1135 tmpl->txq.offloads = conf->offloads | 1136 dev->data->dev_conf.txmode.offloads; 1137 tmpl->priv = priv; 1138 tmpl->socket = socket; 1139 tmpl->txq.elts_n = log2above(desc); 1140 tmpl->txq.elts_s = desc; 1141 tmpl->txq.elts_m = desc - 1; 1142 tmpl->txq.port_id = dev->data->port_id; 1143 tmpl->txq.idx = idx; 1144 txq_set_params(tmpl); 1145 if (txq_adjust_params(tmpl)) 1146 goto error; 1147 if (txq_calc_wqebb_cnt(tmpl) > 1148 priv->sh->device_attr.max_qp_wr) { 1149 DRV_LOG(ERR, 1150 "port %u Tx WQEBB count (%d) exceeds the limit (%d)," 1151 " try smaller queue size", 1152 dev->data->port_id, txq_calc_wqebb_cnt(tmpl), 1153 priv->sh->device_attr.max_qp_wr); 1154 rte_errno = ENOMEM; 1155 goto error; 1156 } 1157 __atomic_fetch_add(&tmpl->refcnt, 1, __ATOMIC_RELAXED); 1158 tmpl->type = MLX5_TXQ_TYPE_STANDARD; 1159 LIST_INSERT_HEAD(&priv->txqsctrl, tmpl, next); 1160 return tmpl; 1161 error: 1162 mlx5_mr_btree_free(&tmpl->txq.mr_ctrl.cache_bh); 1163 mlx5_free(tmpl); 1164 return NULL; 1165 } 1166 1167 /** 1168 * Create a DPDK Tx hairpin queue. 1169 * 1170 * @param dev 1171 * Pointer to Ethernet device. 1172 * @param idx 1173 * TX queue index. 1174 * @param desc 1175 * Number of descriptors to configure in queue. 1176 * @param hairpin_conf 1177 * The hairpin configuration. 1178 * 1179 * @return 1180 * A DPDK queue object on success, NULL otherwise and rte_errno is set. 1181 */ 1182 struct mlx5_txq_ctrl * 1183 mlx5_txq_hairpin_new(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, 1184 const struct rte_eth_hairpin_conf *hairpin_conf) 1185 { 1186 struct mlx5_priv *priv = dev->data->dev_private; 1187 struct mlx5_txq_ctrl *tmpl; 1188 1189 tmpl = mlx5_malloc(MLX5_MEM_RTE | MLX5_MEM_ZERO, sizeof(*tmpl), 0, 1190 SOCKET_ID_ANY); 1191 if (!tmpl) { 1192 rte_errno = ENOMEM; 1193 return NULL; 1194 } 1195 tmpl->priv = priv; 1196 tmpl->socket = SOCKET_ID_ANY; 1197 tmpl->txq.elts_n = log2above(desc); 1198 tmpl->txq.port_id = dev->data->port_id; 1199 tmpl->txq.idx = idx; 1200 tmpl->hairpin_conf = *hairpin_conf; 1201 tmpl->type = MLX5_TXQ_TYPE_HAIRPIN; 1202 __atomic_fetch_add(&tmpl->refcnt, 1, __ATOMIC_RELAXED); 1203 LIST_INSERT_HEAD(&priv->txqsctrl, tmpl, next); 1204 return tmpl; 1205 } 1206 1207 /** 1208 * Get a Tx queue. 1209 * 1210 * @param dev 1211 * Pointer to Ethernet device. 1212 * @param idx 1213 * TX queue index. 1214 * 1215 * @return 1216 * A pointer to the queue if it exists. 1217 */ 1218 struct mlx5_txq_ctrl * 1219 mlx5_txq_get(struct rte_eth_dev *dev, uint16_t idx) 1220 { 1221 struct mlx5_priv *priv = dev->data->dev_private; 1222 struct mlx5_txq_data *txq_data = (*priv->txqs)[idx]; 1223 struct mlx5_txq_ctrl *ctrl = NULL; 1224 1225 if (txq_data) { 1226 ctrl = container_of(txq_data, struct mlx5_txq_ctrl, txq); 1227 __atomic_fetch_add(&ctrl->refcnt, 1, __ATOMIC_RELAXED); 1228 } 1229 return ctrl; 1230 } 1231 1232 /** 1233 * Release a Tx queue. 1234 * 1235 * @param dev 1236 * Pointer to Ethernet device. 1237 * @param idx 1238 * TX queue index. 1239 * 1240 * @return 1241 * 1 while a reference on it exists, 0 when freed. 1242 */ 1243 int 1244 mlx5_txq_release(struct rte_eth_dev *dev, uint16_t idx) 1245 { 1246 struct mlx5_priv *priv = dev->data->dev_private; 1247 struct mlx5_txq_ctrl *txq_ctrl; 1248 1249 if (!(*priv->txqs)[idx]) 1250 return 0; 1251 txq_ctrl = container_of((*priv->txqs)[idx], struct mlx5_txq_ctrl, txq); 1252 if (__atomic_sub_fetch(&txq_ctrl->refcnt, 1, __ATOMIC_RELAXED) > 1) 1253 return 1; 1254 if (txq_ctrl->obj) { 1255 priv->obj_ops.txq_obj_release(txq_ctrl->obj); 1256 LIST_REMOVE(txq_ctrl->obj, next); 1257 mlx5_free(txq_ctrl->obj); 1258 txq_ctrl->obj = NULL; 1259 } 1260 if (txq_ctrl->type == MLX5_TXQ_TYPE_STANDARD) { 1261 if (txq_ctrl->txq.fcqs) { 1262 mlx5_free(txq_ctrl->txq.fcqs); 1263 txq_ctrl->txq.fcqs = NULL; 1264 } 1265 txq_free_elts(txq_ctrl); 1266 dev->data->tx_queue_state[idx] = RTE_ETH_QUEUE_STATE_STOPPED; 1267 } 1268 if (!__atomic_load_n(&txq_ctrl->refcnt, __ATOMIC_RELAXED)) { 1269 if (txq_ctrl->type == MLX5_TXQ_TYPE_STANDARD) 1270 mlx5_mr_btree_free(&txq_ctrl->txq.mr_ctrl.cache_bh); 1271 LIST_REMOVE(txq_ctrl, next); 1272 mlx5_free(txq_ctrl); 1273 (*priv->txqs)[idx] = NULL; 1274 } 1275 return 0; 1276 } 1277 1278 /** 1279 * Verify if the queue can be released. 1280 * 1281 * @param dev 1282 * Pointer to Ethernet device. 1283 * @param idx 1284 * TX queue index. 1285 * 1286 * @return 1287 * 1 if the queue can be released. 1288 */ 1289 int 1290 mlx5_txq_releasable(struct rte_eth_dev *dev, uint16_t idx) 1291 { 1292 struct mlx5_priv *priv = dev->data->dev_private; 1293 struct mlx5_txq_ctrl *txq; 1294 1295 if (!(*priv->txqs)[idx]) 1296 return -1; 1297 txq = container_of((*priv->txqs)[idx], struct mlx5_txq_ctrl, txq); 1298 return (__atomic_load_n(&txq->refcnt, __ATOMIC_RELAXED) == 1); 1299 } 1300 1301 /** 1302 * Verify the Tx Queue list is empty 1303 * 1304 * @param dev 1305 * Pointer to Ethernet device. 1306 * 1307 * @return 1308 * The number of object not released. 1309 */ 1310 int 1311 mlx5_txq_verify(struct rte_eth_dev *dev) 1312 { 1313 struct mlx5_priv *priv = dev->data->dev_private; 1314 struct mlx5_txq_ctrl *txq_ctrl; 1315 int ret = 0; 1316 1317 LIST_FOREACH(txq_ctrl, &priv->txqsctrl, next) { 1318 DRV_LOG(DEBUG, "port %u Tx queue %u still referenced", 1319 dev->data->port_id, txq_ctrl->txq.idx); 1320 ++ret; 1321 } 1322 return ret; 1323 } 1324 1325 /** 1326 * Set the Tx queue dynamic timestamp (mask and offset) 1327 * 1328 * @param[in] dev 1329 * Pointer to the Ethernet device structure. 1330 */ 1331 void 1332 mlx5_txq_dynf_timestamp_set(struct rte_eth_dev *dev) 1333 { 1334 struct mlx5_priv *priv = dev->data->dev_private; 1335 struct mlx5_dev_ctx_shared *sh = priv->sh; 1336 struct mlx5_txq_data *data; 1337 int off, nbit; 1338 unsigned int i; 1339 uint64_t mask = 0; 1340 1341 nbit = rte_mbuf_dynflag_lookup 1342 (RTE_MBUF_DYNFLAG_TX_TIMESTAMP_NAME, NULL); 1343 off = rte_mbuf_dynfield_lookup 1344 (RTE_MBUF_DYNFIELD_TIMESTAMP_NAME, NULL); 1345 if (nbit >= 0 && off >= 0 && sh->txpp.refcnt) 1346 mask = 1ULL << nbit; 1347 for (i = 0; i != priv->txqs_n; ++i) { 1348 data = (*priv->txqs)[i]; 1349 if (!data) 1350 continue; 1351 data->sh = sh; 1352 data->ts_mask = mask; 1353 data->ts_offset = off; 1354 } 1355 } 1356