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