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 <fcntl.h> 11 #include <sys/queue.h> 12 13 #include <rte_mbuf.h> 14 #include <rte_malloc.h> 15 #include <ethdev_driver.h> 16 #include <rte_common.h> 17 #include <rte_interrupts.h> 18 #include <rte_debug.h> 19 #include <rte_io.h> 20 #include <rte_eal_paging.h> 21 22 #include <mlx5_glue.h> 23 #include <mlx5_malloc.h> 24 25 #include "mlx5_defs.h" 26 #include "mlx5.h" 27 #include "mlx5_tx.h" 28 #include "mlx5_rx.h" 29 #include "mlx5_utils.h" 30 #include "mlx5_autoconf.h" 31 32 33 /* Default RSS hash key also used for ConnectX-3. */ 34 uint8_t rss_hash_default_key[] = { 35 0x2c, 0xc6, 0x81, 0xd1, 36 0x5b, 0xdb, 0xf4, 0xf7, 37 0xfc, 0xa2, 0x83, 0x19, 38 0xdb, 0x1a, 0x3e, 0x94, 39 0x6b, 0x9e, 0x38, 0xd9, 40 0x2c, 0x9c, 0x03, 0xd1, 41 0xad, 0x99, 0x44, 0xa7, 42 0xd9, 0x56, 0x3d, 0x59, 43 0x06, 0x3c, 0x25, 0xf3, 44 0xfc, 0x1f, 0xdc, 0x2a, 45 }; 46 47 /* Length of the default RSS hash key. */ 48 static_assert(MLX5_RSS_HASH_KEY_LEN == 49 (unsigned int)sizeof(rss_hash_default_key), 50 "wrong RSS default key size."); 51 52 /** 53 * Calculate the number of CQEs in CQ for the Rx queue. 54 * 55 * @param rxq_data 56 * Pointer to receive queue structure. 57 * 58 * @return 59 * Number of CQEs in CQ. 60 */ 61 unsigned int 62 mlx5_rxq_cqe_num(struct mlx5_rxq_data *rxq_data) 63 { 64 unsigned int cqe_n; 65 unsigned int wqe_n = 1 << rxq_data->elts_n; 66 67 if (mlx5_rxq_mprq_enabled(rxq_data)) 68 cqe_n = wqe_n * (1 << rxq_data->strd_num_n) - 1; 69 else 70 cqe_n = wqe_n - 1; 71 return cqe_n; 72 } 73 74 /** 75 * Allocate RX queue elements for Multi-Packet RQ. 76 * 77 * @param rxq_ctrl 78 * Pointer to RX queue structure. 79 * 80 * @return 81 * 0 on success, a negative errno value otherwise and rte_errno is set. 82 */ 83 static int 84 rxq_alloc_elts_mprq(struct mlx5_rxq_ctrl *rxq_ctrl) 85 { 86 struct mlx5_rxq_data *rxq = &rxq_ctrl->rxq; 87 unsigned int wqe_n = 1 << rxq->elts_n; 88 unsigned int i; 89 int err; 90 91 /* Iterate on segments. */ 92 for (i = 0; i <= wqe_n; ++i) { 93 struct mlx5_mprq_buf *buf; 94 95 if (rte_mempool_get(rxq->mprq_mp, (void **)&buf) < 0) { 96 DRV_LOG(ERR, "port %u empty mbuf pool", rxq->port_id); 97 rte_errno = ENOMEM; 98 goto error; 99 } 100 if (i < wqe_n) 101 (*rxq->mprq_bufs)[i] = buf; 102 else 103 rxq->mprq_repl = buf; 104 } 105 DRV_LOG(DEBUG, 106 "port %u MPRQ queue %u allocated and configured %u segments", 107 rxq->port_id, rxq->idx, wqe_n); 108 return 0; 109 error: 110 err = rte_errno; /* Save rte_errno before cleanup. */ 111 wqe_n = i; 112 for (i = 0; (i != wqe_n); ++i) { 113 if ((*rxq->mprq_bufs)[i] != NULL) 114 rte_mempool_put(rxq->mprq_mp, 115 (*rxq->mprq_bufs)[i]); 116 (*rxq->mprq_bufs)[i] = NULL; 117 } 118 DRV_LOG(DEBUG, "port %u MPRQ queue %u failed, freed everything", 119 rxq->port_id, rxq->idx); 120 rte_errno = err; /* Restore rte_errno. */ 121 return -rte_errno; 122 } 123 124 /** 125 * Allocate RX queue elements for Single-Packet RQ. 126 * 127 * @param rxq_ctrl 128 * Pointer to RX queue structure. 129 * 130 * @return 131 * 0 on success, errno value on failure. 132 */ 133 static int 134 rxq_alloc_elts_sprq(struct mlx5_rxq_ctrl *rxq_ctrl) 135 { 136 const unsigned int sges_n = 1 << rxq_ctrl->rxq.sges_n; 137 unsigned int elts_n = mlx5_rxq_mprq_enabled(&rxq_ctrl->rxq) ? 138 (1 << rxq_ctrl->rxq.elts_n) * (1 << rxq_ctrl->rxq.strd_num_n) : 139 (1 << rxq_ctrl->rxq.elts_n); 140 unsigned int i; 141 int err; 142 143 /* Iterate on segments. */ 144 for (i = 0; (i != elts_n); ++i) { 145 struct mlx5_eth_rxseg *seg = &rxq_ctrl->rxq.rxseg[i % sges_n]; 146 struct rte_mbuf *buf; 147 148 buf = rte_pktmbuf_alloc(seg->mp); 149 if (buf == NULL) { 150 DRV_LOG(ERR, "port %u empty mbuf pool", 151 PORT_ID(rxq_ctrl->priv)); 152 rte_errno = ENOMEM; 153 goto error; 154 } 155 /* Headroom is reserved by rte_pktmbuf_alloc(). */ 156 MLX5_ASSERT(DATA_OFF(buf) == RTE_PKTMBUF_HEADROOM); 157 /* Buffer is supposed to be empty. */ 158 MLX5_ASSERT(rte_pktmbuf_data_len(buf) == 0); 159 MLX5_ASSERT(rte_pktmbuf_pkt_len(buf) == 0); 160 MLX5_ASSERT(!buf->next); 161 SET_DATA_OFF(buf, seg->offset); 162 PORT(buf) = rxq_ctrl->rxq.port_id; 163 DATA_LEN(buf) = seg->length; 164 PKT_LEN(buf) = seg->length; 165 NB_SEGS(buf) = 1; 166 (*rxq_ctrl->rxq.elts)[i] = buf; 167 } 168 /* If Rx vector is activated. */ 169 if (mlx5_rxq_check_vec_support(&rxq_ctrl->rxq) > 0) { 170 struct mlx5_rxq_data *rxq = &rxq_ctrl->rxq; 171 struct rte_mbuf *mbuf_init = &rxq->fake_mbuf; 172 struct rte_pktmbuf_pool_private *priv = 173 (struct rte_pktmbuf_pool_private *) 174 rte_mempool_get_priv(rxq_ctrl->rxq.mp); 175 int j; 176 177 /* Initialize default rearm_data for vPMD. */ 178 mbuf_init->data_off = RTE_PKTMBUF_HEADROOM; 179 rte_mbuf_refcnt_set(mbuf_init, 1); 180 mbuf_init->nb_segs = 1; 181 mbuf_init->port = rxq->port_id; 182 if (priv->flags & RTE_PKTMBUF_POOL_F_PINNED_EXT_BUF) 183 mbuf_init->ol_flags = EXT_ATTACHED_MBUF; 184 /* 185 * prevent compiler reordering: 186 * rearm_data covers previous fields. 187 */ 188 rte_compiler_barrier(); 189 rxq->mbuf_initializer = 190 *(rte_xmm_t *)&mbuf_init->rearm_data; 191 /* Padding with a fake mbuf for vectorized Rx. */ 192 for (j = 0; j < MLX5_VPMD_DESCS_PER_LOOP; ++j) 193 (*rxq->elts)[elts_n + j] = &rxq->fake_mbuf; 194 } 195 DRV_LOG(DEBUG, 196 "port %u SPRQ queue %u allocated and configured %u segments" 197 " (max %u packets)", 198 PORT_ID(rxq_ctrl->priv), rxq_ctrl->rxq.idx, elts_n, 199 elts_n / (1 << rxq_ctrl->rxq.sges_n)); 200 return 0; 201 error: 202 err = rte_errno; /* Save rte_errno before cleanup. */ 203 elts_n = i; 204 for (i = 0; (i != elts_n); ++i) { 205 if ((*rxq_ctrl->rxq.elts)[i] != NULL) 206 rte_pktmbuf_free_seg((*rxq_ctrl->rxq.elts)[i]); 207 (*rxq_ctrl->rxq.elts)[i] = NULL; 208 } 209 DRV_LOG(DEBUG, "port %u SPRQ queue %u failed, freed everything", 210 PORT_ID(rxq_ctrl->priv), rxq_ctrl->rxq.idx); 211 rte_errno = err; /* Restore rte_errno. */ 212 return -rte_errno; 213 } 214 215 /** 216 * Allocate RX queue elements. 217 * 218 * @param rxq_ctrl 219 * Pointer to RX queue structure. 220 * 221 * @return 222 * 0 on success, errno value on failure. 223 */ 224 int 225 rxq_alloc_elts(struct mlx5_rxq_ctrl *rxq_ctrl) 226 { 227 int ret = 0; 228 229 /** 230 * For MPRQ we need to allocate both MPRQ buffers 231 * for WQEs and simple mbufs for vector processing. 232 */ 233 if (mlx5_rxq_mprq_enabled(&rxq_ctrl->rxq)) 234 ret = rxq_alloc_elts_mprq(rxq_ctrl); 235 return (ret || rxq_alloc_elts_sprq(rxq_ctrl)); 236 } 237 238 /** 239 * Free RX queue elements for Multi-Packet RQ. 240 * 241 * @param rxq_ctrl 242 * Pointer to RX queue structure. 243 */ 244 static void 245 rxq_free_elts_mprq(struct mlx5_rxq_ctrl *rxq_ctrl) 246 { 247 struct mlx5_rxq_data *rxq = &rxq_ctrl->rxq; 248 uint16_t i; 249 250 DRV_LOG(DEBUG, "port %u Multi-Packet Rx queue %u freeing %d WRs", 251 rxq->port_id, rxq->idx, (1u << rxq->elts_n)); 252 if (rxq->mprq_bufs == NULL) 253 return; 254 for (i = 0; (i != (1u << rxq->elts_n)); ++i) { 255 if ((*rxq->mprq_bufs)[i] != NULL) 256 mlx5_mprq_buf_free((*rxq->mprq_bufs)[i]); 257 (*rxq->mprq_bufs)[i] = NULL; 258 } 259 if (rxq->mprq_repl != NULL) { 260 mlx5_mprq_buf_free(rxq->mprq_repl); 261 rxq->mprq_repl = NULL; 262 } 263 } 264 265 /** 266 * Free RX queue elements for Single-Packet RQ. 267 * 268 * @param rxq_ctrl 269 * Pointer to RX queue structure. 270 */ 271 static void 272 rxq_free_elts_sprq(struct mlx5_rxq_ctrl *rxq_ctrl) 273 { 274 struct mlx5_rxq_data *rxq = &rxq_ctrl->rxq; 275 const uint16_t q_n = mlx5_rxq_mprq_enabled(&rxq_ctrl->rxq) ? 276 (1 << rxq->elts_n) * (1 << rxq->strd_num_n) : 277 (1 << rxq->elts_n); 278 const uint16_t q_mask = q_n - 1; 279 uint16_t elts_ci = mlx5_rxq_mprq_enabled(&rxq_ctrl->rxq) ? 280 rxq->elts_ci : rxq->rq_ci; 281 uint16_t used = q_n - (elts_ci - rxq->rq_pi); 282 uint16_t i; 283 284 DRV_LOG(DEBUG, "port %u Rx queue %u freeing %d WRs", 285 PORT_ID(rxq_ctrl->priv), rxq->idx, q_n); 286 if (rxq->elts == NULL) 287 return; 288 /** 289 * Some mbuf in the Ring belongs to the application. 290 * They cannot be freed. 291 */ 292 if (mlx5_rxq_check_vec_support(rxq) > 0) { 293 for (i = 0; i < used; ++i) 294 (*rxq->elts)[(elts_ci + i) & q_mask] = NULL; 295 rxq->rq_pi = elts_ci; 296 } 297 for (i = 0; i != q_n; ++i) { 298 if ((*rxq->elts)[i] != NULL) 299 rte_pktmbuf_free_seg((*rxq->elts)[i]); 300 (*rxq->elts)[i] = NULL; 301 } 302 } 303 304 /** 305 * Free RX queue elements. 306 * 307 * @param rxq_ctrl 308 * Pointer to RX queue structure. 309 */ 310 static void 311 rxq_free_elts(struct mlx5_rxq_ctrl *rxq_ctrl) 312 { 313 /* 314 * For MPRQ we need to allocate both MPRQ buffers 315 * for WQEs and simple mbufs for vector processing. 316 */ 317 if (mlx5_rxq_mprq_enabled(&rxq_ctrl->rxq)) 318 rxq_free_elts_mprq(rxq_ctrl); 319 rxq_free_elts_sprq(rxq_ctrl); 320 } 321 322 /** 323 * Returns the per-queue supported offloads. 324 * 325 * @param dev 326 * Pointer to Ethernet device. 327 * 328 * @return 329 * Supported Rx offloads. 330 */ 331 uint64_t 332 mlx5_get_rx_queue_offloads(struct rte_eth_dev *dev) 333 { 334 struct mlx5_priv *priv = dev->data->dev_private; 335 struct mlx5_dev_config *config = &priv->config; 336 uint64_t offloads = (DEV_RX_OFFLOAD_SCATTER | 337 DEV_RX_OFFLOAD_TIMESTAMP | 338 DEV_RX_OFFLOAD_JUMBO_FRAME | 339 DEV_RX_OFFLOAD_RSS_HASH); 340 341 if (!config->mprq.enabled) 342 offloads |= RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT; 343 if (config->hw_fcs_strip) 344 offloads |= DEV_RX_OFFLOAD_KEEP_CRC; 345 if (config->hw_csum) 346 offloads |= (DEV_RX_OFFLOAD_IPV4_CKSUM | 347 DEV_RX_OFFLOAD_UDP_CKSUM | 348 DEV_RX_OFFLOAD_TCP_CKSUM); 349 if (config->hw_vlan_strip) 350 offloads |= DEV_RX_OFFLOAD_VLAN_STRIP; 351 if (MLX5_LRO_SUPPORTED(dev)) 352 offloads |= DEV_RX_OFFLOAD_TCP_LRO; 353 return offloads; 354 } 355 356 357 /** 358 * Returns the per-port supported offloads. 359 * 360 * @return 361 * Supported Rx offloads. 362 */ 363 uint64_t 364 mlx5_get_rx_port_offloads(void) 365 { 366 uint64_t offloads = DEV_RX_OFFLOAD_VLAN_FILTER; 367 368 return offloads; 369 } 370 371 /** 372 * Verify if the queue can be released. 373 * 374 * @param dev 375 * Pointer to Ethernet device. 376 * @param idx 377 * RX queue index. 378 * 379 * @return 380 * 1 if the queue can be released 381 * 0 if the queue can not be released, there are references to it. 382 * Negative errno and rte_errno is set if queue doesn't exist. 383 */ 384 static int 385 mlx5_rxq_releasable(struct rte_eth_dev *dev, uint16_t idx) 386 { 387 struct mlx5_priv *priv = dev->data->dev_private; 388 struct mlx5_rxq_ctrl *rxq_ctrl; 389 390 if (!(*priv->rxqs)[idx]) { 391 rte_errno = EINVAL; 392 return -rte_errno; 393 } 394 rxq_ctrl = container_of((*priv->rxqs)[idx], struct mlx5_rxq_ctrl, rxq); 395 return (__atomic_load_n(&rxq_ctrl->refcnt, __ATOMIC_RELAXED) == 1); 396 } 397 398 /* Fetches and drops all SW-owned and error CQEs to synchronize CQ. */ 399 static void 400 rxq_sync_cq(struct mlx5_rxq_data *rxq) 401 { 402 const uint16_t cqe_n = 1 << rxq->cqe_n; 403 const uint16_t cqe_mask = cqe_n - 1; 404 volatile struct mlx5_cqe *cqe; 405 int ret, i; 406 407 i = cqe_n; 408 do { 409 cqe = &(*rxq->cqes)[rxq->cq_ci & cqe_mask]; 410 ret = check_cqe(cqe, cqe_n, rxq->cq_ci); 411 if (ret == MLX5_CQE_STATUS_HW_OWN) 412 break; 413 if (ret == MLX5_CQE_STATUS_ERR) { 414 rxq->cq_ci++; 415 continue; 416 } 417 MLX5_ASSERT(ret == MLX5_CQE_STATUS_SW_OWN); 418 if (MLX5_CQE_FORMAT(cqe->op_own) != MLX5_COMPRESSED) { 419 rxq->cq_ci++; 420 continue; 421 } 422 /* Compute the next non compressed CQE. */ 423 rxq->cq_ci += rte_be_to_cpu_32(cqe->byte_cnt); 424 425 } while (--i); 426 /* Move all CQEs to HW ownership, including possible MiniCQEs. */ 427 for (i = 0; i < cqe_n; i++) { 428 cqe = &(*rxq->cqes)[i]; 429 cqe->op_own = MLX5_CQE_INVALIDATE; 430 } 431 /* Resync CQE and WQE (WQ in RESET state). */ 432 rte_io_wmb(); 433 *rxq->cq_db = rte_cpu_to_be_32(rxq->cq_ci); 434 rte_io_wmb(); 435 *rxq->rq_db = rte_cpu_to_be_32(0); 436 rte_io_wmb(); 437 } 438 439 /** 440 * Rx queue stop. Device queue goes to the RESET state, 441 * all involved mbufs are freed from WQ. 442 * 443 * @param dev 444 * Pointer to Ethernet device structure. 445 * @param idx 446 * RX queue index. 447 * 448 * @return 449 * 0 on success, a negative errno value otherwise and rte_errno is set. 450 */ 451 int 452 mlx5_rx_queue_stop_primary(struct rte_eth_dev *dev, uint16_t idx) 453 { 454 struct mlx5_priv *priv = dev->data->dev_private; 455 struct mlx5_rxq_data *rxq = (*priv->rxqs)[idx]; 456 struct mlx5_rxq_ctrl *rxq_ctrl = 457 container_of(rxq, struct mlx5_rxq_ctrl, rxq); 458 int ret; 459 460 MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY); 461 ret = priv->obj_ops.rxq_obj_modify(rxq_ctrl->obj, MLX5_RXQ_MOD_RDY2RST); 462 if (ret) { 463 DRV_LOG(ERR, "Cannot change Rx WQ state to RESET: %s", 464 strerror(errno)); 465 rte_errno = errno; 466 return ret; 467 } 468 /* Remove all processes CQEs. */ 469 rxq_sync_cq(rxq); 470 /* Free all involved mbufs. */ 471 rxq_free_elts(rxq_ctrl); 472 /* Set the actual queue state. */ 473 dev->data->rx_queue_state[idx] = RTE_ETH_QUEUE_STATE_STOPPED; 474 return 0; 475 } 476 477 /** 478 * Rx queue stop. Device queue goes to the RESET state, 479 * all involved mbufs are freed from WQ. 480 * 481 * @param dev 482 * Pointer to Ethernet device structure. 483 * @param idx 484 * RX queue index. 485 * 486 * @return 487 * 0 on success, a negative errno value otherwise and rte_errno is set. 488 */ 489 int 490 mlx5_rx_queue_stop(struct rte_eth_dev *dev, uint16_t idx) 491 { 492 eth_rx_burst_t pkt_burst = dev->rx_pkt_burst; 493 int ret; 494 495 if (rte_eth_dev_is_rx_hairpin_queue(dev, idx)) { 496 DRV_LOG(ERR, "Hairpin queue can't be stopped"); 497 rte_errno = EINVAL; 498 return -EINVAL; 499 } 500 if (dev->data->rx_queue_state[idx] == RTE_ETH_QUEUE_STATE_STOPPED) 501 return 0; 502 /* 503 * Vectorized Rx burst requires the CQ and RQ indices 504 * synchronized, that might be broken on RQ restart 505 * and cause Rx malfunction, so queue stopping is 506 * not supported if vectorized Rx burst is engaged. 507 * The routine pointer depends on the process 508 * type, should perform check there. 509 */ 510 if (pkt_burst == mlx5_rx_burst_vec) { 511 DRV_LOG(ERR, "Rx queue stop is not supported " 512 "for vectorized Rx"); 513 rte_errno = EINVAL; 514 return -EINVAL; 515 } 516 if (rte_eal_process_type() == RTE_PROC_SECONDARY) { 517 ret = mlx5_mp_os_req_queue_control(dev, idx, 518 MLX5_MP_REQ_QUEUE_RX_STOP); 519 } else { 520 ret = mlx5_rx_queue_stop_primary(dev, idx); 521 } 522 return ret; 523 } 524 525 /** 526 * Rx queue start. Device queue goes to the ready state, 527 * all required mbufs are allocated and WQ is replenished. 528 * 529 * @param dev 530 * Pointer to Ethernet device structure. 531 * @param idx 532 * RX queue index. 533 * 534 * @return 535 * 0 on success, a negative errno value otherwise and rte_errno is set. 536 */ 537 int 538 mlx5_rx_queue_start_primary(struct rte_eth_dev *dev, uint16_t idx) 539 { 540 struct mlx5_priv *priv = dev->data->dev_private; 541 struct mlx5_rxq_data *rxq = (*priv->rxqs)[idx]; 542 struct mlx5_rxq_ctrl *rxq_ctrl = 543 container_of(rxq, struct mlx5_rxq_ctrl, rxq); 544 int ret; 545 546 MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY); 547 /* Allocate needed buffers. */ 548 ret = rxq_alloc_elts(rxq_ctrl); 549 if (ret) { 550 DRV_LOG(ERR, "Cannot reallocate buffers for Rx WQ"); 551 rte_errno = errno; 552 return ret; 553 } 554 rte_io_wmb(); 555 *rxq->cq_db = rte_cpu_to_be_32(rxq->cq_ci); 556 rte_io_wmb(); 557 /* Reset RQ consumer before moving queue to READY state. */ 558 *rxq->rq_db = rte_cpu_to_be_32(0); 559 rte_io_wmb(); 560 ret = priv->obj_ops.rxq_obj_modify(rxq_ctrl->obj, MLX5_RXQ_MOD_RST2RDY); 561 if (ret) { 562 DRV_LOG(ERR, "Cannot change Rx WQ state to READY: %s", 563 strerror(errno)); 564 rte_errno = errno; 565 return ret; 566 } 567 /* Reinitialize RQ - set WQEs. */ 568 mlx5_rxq_initialize(rxq); 569 rxq->err_state = MLX5_RXQ_ERR_STATE_NO_ERROR; 570 /* Set actual queue state. */ 571 dev->data->rx_queue_state[idx] = RTE_ETH_QUEUE_STATE_STARTED; 572 return 0; 573 } 574 575 /** 576 * Rx queue start. Device queue goes to the ready state, 577 * all required mbufs are allocated and WQ is replenished. 578 * 579 * @param dev 580 * Pointer to Ethernet device structure. 581 * @param idx 582 * RX queue index. 583 * 584 * @return 585 * 0 on success, a negative errno value otherwise and rte_errno is set. 586 */ 587 int 588 mlx5_rx_queue_start(struct rte_eth_dev *dev, uint16_t idx) 589 { 590 int ret; 591 592 if (rte_eth_dev_is_rx_hairpin_queue(dev, idx)) { 593 DRV_LOG(ERR, "Hairpin queue can't be started"); 594 rte_errno = EINVAL; 595 return -EINVAL; 596 } 597 if (dev->data->rx_queue_state[idx] == RTE_ETH_QUEUE_STATE_STARTED) 598 return 0; 599 if (rte_eal_process_type() == RTE_PROC_SECONDARY) { 600 ret = mlx5_mp_os_req_queue_control(dev, idx, 601 MLX5_MP_REQ_QUEUE_RX_START); 602 } else { 603 ret = mlx5_rx_queue_start_primary(dev, idx); 604 } 605 return ret; 606 } 607 608 /** 609 * Rx queue presetup checks. 610 * 611 * @param dev 612 * Pointer to Ethernet device structure. 613 * @param idx 614 * RX queue index. 615 * @param desc 616 * Number of descriptors to configure in queue. 617 * 618 * @return 619 * 0 on success, a negative errno value otherwise and rte_errno is set. 620 */ 621 static int 622 mlx5_rx_queue_pre_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t *desc) 623 { 624 struct mlx5_priv *priv = dev->data->dev_private; 625 626 if (!rte_is_power_of_2(*desc)) { 627 *desc = 1 << log2above(*desc); 628 DRV_LOG(WARNING, 629 "port %u increased number of descriptors in Rx queue %u" 630 " to the next power of two (%d)", 631 dev->data->port_id, idx, *desc); 632 } 633 DRV_LOG(DEBUG, "port %u configuring Rx queue %u for %u descriptors", 634 dev->data->port_id, idx, *desc); 635 if (idx >= priv->rxqs_n) { 636 DRV_LOG(ERR, "port %u Rx queue index out of range (%u >= %u)", 637 dev->data->port_id, idx, priv->rxqs_n); 638 rte_errno = EOVERFLOW; 639 return -rte_errno; 640 } 641 if (!mlx5_rxq_releasable(dev, idx)) { 642 DRV_LOG(ERR, "port %u unable to release queue index %u", 643 dev->data->port_id, idx); 644 rte_errno = EBUSY; 645 return -rte_errno; 646 } 647 mlx5_rxq_release(dev, idx); 648 return 0; 649 } 650 651 /** 652 * 653 * @param dev 654 * Pointer to Ethernet device structure. 655 * @param idx 656 * RX queue index. 657 * @param desc 658 * Number of descriptors to configure in queue. 659 * @param socket 660 * NUMA socket on which memory must be allocated. 661 * @param[in] conf 662 * Thresholds parameters. 663 * @param mp 664 * Memory pool for buffer allocations. 665 * 666 * @return 667 * 0 on success, a negative errno value otherwise and rte_errno is set. 668 */ 669 int 670 mlx5_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, 671 unsigned int socket, const struct rte_eth_rxconf *conf, 672 struct rte_mempool *mp) 673 { 674 struct mlx5_priv *priv = dev->data->dev_private; 675 struct mlx5_rxq_data *rxq = (*priv->rxqs)[idx]; 676 struct mlx5_rxq_ctrl *rxq_ctrl = 677 container_of(rxq, struct mlx5_rxq_ctrl, rxq); 678 struct rte_eth_rxseg_split *rx_seg = 679 (struct rte_eth_rxseg_split *)conf->rx_seg; 680 struct rte_eth_rxseg_split rx_single = {.mp = mp}; 681 uint16_t n_seg = conf->rx_nseg; 682 int res; 683 684 if (mp) { 685 /* 686 * The parameters should be checked on rte_eth_dev layer. 687 * If mp is specified it means the compatible configuration 688 * without buffer split feature tuning. 689 */ 690 rx_seg = &rx_single; 691 n_seg = 1; 692 } 693 if (n_seg > 1) { 694 uint64_t offloads = conf->offloads | 695 dev->data->dev_conf.rxmode.offloads; 696 697 /* The offloads should be checked on rte_eth_dev layer. */ 698 MLX5_ASSERT(offloads & DEV_RX_OFFLOAD_SCATTER); 699 if (!(offloads & RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT)) { 700 DRV_LOG(ERR, "port %u queue index %u split " 701 "offload not configured", 702 dev->data->port_id, idx); 703 rte_errno = ENOSPC; 704 return -rte_errno; 705 } 706 MLX5_ASSERT(n_seg < MLX5_MAX_RXQ_NSEG); 707 } 708 res = mlx5_rx_queue_pre_setup(dev, idx, &desc); 709 if (res) 710 return res; 711 rxq_ctrl = mlx5_rxq_new(dev, idx, desc, socket, conf, rx_seg, n_seg); 712 if (!rxq_ctrl) { 713 DRV_LOG(ERR, "port %u unable to allocate queue index %u", 714 dev->data->port_id, idx); 715 rte_errno = ENOMEM; 716 return -rte_errno; 717 } 718 DRV_LOG(DEBUG, "port %u adding Rx queue %u to list", 719 dev->data->port_id, idx); 720 (*priv->rxqs)[idx] = &rxq_ctrl->rxq; 721 return 0; 722 } 723 724 /** 725 * 726 * @param dev 727 * Pointer to Ethernet device structure. 728 * @param idx 729 * RX queue index. 730 * @param desc 731 * Number of descriptors to configure in queue. 732 * @param hairpin_conf 733 * Hairpin configuration parameters. 734 * 735 * @return 736 * 0 on success, a negative errno value otherwise and rte_errno is set. 737 */ 738 int 739 mlx5_rx_hairpin_queue_setup(struct rte_eth_dev *dev, uint16_t idx, 740 uint16_t desc, 741 const struct rte_eth_hairpin_conf *hairpin_conf) 742 { 743 struct mlx5_priv *priv = dev->data->dev_private; 744 struct mlx5_rxq_data *rxq = (*priv->rxqs)[idx]; 745 struct mlx5_rxq_ctrl *rxq_ctrl = 746 container_of(rxq, struct mlx5_rxq_ctrl, rxq); 747 int res; 748 749 res = mlx5_rx_queue_pre_setup(dev, idx, &desc); 750 if (res) 751 return res; 752 if (hairpin_conf->peer_count != 1) { 753 rte_errno = EINVAL; 754 DRV_LOG(ERR, "port %u unable to setup Rx hairpin queue index %u" 755 " peer count is %u", dev->data->port_id, 756 idx, hairpin_conf->peer_count); 757 return -rte_errno; 758 } 759 if (hairpin_conf->peers[0].port == dev->data->port_id) { 760 if (hairpin_conf->peers[0].queue >= priv->txqs_n) { 761 rte_errno = EINVAL; 762 DRV_LOG(ERR, "port %u unable to setup Rx hairpin queue" 763 " index %u, Tx %u is larger than %u", 764 dev->data->port_id, idx, 765 hairpin_conf->peers[0].queue, priv->txqs_n); 766 return -rte_errno; 767 } 768 } else { 769 if (hairpin_conf->manual_bind == 0 || 770 hairpin_conf->tx_explicit == 0) { 771 rte_errno = EINVAL; 772 DRV_LOG(ERR, "port %u unable to setup Rx hairpin queue" 773 " index %u peer port %u with attributes %u %u", 774 dev->data->port_id, idx, 775 hairpin_conf->peers[0].port, 776 hairpin_conf->manual_bind, 777 hairpin_conf->tx_explicit); 778 return -rte_errno; 779 } 780 } 781 rxq_ctrl = mlx5_rxq_hairpin_new(dev, idx, desc, hairpin_conf); 782 if (!rxq_ctrl) { 783 DRV_LOG(ERR, "port %u unable to allocate queue index %u", 784 dev->data->port_id, idx); 785 rte_errno = ENOMEM; 786 return -rte_errno; 787 } 788 DRV_LOG(DEBUG, "port %u adding Rx queue %u to list", 789 dev->data->port_id, idx); 790 (*priv->rxqs)[idx] = &rxq_ctrl->rxq; 791 return 0; 792 } 793 794 /** 795 * DPDK callback to release a RX queue. 796 * 797 * @param dev 798 * Pointer to Ethernet device structure. 799 * @param qid 800 * Receive queue index. 801 */ 802 void 803 mlx5_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid) 804 { 805 struct mlx5_rxq_data *rxq = dev->data->rx_queues[qid]; 806 807 if (rxq == NULL) 808 return; 809 if (!mlx5_rxq_releasable(dev, qid)) 810 rte_panic("port %u Rx queue %u is still used by a flow and" 811 " cannot be removed\n", dev->data->port_id, qid); 812 mlx5_rxq_release(dev, qid); 813 } 814 815 /** 816 * Allocate queue vector and fill epoll fd list for Rx interrupts. 817 * 818 * @param dev 819 * Pointer to Ethernet device. 820 * 821 * @return 822 * 0 on success, a negative errno value otherwise and rte_errno is set. 823 */ 824 int 825 mlx5_rx_intr_vec_enable(struct rte_eth_dev *dev) 826 { 827 struct mlx5_priv *priv = dev->data->dev_private; 828 unsigned int i; 829 unsigned int rxqs_n = priv->rxqs_n; 830 unsigned int n = RTE_MIN(rxqs_n, (uint32_t)RTE_MAX_RXTX_INTR_VEC_ID); 831 unsigned int count = 0; 832 struct rte_intr_handle *intr_handle = dev->intr_handle; 833 834 if (!dev->data->dev_conf.intr_conf.rxq) 835 return 0; 836 mlx5_rx_intr_vec_disable(dev); 837 intr_handle->intr_vec = mlx5_malloc(0, 838 n * sizeof(intr_handle->intr_vec[0]), 839 0, SOCKET_ID_ANY); 840 if (intr_handle->intr_vec == NULL) { 841 DRV_LOG(ERR, 842 "port %u failed to allocate memory for interrupt" 843 " vector, Rx interrupts will not be supported", 844 dev->data->port_id); 845 rte_errno = ENOMEM; 846 return -rte_errno; 847 } 848 intr_handle->type = RTE_INTR_HANDLE_EXT; 849 for (i = 0; i != n; ++i) { 850 /* This rxq obj must not be released in this function. */ 851 struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_rxq_get(dev, i); 852 struct mlx5_rxq_obj *rxq_obj = rxq_ctrl ? rxq_ctrl->obj : NULL; 853 int rc; 854 855 /* Skip queues that cannot request interrupts. */ 856 if (!rxq_obj || (!rxq_obj->ibv_channel && 857 !rxq_obj->devx_channel)) { 858 /* Use invalid intr_vec[] index to disable entry. */ 859 intr_handle->intr_vec[i] = 860 RTE_INTR_VEC_RXTX_OFFSET + 861 RTE_MAX_RXTX_INTR_VEC_ID; 862 /* Decrease the rxq_ctrl's refcnt */ 863 if (rxq_ctrl) 864 mlx5_rxq_release(dev, i); 865 continue; 866 } 867 if (count >= RTE_MAX_RXTX_INTR_VEC_ID) { 868 DRV_LOG(ERR, 869 "port %u too many Rx queues for interrupt" 870 " vector size (%d), Rx interrupts cannot be" 871 " enabled", 872 dev->data->port_id, RTE_MAX_RXTX_INTR_VEC_ID); 873 mlx5_rx_intr_vec_disable(dev); 874 rte_errno = ENOMEM; 875 return -rte_errno; 876 } 877 rc = mlx5_os_set_nonblock_channel_fd(rxq_obj->fd); 878 if (rc < 0) { 879 rte_errno = errno; 880 DRV_LOG(ERR, 881 "port %u failed to make Rx interrupt file" 882 " descriptor %d non-blocking for queue index" 883 " %d", 884 dev->data->port_id, rxq_obj->fd, i); 885 mlx5_rx_intr_vec_disable(dev); 886 return -rte_errno; 887 } 888 intr_handle->intr_vec[i] = RTE_INTR_VEC_RXTX_OFFSET + count; 889 intr_handle->efds[count] = rxq_obj->fd; 890 count++; 891 } 892 if (!count) 893 mlx5_rx_intr_vec_disable(dev); 894 else 895 intr_handle->nb_efd = count; 896 return 0; 897 } 898 899 /** 900 * Clean up Rx interrupts handler. 901 * 902 * @param dev 903 * Pointer to Ethernet device. 904 */ 905 void 906 mlx5_rx_intr_vec_disable(struct rte_eth_dev *dev) 907 { 908 struct mlx5_priv *priv = dev->data->dev_private; 909 struct rte_intr_handle *intr_handle = dev->intr_handle; 910 unsigned int i; 911 unsigned int rxqs_n = priv->rxqs_n; 912 unsigned int n = RTE_MIN(rxqs_n, (uint32_t)RTE_MAX_RXTX_INTR_VEC_ID); 913 914 if (!dev->data->dev_conf.intr_conf.rxq) 915 return; 916 if (!intr_handle->intr_vec) 917 goto free; 918 for (i = 0; i != n; ++i) { 919 if (intr_handle->intr_vec[i] == RTE_INTR_VEC_RXTX_OFFSET + 920 RTE_MAX_RXTX_INTR_VEC_ID) 921 continue; 922 /** 923 * Need to access directly the queue to release the reference 924 * kept in mlx5_rx_intr_vec_enable(). 925 */ 926 mlx5_rxq_release(dev, i); 927 } 928 free: 929 rte_intr_free_epoll_fd(intr_handle); 930 if (intr_handle->intr_vec) 931 mlx5_free(intr_handle->intr_vec); 932 intr_handle->nb_efd = 0; 933 intr_handle->intr_vec = NULL; 934 } 935 936 /** 937 * MLX5 CQ notification . 938 * 939 * @param rxq 940 * Pointer to receive queue structure. 941 * @param sq_n_rxq 942 * Sequence number per receive queue . 943 */ 944 static inline void 945 mlx5_arm_cq(struct mlx5_rxq_data *rxq, int sq_n_rxq) 946 { 947 int sq_n = 0; 948 uint32_t doorbell_hi; 949 uint64_t doorbell; 950 void *cq_db_reg = (char *)rxq->cq_uar + MLX5_CQ_DOORBELL; 951 952 sq_n = sq_n_rxq & MLX5_CQ_SQN_MASK; 953 doorbell_hi = sq_n << MLX5_CQ_SQN_OFFSET | (rxq->cq_ci & MLX5_CI_MASK); 954 doorbell = (uint64_t)doorbell_hi << 32; 955 doorbell |= rxq->cqn; 956 rxq->cq_db[MLX5_CQ_ARM_DB] = rte_cpu_to_be_32(doorbell_hi); 957 mlx5_uar_write64(rte_cpu_to_be_64(doorbell), 958 cq_db_reg, rxq->uar_lock_cq); 959 } 960 961 /** 962 * DPDK callback for Rx queue interrupt enable. 963 * 964 * @param dev 965 * Pointer to Ethernet device structure. 966 * @param rx_queue_id 967 * Rx queue number. 968 * 969 * @return 970 * 0 on success, a negative errno value otherwise and rte_errno is set. 971 */ 972 int 973 mlx5_rx_intr_enable(struct rte_eth_dev *dev, uint16_t rx_queue_id) 974 { 975 struct mlx5_rxq_ctrl *rxq_ctrl; 976 977 rxq_ctrl = mlx5_rxq_get(dev, rx_queue_id); 978 if (!rxq_ctrl) 979 goto error; 980 if (rxq_ctrl->irq) { 981 if (!rxq_ctrl->obj) { 982 mlx5_rxq_release(dev, rx_queue_id); 983 goto error; 984 } 985 mlx5_arm_cq(&rxq_ctrl->rxq, rxq_ctrl->rxq.cq_arm_sn); 986 } 987 mlx5_rxq_release(dev, rx_queue_id); 988 return 0; 989 error: 990 rte_errno = EINVAL; 991 return -rte_errno; 992 } 993 994 /** 995 * DPDK callback for Rx queue interrupt disable. 996 * 997 * @param dev 998 * Pointer to Ethernet device structure. 999 * @param rx_queue_id 1000 * Rx queue number. 1001 * 1002 * @return 1003 * 0 on success, a negative errno value otherwise and rte_errno is set. 1004 */ 1005 int 1006 mlx5_rx_intr_disable(struct rte_eth_dev *dev, uint16_t rx_queue_id) 1007 { 1008 struct mlx5_priv *priv = dev->data->dev_private; 1009 struct mlx5_rxq_ctrl *rxq_ctrl; 1010 int ret = 0; 1011 1012 rxq_ctrl = mlx5_rxq_get(dev, rx_queue_id); 1013 if (!rxq_ctrl) { 1014 rte_errno = EINVAL; 1015 return -rte_errno; 1016 } 1017 if (!rxq_ctrl->obj) 1018 goto error; 1019 if (rxq_ctrl->irq) { 1020 ret = priv->obj_ops.rxq_event_get(rxq_ctrl->obj); 1021 if (ret < 0) 1022 goto error; 1023 rxq_ctrl->rxq.cq_arm_sn++; 1024 } 1025 mlx5_rxq_release(dev, rx_queue_id); 1026 return 0; 1027 error: 1028 /** 1029 * The ret variable may be EAGAIN which means the get_event function was 1030 * called before receiving one. 1031 */ 1032 if (ret < 0) 1033 rte_errno = errno; 1034 else 1035 rte_errno = EINVAL; 1036 ret = rte_errno; /* Save rte_errno before cleanup. */ 1037 mlx5_rxq_release(dev, rx_queue_id); 1038 if (ret != EAGAIN) 1039 DRV_LOG(WARNING, "port %u unable to disable interrupt on Rx queue %d", 1040 dev->data->port_id, rx_queue_id); 1041 rte_errno = ret; /* Restore rte_errno. */ 1042 return -rte_errno; 1043 } 1044 1045 /** 1046 * Verify the Rx queue objects list is empty 1047 * 1048 * @param dev 1049 * Pointer to Ethernet device. 1050 * 1051 * @return 1052 * The number of objects not released. 1053 */ 1054 int 1055 mlx5_rxq_obj_verify(struct rte_eth_dev *dev) 1056 { 1057 struct mlx5_priv *priv = dev->data->dev_private; 1058 int ret = 0; 1059 struct mlx5_rxq_obj *rxq_obj; 1060 1061 LIST_FOREACH(rxq_obj, &priv->rxqsobj, next) { 1062 DRV_LOG(DEBUG, "port %u Rx queue %u still referenced", 1063 dev->data->port_id, rxq_obj->rxq_ctrl->rxq.idx); 1064 ++ret; 1065 } 1066 return ret; 1067 } 1068 1069 /** 1070 * Callback function to initialize mbufs for Multi-Packet RQ. 1071 */ 1072 static inline void 1073 mlx5_mprq_buf_init(struct rte_mempool *mp, void *opaque_arg, 1074 void *_m, unsigned int i __rte_unused) 1075 { 1076 struct mlx5_mprq_buf *buf = _m; 1077 struct rte_mbuf_ext_shared_info *shinfo; 1078 unsigned int strd_n = (unsigned int)(uintptr_t)opaque_arg; 1079 unsigned int j; 1080 1081 memset(_m, 0, sizeof(*buf)); 1082 buf->mp = mp; 1083 __atomic_store_n(&buf->refcnt, 1, __ATOMIC_RELAXED); 1084 for (j = 0; j != strd_n; ++j) { 1085 shinfo = &buf->shinfos[j]; 1086 shinfo->free_cb = mlx5_mprq_buf_free_cb; 1087 shinfo->fcb_opaque = buf; 1088 } 1089 } 1090 1091 /** 1092 * Free mempool of Multi-Packet RQ. 1093 * 1094 * @param dev 1095 * Pointer to Ethernet device. 1096 * 1097 * @return 1098 * 0 on success, negative errno value on failure. 1099 */ 1100 int 1101 mlx5_mprq_free_mp(struct rte_eth_dev *dev) 1102 { 1103 struct mlx5_priv *priv = dev->data->dev_private; 1104 struct rte_mempool *mp = priv->mprq_mp; 1105 unsigned int i; 1106 1107 if (mp == NULL) 1108 return 0; 1109 DRV_LOG(DEBUG, "port %u freeing mempool (%s) for Multi-Packet RQ", 1110 dev->data->port_id, mp->name); 1111 /* 1112 * If a buffer in the pool has been externally attached to a mbuf and it 1113 * is still in use by application, destroying the Rx queue can spoil 1114 * the packet. It is unlikely to happen but if application dynamically 1115 * creates and destroys with holding Rx packets, this can happen. 1116 * 1117 * TODO: It is unavoidable for now because the mempool for Multi-Packet 1118 * RQ isn't provided by application but managed by PMD. 1119 */ 1120 if (!rte_mempool_full(mp)) { 1121 DRV_LOG(ERR, 1122 "port %u mempool for Multi-Packet RQ is still in use", 1123 dev->data->port_id); 1124 rte_errno = EBUSY; 1125 return -rte_errno; 1126 } 1127 rte_mempool_free(mp); 1128 /* Unset mempool for each Rx queue. */ 1129 for (i = 0; i != priv->rxqs_n; ++i) { 1130 struct mlx5_rxq_data *rxq = (*priv->rxqs)[i]; 1131 1132 if (rxq == NULL) 1133 continue; 1134 rxq->mprq_mp = NULL; 1135 } 1136 priv->mprq_mp = NULL; 1137 return 0; 1138 } 1139 1140 /** 1141 * Allocate a mempool for Multi-Packet RQ. All configured Rx queues share the 1142 * mempool. If already allocated, reuse it if there're enough elements. 1143 * Otherwise, resize it. 1144 * 1145 * @param dev 1146 * Pointer to Ethernet device. 1147 * 1148 * @return 1149 * 0 on success, negative errno value on failure. 1150 */ 1151 int 1152 mlx5_mprq_alloc_mp(struct rte_eth_dev *dev) 1153 { 1154 struct mlx5_priv *priv = dev->data->dev_private; 1155 struct rte_mempool *mp = priv->mprq_mp; 1156 char name[RTE_MEMPOOL_NAMESIZE]; 1157 unsigned int desc = 0; 1158 unsigned int buf_len; 1159 unsigned int obj_num; 1160 unsigned int obj_size; 1161 unsigned int strd_num_n = 0; 1162 unsigned int strd_sz_n = 0; 1163 unsigned int i; 1164 unsigned int n_ibv = 0; 1165 1166 if (!mlx5_mprq_enabled(dev)) 1167 return 0; 1168 /* Count the total number of descriptors configured. */ 1169 for (i = 0; i != priv->rxqs_n; ++i) { 1170 struct mlx5_rxq_data *rxq = (*priv->rxqs)[i]; 1171 struct mlx5_rxq_ctrl *rxq_ctrl = container_of 1172 (rxq, struct mlx5_rxq_ctrl, rxq); 1173 1174 if (rxq == NULL || rxq_ctrl->type != MLX5_RXQ_TYPE_STANDARD) 1175 continue; 1176 n_ibv++; 1177 desc += 1 << rxq->elts_n; 1178 /* Get the max number of strides. */ 1179 if (strd_num_n < rxq->strd_num_n) 1180 strd_num_n = rxq->strd_num_n; 1181 /* Get the max size of a stride. */ 1182 if (strd_sz_n < rxq->strd_sz_n) 1183 strd_sz_n = rxq->strd_sz_n; 1184 } 1185 MLX5_ASSERT(strd_num_n && strd_sz_n); 1186 buf_len = (1 << strd_num_n) * (1 << strd_sz_n); 1187 obj_size = sizeof(struct mlx5_mprq_buf) + buf_len + (1 << strd_num_n) * 1188 sizeof(struct rte_mbuf_ext_shared_info) + RTE_PKTMBUF_HEADROOM; 1189 /* 1190 * Received packets can be either memcpy'd or externally referenced. In 1191 * case that the packet is attached to an mbuf as an external buffer, as 1192 * it isn't possible to predict how the buffers will be queued by 1193 * application, there's no option to exactly pre-allocate needed buffers 1194 * in advance but to speculatively prepares enough buffers. 1195 * 1196 * In the data path, if this Mempool is depleted, PMD will try to memcpy 1197 * received packets to buffers provided by application (rxq->mp) until 1198 * this Mempool gets available again. 1199 */ 1200 desc *= 4; 1201 obj_num = desc + MLX5_MPRQ_MP_CACHE_SZ * n_ibv; 1202 /* 1203 * rte_mempool_create_empty() has sanity check to refuse large cache 1204 * size compared to the number of elements. 1205 * CACHE_FLUSHTHRESH_MULTIPLIER is defined in a C file, so using a 1206 * constant number 2 instead. 1207 */ 1208 obj_num = RTE_MAX(obj_num, MLX5_MPRQ_MP_CACHE_SZ * 2); 1209 /* Check a mempool is already allocated and if it can be resued. */ 1210 if (mp != NULL && mp->elt_size >= obj_size && mp->size >= obj_num) { 1211 DRV_LOG(DEBUG, "port %u mempool %s is being reused", 1212 dev->data->port_id, mp->name); 1213 /* Reuse. */ 1214 goto exit; 1215 } else if (mp != NULL) { 1216 DRV_LOG(DEBUG, "port %u mempool %s should be resized, freeing it", 1217 dev->data->port_id, mp->name); 1218 /* 1219 * If failed to free, which means it may be still in use, no way 1220 * but to keep using the existing one. On buffer underrun, 1221 * packets will be memcpy'd instead of external buffer 1222 * attachment. 1223 */ 1224 if (mlx5_mprq_free_mp(dev)) { 1225 if (mp->elt_size >= obj_size) 1226 goto exit; 1227 else 1228 return -rte_errno; 1229 } 1230 } 1231 snprintf(name, sizeof(name), "port-%u-mprq", dev->data->port_id); 1232 mp = rte_mempool_create(name, obj_num, obj_size, MLX5_MPRQ_MP_CACHE_SZ, 1233 0, NULL, NULL, mlx5_mprq_buf_init, 1234 (void *)((uintptr_t)1 << strd_num_n), 1235 dev->device->numa_node, 0); 1236 if (mp == NULL) { 1237 DRV_LOG(ERR, 1238 "port %u failed to allocate a mempool for" 1239 " Multi-Packet RQ, count=%u, size=%u", 1240 dev->data->port_id, obj_num, obj_size); 1241 rte_errno = ENOMEM; 1242 return -rte_errno; 1243 } 1244 priv->mprq_mp = mp; 1245 exit: 1246 /* Set mempool for each Rx queue. */ 1247 for (i = 0; i != priv->rxqs_n; ++i) { 1248 struct mlx5_rxq_data *rxq = (*priv->rxqs)[i]; 1249 struct mlx5_rxq_ctrl *rxq_ctrl = container_of 1250 (rxq, struct mlx5_rxq_ctrl, rxq); 1251 1252 if (rxq == NULL || rxq_ctrl->type != MLX5_RXQ_TYPE_STANDARD) 1253 continue; 1254 rxq->mprq_mp = mp; 1255 } 1256 DRV_LOG(INFO, "port %u Multi-Packet RQ is configured", 1257 dev->data->port_id); 1258 return 0; 1259 } 1260 1261 #define MLX5_MAX_TCP_HDR_OFFSET ((unsigned int)(sizeof(struct rte_ether_hdr) + \ 1262 sizeof(struct rte_vlan_hdr) * 2 + \ 1263 sizeof(struct rte_ipv6_hdr))) 1264 #define MAX_TCP_OPTION_SIZE 40u 1265 #define MLX5_MAX_LRO_HEADER_FIX ((unsigned int)(MLX5_MAX_TCP_HDR_OFFSET + \ 1266 sizeof(struct rte_tcp_hdr) + \ 1267 MAX_TCP_OPTION_SIZE)) 1268 1269 /** 1270 * Adjust the maximum LRO massage size. 1271 * 1272 * @param dev 1273 * Pointer to Ethernet device. 1274 * @param idx 1275 * RX queue index. 1276 * @param max_lro_size 1277 * The maximum size for LRO packet. 1278 */ 1279 static void 1280 mlx5_max_lro_msg_size_adjust(struct rte_eth_dev *dev, uint16_t idx, 1281 uint32_t max_lro_size) 1282 { 1283 struct mlx5_priv *priv = dev->data->dev_private; 1284 1285 if (priv->config.hca_attr.lro_max_msg_sz_mode == 1286 MLX5_LRO_MAX_MSG_SIZE_START_FROM_L4 && max_lro_size > 1287 MLX5_MAX_TCP_HDR_OFFSET) 1288 max_lro_size -= MLX5_MAX_TCP_HDR_OFFSET; 1289 max_lro_size = RTE_MIN(max_lro_size, MLX5_MAX_LRO_SIZE); 1290 MLX5_ASSERT(max_lro_size >= MLX5_LRO_SEG_CHUNK_SIZE); 1291 max_lro_size /= MLX5_LRO_SEG_CHUNK_SIZE; 1292 if (priv->max_lro_msg_size) 1293 priv->max_lro_msg_size = 1294 RTE_MIN((uint32_t)priv->max_lro_msg_size, max_lro_size); 1295 else 1296 priv->max_lro_msg_size = max_lro_size; 1297 DRV_LOG(DEBUG, 1298 "port %u Rx Queue %u max LRO message size adjusted to %u bytes", 1299 dev->data->port_id, idx, 1300 priv->max_lro_msg_size * MLX5_LRO_SEG_CHUNK_SIZE); 1301 } 1302 1303 /** 1304 * Create a DPDK Rx queue. 1305 * 1306 * @param dev 1307 * Pointer to Ethernet device. 1308 * @param idx 1309 * RX queue index. 1310 * @param desc 1311 * Number of descriptors to configure in queue. 1312 * @param socket 1313 * NUMA socket on which memory must be allocated. 1314 * 1315 * @return 1316 * A DPDK queue object on success, NULL otherwise and rte_errno is set. 1317 */ 1318 struct mlx5_rxq_ctrl * 1319 mlx5_rxq_new(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, 1320 unsigned int socket, const struct rte_eth_rxconf *conf, 1321 const struct rte_eth_rxseg_split *rx_seg, uint16_t n_seg) 1322 { 1323 struct mlx5_priv *priv = dev->data->dev_private; 1324 struct mlx5_rxq_ctrl *tmpl; 1325 unsigned int mb_len = rte_pktmbuf_data_room_size(rx_seg[0].mp); 1326 struct mlx5_dev_config *config = &priv->config; 1327 uint64_t offloads = conf->offloads | 1328 dev->data->dev_conf.rxmode.offloads; 1329 unsigned int lro_on_queue = !!(offloads & DEV_RX_OFFLOAD_TCP_LRO); 1330 unsigned int max_rx_pkt_len = lro_on_queue ? 1331 dev->data->dev_conf.rxmode.max_lro_pkt_size : 1332 dev->data->dev_conf.rxmode.max_rx_pkt_len; 1333 unsigned int non_scatter_min_mbuf_size = max_rx_pkt_len + 1334 RTE_PKTMBUF_HEADROOM; 1335 unsigned int max_lro_size = 0; 1336 unsigned int first_mb_free_size = mb_len - RTE_PKTMBUF_HEADROOM; 1337 const int mprq_en = mlx5_check_mprq_support(dev) > 0 && n_seg == 1 && 1338 !rx_seg[0].offset && !rx_seg[0].length; 1339 unsigned int mprq_stride_nums = config->mprq.stride_num_n ? 1340 config->mprq.stride_num_n : MLX5_MPRQ_STRIDE_NUM_N; 1341 unsigned int mprq_stride_size = non_scatter_min_mbuf_size <= 1342 (1U << config->mprq.max_stride_size_n) ? 1343 log2above(non_scatter_min_mbuf_size) : MLX5_MPRQ_STRIDE_SIZE_N; 1344 unsigned int mprq_stride_cap = (config->mprq.stride_num_n ? 1345 (1U << config->mprq.stride_num_n) : (1U << mprq_stride_nums)) * 1346 (config->mprq.stride_size_n ? 1347 (1U << config->mprq.stride_size_n) : (1U << mprq_stride_size)); 1348 /* 1349 * Always allocate extra slots, even if eventually 1350 * the vector Rx will not be used. 1351 */ 1352 uint16_t desc_n = desc + config->rx_vec_en * MLX5_VPMD_DESCS_PER_LOOP; 1353 const struct rte_eth_rxseg_split *qs_seg = rx_seg; 1354 unsigned int tail_len; 1355 1356 tmpl = mlx5_malloc(MLX5_MEM_RTE | MLX5_MEM_ZERO, 1357 sizeof(*tmpl) + desc_n * sizeof(struct rte_mbuf *) + 1358 (!!mprq_en) * 1359 (desc >> mprq_stride_nums) * sizeof(struct mlx5_mprq_buf *), 1360 0, socket); 1361 if (!tmpl) { 1362 rte_errno = ENOMEM; 1363 return NULL; 1364 } 1365 MLX5_ASSERT(n_seg && n_seg <= MLX5_MAX_RXQ_NSEG); 1366 /* 1367 * Build the array of actual buffer offsets and lengths. 1368 * Pad with the buffers from the last memory pool if 1369 * needed to handle max size packets, replace zero length 1370 * with the buffer length from the pool. 1371 */ 1372 tail_len = max_rx_pkt_len; 1373 do { 1374 struct mlx5_eth_rxseg *hw_seg = 1375 &tmpl->rxq.rxseg[tmpl->rxq.rxseg_n]; 1376 uint32_t buf_len, offset, seg_len; 1377 1378 /* 1379 * For the buffers beyond descriptions offset is zero, 1380 * the first buffer contains head room. 1381 */ 1382 buf_len = rte_pktmbuf_data_room_size(qs_seg->mp); 1383 offset = (tmpl->rxq.rxseg_n >= n_seg ? 0 : qs_seg->offset) + 1384 (tmpl->rxq.rxseg_n ? 0 : RTE_PKTMBUF_HEADROOM); 1385 /* 1386 * For the buffers beyond descriptions the length is 1387 * pool buffer length, zero lengths are replaced with 1388 * pool buffer length either. 1389 */ 1390 seg_len = tmpl->rxq.rxseg_n >= n_seg ? buf_len : 1391 qs_seg->length ? 1392 qs_seg->length : 1393 (buf_len - offset); 1394 /* Check is done in long int, now overflows. */ 1395 if (buf_len < seg_len + offset) { 1396 DRV_LOG(ERR, "port %u Rx queue %u: Split offset/length " 1397 "%u/%u can't be satisfied", 1398 dev->data->port_id, idx, 1399 qs_seg->length, qs_seg->offset); 1400 rte_errno = EINVAL; 1401 goto error; 1402 } 1403 if (seg_len > tail_len) 1404 seg_len = buf_len - offset; 1405 if (++tmpl->rxq.rxseg_n > MLX5_MAX_RXQ_NSEG) { 1406 DRV_LOG(ERR, 1407 "port %u too many SGEs (%u) needed to handle" 1408 " requested maximum packet size %u, the maximum" 1409 " supported are %u", dev->data->port_id, 1410 tmpl->rxq.rxseg_n, max_rx_pkt_len, 1411 MLX5_MAX_RXQ_NSEG); 1412 rte_errno = ENOTSUP; 1413 goto error; 1414 } 1415 /* Build the actual scattering element in the queue object. */ 1416 hw_seg->mp = qs_seg->mp; 1417 MLX5_ASSERT(offset <= UINT16_MAX); 1418 MLX5_ASSERT(seg_len <= UINT16_MAX); 1419 hw_seg->offset = (uint16_t)offset; 1420 hw_seg->length = (uint16_t)seg_len; 1421 /* 1422 * Advance the segment descriptor, the padding is the based 1423 * on the attributes of the last descriptor. 1424 */ 1425 if (tmpl->rxq.rxseg_n < n_seg) 1426 qs_seg++; 1427 tail_len -= RTE_MIN(tail_len, seg_len); 1428 } while (tail_len || !rte_is_power_of_2(tmpl->rxq.rxseg_n)); 1429 MLX5_ASSERT(tmpl->rxq.rxseg_n && 1430 tmpl->rxq.rxseg_n <= MLX5_MAX_RXQ_NSEG); 1431 if (tmpl->rxq.rxseg_n > 1 && !(offloads & DEV_RX_OFFLOAD_SCATTER)) { 1432 DRV_LOG(ERR, "port %u Rx queue %u: Scatter offload is not" 1433 " configured and no enough mbuf space(%u) to contain " 1434 "the maximum RX packet length(%u) with head-room(%u)", 1435 dev->data->port_id, idx, mb_len, max_rx_pkt_len, 1436 RTE_PKTMBUF_HEADROOM); 1437 rte_errno = ENOSPC; 1438 goto error; 1439 } 1440 tmpl->type = MLX5_RXQ_TYPE_STANDARD; 1441 if (mlx5_mr_btree_init(&tmpl->rxq.mr_ctrl.cache_bh, 1442 MLX5_MR_BTREE_CACHE_N, socket)) { 1443 /* rte_errno is already set. */ 1444 goto error; 1445 } 1446 tmpl->socket = socket; 1447 if (dev->data->dev_conf.intr_conf.rxq) 1448 tmpl->irq = 1; 1449 /* 1450 * This Rx queue can be configured as a Multi-Packet RQ if all of the 1451 * following conditions are met: 1452 * - MPRQ is enabled. 1453 * - The number of descs is more than the number of strides. 1454 * - max_rx_pkt_len plus overhead is less than the max size 1455 * of a stride or mprq_stride_size is specified by a user. 1456 * Need to make sure that there are enough strides to encap 1457 * the maximum packet size in case mprq_stride_size is set. 1458 * Otherwise, enable Rx scatter if necessary. 1459 */ 1460 if (mprq_en && desc > (1U << mprq_stride_nums) && 1461 (non_scatter_min_mbuf_size <= 1462 (1U << config->mprq.max_stride_size_n) || 1463 (config->mprq.stride_size_n && 1464 non_scatter_min_mbuf_size <= mprq_stride_cap))) { 1465 /* TODO: Rx scatter isn't supported yet. */ 1466 tmpl->rxq.sges_n = 0; 1467 /* Trim the number of descs needed. */ 1468 desc >>= mprq_stride_nums; 1469 tmpl->rxq.strd_num_n = config->mprq.stride_num_n ? 1470 config->mprq.stride_num_n : mprq_stride_nums; 1471 tmpl->rxq.strd_sz_n = config->mprq.stride_size_n ? 1472 config->mprq.stride_size_n : mprq_stride_size; 1473 tmpl->rxq.strd_shift_en = MLX5_MPRQ_TWO_BYTE_SHIFT; 1474 tmpl->rxq.strd_scatter_en = 1475 !!(offloads & DEV_RX_OFFLOAD_SCATTER); 1476 tmpl->rxq.mprq_max_memcpy_len = RTE_MIN(first_mb_free_size, 1477 config->mprq.max_memcpy_len); 1478 max_lro_size = RTE_MIN(max_rx_pkt_len, 1479 (1u << tmpl->rxq.strd_num_n) * 1480 (1u << tmpl->rxq.strd_sz_n)); 1481 DRV_LOG(DEBUG, 1482 "port %u Rx queue %u: Multi-Packet RQ is enabled" 1483 " strd_num_n = %u, strd_sz_n = %u", 1484 dev->data->port_id, idx, 1485 tmpl->rxq.strd_num_n, tmpl->rxq.strd_sz_n); 1486 } else if (tmpl->rxq.rxseg_n == 1) { 1487 MLX5_ASSERT(max_rx_pkt_len <= first_mb_free_size); 1488 tmpl->rxq.sges_n = 0; 1489 max_lro_size = max_rx_pkt_len; 1490 } else if (offloads & DEV_RX_OFFLOAD_SCATTER) { 1491 unsigned int sges_n; 1492 1493 if (lro_on_queue && first_mb_free_size < 1494 MLX5_MAX_LRO_HEADER_FIX) { 1495 DRV_LOG(ERR, "Not enough space in the first segment(%u)" 1496 " to include the max header size(%u) for LRO", 1497 first_mb_free_size, MLX5_MAX_LRO_HEADER_FIX); 1498 rte_errno = ENOTSUP; 1499 goto error; 1500 } 1501 /* 1502 * Determine the number of SGEs needed for a full packet 1503 * and round it to the next power of two. 1504 */ 1505 sges_n = log2above(tmpl->rxq.rxseg_n); 1506 if (sges_n > MLX5_MAX_LOG_RQ_SEGS) { 1507 DRV_LOG(ERR, 1508 "port %u too many SGEs (%u) needed to handle" 1509 " requested maximum packet size %u, the maximum" 1510 " supported are %u", dev->data->port_id, 1511 1 << sges_n, max_rx_pkt_len, 1512 1u << MLX5_MAX_LOG_RQ_SEGS); 1513 rte_errno = ENOTSUP; 1514 goto error; 1515 } 1516 tmpl->rxq.sges_n = sges_n; 1517 max_lro_size = max_rx_pkt_len; 1518 } 1519 if (config->mprq.enabled && !mlx5_rxq_mprq_enabled(&tmpl->rxq)) 1520 DRV_LOG(WARNING, 1521 "port %u MPRQ is requested but cannot be enabled\n" 1522 " (requested: pkt_sz = %u, desc_num = %u," 1523 " rxq_num = %u, stride_sz = %u, stride_num = %u\n" 1524 " supported: min_rxqs_num = %u," 1525 " min_stride_sz = %u, max_stride_sz = %u).", 1526 dev->data->port_id, non_scatter_min_mbuf_size, 1527 desc, priv->rxqs_n, 1528 config->mprq.stride_size_n ? 1529 (1U << config->mprq.stride_size_n) : 1530 (1U << mprq_stride_size), 1531 config->mprq.stride_num_n ? 1532 (1U << config->mprq.stride_num_n) : 1533 (1U << mprq_stride_nums), 1534 config->mprq.min_rxqs_num, 1535 (1U << config->mprq.min_stride_size_n), 1536 (1U << config->mprq.max_stride_size_n)); 1537 DRV_LOG(DEBUG, "port %u maximum number of segments per packet: %u", 1538 dev->data->port_id, 1 << tmpl->rxq.sges_n); 1539 if (desc % (1 << tmpl->rxq.sges_n)) { 1540 DRV_LOG(ERR, 1541 "port %u number of Rx queue descriptors (%u) is not a" 1542 " multiple of SGEs per packet (%u)", 1543 dev->data->port_id, 1544 desc, 1545 1 << tmpl->rxq.sges_n); 1546 rte_errno = EINVAL; 1547 goto error; 1548 } 1549 mlx5_max_lro_msg_size_adjust(dev, idx, max_lro_size); 1550 /* Toggle RX checksum offload if hardware supports it. */ 1551 tmpl->rxq.csum = !!(offloads & DEV_RX_OFFLOAD_CHECKSUM); 1552 /* Configure Rx timestamp. */ 1553 tmpl->rxq.hw_timestamp = !!(offloads & DEV_RX_OFFLOAD_TIMESTAMP); 1554 tmpl->rxq.timestamp_rx_flag = 0; 1555 if (tmpl->rxq.hw_timestamp && rte_mbuf_dyn_rx_timestamp_register( 1556 &tmpl->rxq.timestamp_offset, 1557 &tmpl->rxq.timestamp_rx_flag) != 0) { 1558 DRV_LOG(ERR, "Cannot register Rx timestamp field/flag"); 1559 goto error; 1560 } 1561 /* Configure VLAN stripping. */ 1562 tmpl->rxq.vlan_strip = !!(offloads & DEV_RX_OFFLOAD_VLAN_STRIP); 1563 /* By default, FCS (CRC) is stripped by hardware. */ 1564 tmpl->rxq.crc_present = 0; 1565 tmpl->rxq.lro = lro_on_queue; 1566 if (offloads & DEV_RX_OFFLOAD_KEEP_CRC) { 1567 if (config->hw_fcs_strip) { 1568 /* 1569 * RQs used for LRO-enabled TIRs should not be 1570 * configured to scatter the FCS. 1571 */ 1572 if (lro_on_queue) 1573 DRV_LOG(WARNING, 1574 "port %u CRC stripping has been " 1575 "disabled but will still be performed " 1576 "by hardware, because LRO is enabled", 1577 dev->data->port_id); 1578 else 1579 tmpl->rxq.crc_present = 1; 1580 } else { 1581 DRV_LOG(WARNING, 1582 "port %u CRC stripping has been disabled but will" 1583 " still be performed by hardware, make sure MLNX_OFED" 1584 " and firmware are up to date", 1585 dev->data->port_id); 1586 } 1587 } 1588 DRV_LOG(DEBUG, 1589 "port %u CRC stripping is %s, %u bytes will be subtracted from" 1590 " incoming frames to hide it", 1591 dev->data->port_id, 1592 tmpl->rxq.crc_present ? "disabled" : "enabled", 1593 tmpl->rxq.crc_present << 2); 1594 /* Save port ID. */ 1595 tmpl->rxq.rss_hash = !!priv->rss_conf.rss_hf && 1596 (!!(dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS)); 1597 tmpl->rxq.port_id = dev->data->port_id; 1598 tmpl->priv = priv; 1599 tmpl->rxq.mp = rx_seg[0].mp; 1600 tmpl->rxq.elts_n = log2above(desc); 1601 tmpl->rxq.rq_repl_thresh = 1602 MLX5_VPMD_RXQ_RPLNSH_THRESH(desc_n); 1603 tmpl->rxq.elts = 1604 (struct rte_mbuf *(*)[desc_n])(tmpl + 1); 1605 tmpl->rxq.mprq_bufs = 1606 (struct mlx5_mprq_buf *(*)[desc])(*tmpl->rxq.elts + desc_n); 1607 #ifndef RTE_ARCH_64 1608 tmpl->rxq.uar_lock_cq = &priv->sh->uar_lock_cq; 1609 #endif 1610 tmpl->rxq.idx = idx; 1611 __atomic_fetch_add(&tmpl->refcnt, 1, __ATOMIC_RELAXED); 1612 LIST_INSERT_HEAD(&priv->rxqsctrl, tmpl, next); 1613 return tmpl; 1614 error: 1615 mlx5_mr_btree_free(&tmpl->rxq.mr_ctrl.cache_bh); 1616 mlx5_free(tmpl); 1617 return NULL; 1618 } 1619 1620 /** 1621 * Create a DPDK Rx hairpin queue. 1622 * 1623 * @param dev 1624 * Pointer to Ethernet device. 1625 * @param idx 1626 * RX queue index. 1627 * @param desc 1628 * Number of descriptors to configure in queue. 1629 * @param hairpin_conf 1630 * The hairpin binding configuration. 1631 * 1632 * @return 1633 * A DPDK queue object on success, NULL otherwise and rte_errno is set. 1634 */ 1635 struct mlx5_rxq_ctrl * 1636 mlx5_rxq_hairpin_new(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, 1637 const struct rte_eth_hairpin_conf *hairpin_conf) 1638 { 1639 struct mlx5_priv *priv = dev->data->dev_private; 1640 struct mlx5_rxq_ctrl *tmpl; 1641 1642 tmpl = mlx5_malloc(MLX5_MEM_RTE | MLX5_MEM_ZERO, sizeof(*tmpl), 0, 1643 SOCKET_ID_ANY); 1644 if (!tmpl) { 1645 rte_errno = ENOMEM; 1646 return NULL; 1647 } 1648 tmpl->type = MLX5_RXQ_TYPE_HAIRPIN; 1649 tmpl->socket = SOCKET_ID_ANY; 1650 tmpl->rxq.rss_hash = 0; 1651 tmpl->rxq.port_id = dev->data->port_id; 1652 tmpl->priv = priv; 1653 tmpl->rxq.mp = NULL; 1654 tmpl->rxq.elts_n = log2above(desc); 1655 tmpl->rxq.elts = NULL; 1656 tmpl->rxq.mr_ctrl.cache_bh = (struct mlx5_mr_btree) { 0 }; 1657 tmpl->hairpin_conf = *hairpin_conf; 1658 tmpl->rxq.idx = idx; 1659 __atomic_fetch_add(&tmpl->refcnt, 1, __ATOMIC_RELAXED); 1660 LIST_INSERT_HEAD(&priv->rxqsctrl, tmpl, next); 1661 return tmpl; 1662 } 1663 1664 /** 1665 * Get a Rx queue. 1666 * 1667 * @param dev 1668 * Pointer to Ethernet device. 1669 * @param idx 1670 * RX queue index. 1671 * 1672 * @return 1673 * A pointer to the queue if it exists, NULL otherwise. 1674 */ 1675 struct mlx5_rxq_ctrl * 1676 mlx5_rxq_get(struct rte_eth_dev *dev, uint16_t idx) 1677 { 1678 struct mlx5_priv *priv = dev->data->dev_private; 1679 struct mlx5_rxq_data *rxq_data = (*priv->rxqs)[idx]; 1680 struct mlx5_rxq_ctrl *rxq_ctrl = NULL; 1681 1682 if (rxq_data) { 1683 rxq_ctrl = container_of(rxq_data, struct mlx5_rxq_ctrl, rxq); 1684 __atomic_fetch_add(&rxq_ctrl->refcnt, 1, __ATOMIC_RELAXED); 1685 } 1686 return rxq_ctrl; 1687 } 1688 1689 /** 1690 * Release a Rx queue. 1691 * 1692 * @param dev 1693 * Pointer to Ethernet device. 1694 * @param idx 1695 * RX queue index. 1696 * 1697 * @return 1698 * 1 while a reference on it exists, 0 when freed. 1699 */ 1700 int 1701 mlx5_rxq_release(struct rte_eth_dev *dev, uint16_t idx) 1702 { 1703 struct mlx5_priv *priv = dev->data->dev_private; 1704 struct mlx5_rxq_ctrl *rxq_ctrl; 1705 1706 if (priv->rxqs == NULL || (*priv->rxqs)[idx] == NULL) 1707 return 0; 1708 rxq_ctrl = container_of((*priv->rxqs)[idx], struct mlx5_rxq_ctrl, rxq); 1709 if (__atomic_sub_fetch(&rxq_ctrl->refcnt, 1, __ATOMIC_RELAXED) > 1) 1710 return 1; 1711 if (rxq_ctrl->obj) { 1712 priv->obj_ops.rxq_obj_release(rxq_ctrl->obj); 1713 LIST_REMOVE(rxq_ctrl->obj, next); 1714 mlx5_free(rxq_ctrl->obj); 1715 rxq_ctrl->obj = NULL; 1716 } 1717 if (rxq_ctrl->type == MLX5_RXQ_TYPE_STANDARD) { 1718 rxq_free_elts(rxq_ctrl); 1719 dev->data->rx_queue_state[idx] = RTE_ETH_QUEUE_STATE_STOPPED; 1720 } 1721 if (!__atomic_load_n(&rxq_ctrl->refcnt, __ATOMIC_RELAXED)) { 1722 if (rxq_ctrl->type == MLX5_RXQ_TYPE_STANDARD) 1723 mlx5_mr_btree_free(&rxq_ctrl->rxq.mr_ctrl.cache_bh); 1724 LIST_REMOVE(rxq_ctrl, next); 1725 mlx5_free(rxq_ctrl); 1726 (*priv->rxqs)[idx] = NULL; 1727 } 1728 return 0; 1729 } 1730 1731 /** 1732 * Verify the Rx Queue list is empty 1733 * 1734 * @param dev 1735 * Pointer to Ethernet device. 1736 * 1737 * @return 1738 * The number of object not released. 1739 */ 1740 int 1741 mlx5_rxq_verify(struct rte_eth_dev *dev) 1742 { 1743 struct mlx5_priv *priv = dev->data->dev_private; 1744 struct mlx5_rxq_ctrl *rxq_ctrl; 1745 int ret = 0; 1746 1747 LIST_FOREACH(rxq_ctrl, &priv->rxqsctrl, next) { 1748 DRV_LOG(DEBUG, "port %u Rx Queue %u still referenced", 1749 dev->data->port_id, rxq_ctrl->rxq.idx); 1750 ++ret; 1751 } 1752 return ret; 1753 } 1754 1755 /** 1756 * Get a Rx queue type. 1757 * 1758 * @param dev 1759 * Pointer to Ethernet device. 1760 * @param idx 1761 * Rx queue index. 1762 * 1763 * @return 1764 * The Rx queue type. 1765 */ 1766 enum mlx5_rxq_type 1767 mlx5_rxq_get_type(struct rte_eth_dev *dev, uint16_t idx) 1768 { 1769 struct mlx5_priv *priv = dev->data->dev_private; 1770 struct mlx5_rxq_ctrl *rxq_ctrl = NULL; 1771 1772 if (idx < priv->rxqs_n && (*priv->rxqs)[idx]) { 1773 rxq_ctrl = container_of((*priv->rxqs)[idx], 1774 struct mlx5_rxq_ctrl, 1775 rxq); 1776 return rxq_ctrl->type; 1777 } 1778 return MLX5_RXQ_TYPE_UNDEFINED; 1779 } 1780 1781 /* 1782 * Get a Rx hairpin queue configuration. 1783 * 1784 * @param dev 1785 * Pointer to Ethernet device. 1786 * @param idx 1787 * Rx queue index. 1788 * 1789 * @return 1790 * Pointer to the configuration if a hairpin RX queue, otherwise NULL. 1791 */ 1792 const struct rte_eth_hairpin_conf * 1793 mlx5_rxq_get_hairpin_conf(struct rte_eth_dev *dev, uint16_t idx) 1794 { 1795 struct mlx5_priv *priv = dev->data->dev_private; 1796 struct mlx5_rxq_ctrl *rxq_ctrl = NULL; 1797 1798 if (idx < priv->rxqs_n && (*priv->rxqs)[idx]) { 1799 rxq_ctrl = container_of((*priv->rxqs)[idx], 1800 struct mlx5_rxq_ctrl, 1801 rxq); 1802 if (rxq_ctrl->type == MLX5_RXQ_TYPE_HAIRPIN) 1803 return &rxq_ctrl->hairpin_conf; 1804 } 1805 return NULL; 1806 } 1807 1808 /** 1809 * Match queues listed in arguments to queues contained in indirection table 1810 * object. 1811 * 1812 * @param ind_tbl 1813 * Pointer to indirection table to match. 1814 * @param queues 1815 * Queues to match to ques in indirection table. 1816 * @param queues_n 1817 * Number of queues in the array. 1818 * 1819 * @return 1820 * 1 if all queues in indirection table match 0 othrwise. 1821 */ 1822 static int 1823 mlx5_ind_table_obj_match_queues(const struct mlx5_ind_table_obj *ind_tbl, 1824 const uint16_t *queues, uint32_t queues_n) 1825 { 1826 return (ind_tbl->queues_n == queues_n) && 1827 (!memcmp(ind_tbl->queues, queues, 1828 ind_tbl->queues_n * sizeof(ind_tbl->queues[0]))); 1829 } 1830 1831 /** 1832 * Get an indirection table. 1833 * 1834 * @param dev 1835 * Pointer to Ethernet device. 1836 * @param queues 1837 * Queues entering in the indirection table. 1838 * @param queues_n 1839 * Number of queues in the array. 1840 * 1841 * @return 1842 * An indirection table if found. 1843 */ 1844 struct mlx5_ind_table_obj * 1845 mlx5_ind_table_obj_get(struct rte_eth_dev *dev, const uint16_t *queues, 1846 uint32_t queues_n) 1847 { 1848 struct mlx5_priv *priv = dev->data->dev_private; 1849 struct mlx5_ind_table_obj *ind_tbl; 1850 1851 rte_rwlock_read_lock(&priv->ind_tbls_lock); 1852 LIST_FOREACH(ind_tbl, &priv->ind_tbls, next) { 1853 if ((ind_tbl->queues_n == queues_n) && 1854 (memcmp(ind_tbl->queues, queues, 1855 ind_tbl->queues_n * sizeof(ind_tbl->queues[0])) 1856 == 0)) { 1857 __atomic_fetch_add(&ind_tbl->refcnt, 1, 1858 __ATOMIC_RELAXED); 1859 break; 1860 } 1861 } 1862 rte_rwlock_read_unlock(&priv->ind_tbls_lock); 1863 return ind_tbl; 1864 } 1865 1866 /** 1867 * Release an indirection table. 1868 * 1869 * @param dev 1870 * Pointer to Ethernet device. 1871 * @param ind_table 1872 * Indirection table to release. 1873 * @param standalone 1874 * Indirection table for Standalone queue. 1875 * 1876 * @return 1877 * 1 while a reference on it exists, 0 when freed. 1878 */ 1879 int 1880 mlx5_ind_table_obj_release(struct rte_eth_dev *dev, 1881 struct mlx5_ind_table_obj *ind_tbl, 1882 bool standalone) 1883 { 1884 struct mlx5_priv *priv = dev->data->dev_private; 1885 unsigned int i, ret; 1886 1887 rte_rwlock_write_lock(&priv->ind_tbls_lock); 1888 ret = __atomic_sub_fetch(&ind_tbl->refcnt, 1, __ATOMIC_RELAXED); 1889 if (!ret && !standalone) 1890 LIST_REMOVE(ind_tbl, next); 1891 rte_rwlock_write_unlock(&priv->ind_tbls_lock); 1892 if (ret) 1893 return 1; 1894 priv->obj_ops.ind_table_destroy(ind_tbl); 1895 for (i = 0; i != ind_tbl->queues_n; ++i) 1896 claim_nonzero(mlx5_rxq_release(dev, ind_tbl->queues[i])); 1897 mlx5_free(ind_tbl); 1898 return 0; 1899 } 1900 1901 /** 1902 * Verify the Rx Queue list is empty 1903 * 1904 * @param dev 1905 * Pointer to Ethernet device. 1906 * 1907 * @return 1908 * The number of object not released. 1909 */ 1910 int 1911 mlx5_ind_table_obj_verify(struct rte_eth_dev *dev) 1912 { 1913 struct mlx5_priv *priv = dev->data->dev_private; 1914 struct mlx5_ind_table_obj *ind_tbl; 1915 int ret = 0; 1916 1917 rte_rwlock_read_lock(&priv->ind_tbls_lock); 1918 LIST_FOREACH(ind_tbl, &priv->ind_tbls, next) { 1919 DRV_LOG(DEBUG, 1920 "port %u indirection table obj %p still referenced", 1921 dev->data->port_id, (void *)ind_tbl); 1922 ++ret; 1923 } 1924 rte_rwlock_read_unlock(&priv->ind_tbls_lock); 1925 return ret; 1926 } 1927 1928 /** 1929 * Setup an indirection table structure fields. 1930 * 1931 * @param dev 1932 * Pointer to Ethernet device. 1933 * @param ind_table 1934 * Indirection table to modify. 1935 * 1936 * @return 1937 * 0 on success, a negative errno value otherwise and rte_errno is set. 1938 */ 1939 int 1940 mlx5_ind_table_obj_setup(struct rte_eth_dev *dev, 1941 struct mlx5_ind_table_obj *ind_tbl) 1942 { 1943 struct mlx5_priv *priv = dev->data->dev_private; 1944 uint32_t queues_n = ind_tbl->queues_n; 1945 uint16_t *queues = ind_tbl->queues; 1946 unsigned int i, j; 1947 int ret = 0, err; 1948 const unsigned int n = rte_is_power_of_2(queues_n) ? 1949 log2above(queues_n) : 1950 log2above(priv->config.ind_table_max_size); 1951 1952 for (i = 0; i != queues_n; ++i) { 1953 if (!mlx5_rxq_get(dev, queues[i])) { 1954 ret = -rte_errno; 1955 goto error; 1956 } 1957 } 1958 ret = priv->obj_ops.ind_table_new(dev, n, ind_tbl); 1959 if (ret) 1960 goto error; 1961 __atomic_fetch_add(&ind_tbl->refcnt, 1, __ATOMIC_RELAXED); 1962 return 0; 1963 error: 1964 err = rte_errno; 1965 for (j = 0; j < i; j++) 1966 mlx5_rxq_release(dev, ind_tbl->queues[j]); 1967 rte_errno = err; 1968 DRV_LOG(DEBUG, "Port %u cannot setup indirection table.", 1969 dev->data->port_id); 1970 return ret; 1971 } 1972 1973 /** 1974 * Create an indirection table. 1975 * 1976 * @param dev 1977 * Pointer to Ethernet device. 1978 * @param queues 1979 * Queues entering in the indirection table. 1980 * @param queues_n 1981 * Number of queues in the array. 1982 * @param standalone 1983 * Indirection table for Standalone queue. 1984 * 1985 * @return 1986 * The Verbs/DevX object initialized, NULL otherwise and rte_errno is set. 1987 */ 1988 static struct mlx5_ind_table_obj * 1989 mlx5_ind_table_obj_new(struct rte_eth_dev *dev, const uint16_t *queues, 1990 uint32_t queues_n, bool standalone) 1991 { 1992 struct mlx5_priv *priv = dev->data->dev_private; 1993 struct mlx5_ind_table_obj *ind_tbl; 1994 int ret; 1995 1996 ind_tbl = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*ind_tbl) + 1997 queues_n * sizeof(uint16_t), 0, SOCKET_ID_ANY); 1998 if (!ind_tbl) { 1999 rte_errno = ENOMEM; 2000 return NULL; 2001 } 2002 ind_tbl->queues_n = queues_n; 2003 ind_tbl->queues = (uint16_t *)(ind_tbl + 1); 2004 memcpy(ind_tbl->queues, queues, queues_n * sizeof(*queues)); 2005 ret = mlx5_ind_table_obj_setup(dev, ind_tbl); 2006 if (ret < 0) { 2007 mlx5_free(ind_tbl); 2008 return NULL; 2009 } 2010 if (!standalone) { 2011 rte_rwlock_write_lock(&priv->ind_tbls_lock); 2012 LIST_INSERT_HEAD(&priv->ind_tbls, ind_tbl, next); 2013 rte_rwlock_write_unlock(&priv->ind_tbls_lock); 2014 } 2015 return ind_tbl; 2016 } 2017 2018 /** 2019 * Modify an indirection table. 2020 * 2021 * @param dev 2022 * Pointer to Ethernet device. 2023 * @param ind_table 2024 * Indirection table to modify. 2025 * @param queues 2026 * Queues replacement for the indirection table. 2027 * @param queues_n 2028 * Number of queues in the array. 2029 * @param standalone 2030 * Indirection table for Standalone queue. 2031 * 2032 * @return 2033 * 0 on success, a negative errno value otherwise and rte_errno is set. 2034 */ 2035 int 2036 mlx5_ind_table_obj_modify(struct rte_eth_dev *dev, 2037 struct mlx5_ind_table_obj *ind_tbl, 2038 uint16_t *queues, const uint32_t queues_n, 2039 bool standalone) 2040 { 2041 struct mlx5_priv *priv = dev->data->dev_private; 2042 unsigned int i, j; 2043 int ret = 0, err; 2044 const unsigned int n = rte_is_power_of_2(queues_n) ? 2045 log2above(queues_n) : 2046 log2above(priv->config.ind_table_max_size); 2047 2048 MLX5_ASSERT(standalone); 2049 RTE_SET_USED(standalone); 2050 if (__atomic_load_n(&ind_tbl->refcnt, __ATOMIC_RELAXED) > 1) { 2051 /* 2052 * Modification of indirection ntables having more than 1 2053 * reference unsupported. Intended for standalone indirection 2054 * tables only. 2055 */ 2056 DRV_LOG(DEBUG, 2057 "Port %u cannot modify indirection table (refcnt> 1).", 2058 dev->data->port_id); 2059 rte_errno = EINVAL; 2060 return -rte_errno; 2061 } 2062 for (i = 0; i != queues_n; ++i) { 2063 if (!mlx5_rxq_get(dev, queues[i])) { 2064 ret = -rte_errno; 2065 goto error; 2066 } 2067 } 2068 MLX5_ASSERT(priv->obj_ops.ind_table_modify); 2069 ret = priv->obj_ops.ind_table_modify(dev, n, queues, queues_n, ind_tbl); 2070 if (ret) 2071 goto error; 2072 for (j = 0; j < ind_tbl->queues_n; j++) 2073 mlx5_rxq_release(dev, ind_tbl->queues[j]); 2074 ind_tbl->queues_n = queues_n; 2075 ind_tbl->queues = queues; 2076 return 0; 2077 error: 2078 err = rte_errno; 2079 for (j = 0; j < i; j++) 2080 mlx5_rxq_release(dev, queues[j]); 2081 rte_errno = err; 2082 DRV_LOG(DEBUG, "Port %u cannot setup indirection table.", 2083 dev->data->port_id); 2084 return ret; 2085 } 2086 2087 int 2088 mlx5_hrxq_match_cb(void *tool_ctx __rte_unused, struct mlx5_list_entry *entry, 2089 void *cb_ctx) 2090 { 2091 struct mlx5_flow_cb_ctx *ctx = cb_ctx; 2092 struct mlx5_flow_rss_desc *rss_desc = ctx->data; 2093 struct mlx5_hrxq *hrxq = container_of(entry, typeof(*hrxq), entry); 2094 2095 return (hrxq->rss_key_len != rss_desc->key_len || 2096 memcmp(hrxq->rss_key, rss_desc->key, rss_desc->key_len) || 2097 hrxq->hash_fields != rss_desc->hash_fields || 2098 hrxq->ind_table->queues_n != rss_desc->queue_num || 2099 memcmp(hrxq->ind_table->queues, rss_desc->queue, 2100 rss_desc->queue_num * sizeof(rss_desc->queue[0]))); 2101 } 2102 2103 /** 2104 * Modify an Rx Hash queue configuration. 2105 * 2106 * @param dev 2107 * Pointer to Ethernet device. 2108 * @param hrxq 2109 * Index to Hash Rx queue to modify. 2110 * @param rss_key 2111 * RSS key for the Rx hash queue. 2112 * @param rss_key_len 2113 * RSS key length. 2114 * @param hash_fields 2115 * Verbs protocol hash field to make the RSS on. 2116 * @param queues 2117 * Queues entering in hash queue. In case of empty hash_fields only the 2118 * first queue index will be taken for the indirection table. 2119 * @param queues_n 2120 * Number of queues. 2121 * 2122 * @return 2123 * 0 on success, a negative errno value otherwise and rte_errno is set. 2124 */ 2125 int 2126 mlx5_hrxq_modify(struct rte_eth_dev *dev, uint32_t hrxq_idx, 2127 const uint8_t *rss_key, uint32_t rss_key_len, 2128 uint64_t hash_fields, 2129 const uint16_t *queues, uint32_t queues_n) 2130 { 2131 int err; 2132 struct mlx5_ind_table_obj *ind_tbl = NULL; 2133 struct mlx5_priv *priv = dev->data->dev_private; 2134 struct mlx5_hrxq *hrxq = 2135 mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_HRXQ], hrxq_idx); 2136 int ret; 2137 2138 if (!hrxq) { 2139 rte_errno = EINVAL; 2140 return -rte_errno; 2141 } 2142 /* validations */ 2143 if (hrxq->rss_key_len != rss_key_len) { 2144 /* rss_key_len is fixed size 40 byte & not supposed to change */ 2145 rte_errno = EINVAL; 2146 return -rte_errno; 2147 } 2148 queues_n = hash_fields ? queues_n : 1; 2149 if (mlx5_ind_table_obj_match_queues(hrxq->ind_table, 2150 queues, queues_n)) { 2151 ind_tbl = hrxq->ind_table; 2152 } else { 2153 if (hrxq->standalone) { 2154 /* 2155 * Replacement of indirection table unsupported for 2156 * stanalone hrxq objects (used by shared RSS). 2157 */ 2158 rte_errno = ENOTSUP; 2159 return -rte_errno; 2160 } 2161 ind_tbl = mlx5_ind_table_obj_get(dev, queues, queues_n); 2162 if (!ind_tbl) 2163 ind_tbl = mlx5_ind_table_obj_new(dev, queues, queues_n, 2164 hrxq->standalone); 2165 } 2166 if (!ind_tbl) { 2167 rte_errno = ENOMEM; 2168 return -rte_errno; 2169 } 2170 MLX5_ASSERT(priv->obj_ops.hrxq_modify); 2171 ret = priv->obj_ops.hrxq_modify(dev, hrxq, rss_key, 2172 hash_fields, ind_tbl); 2173 if (ret) { 2174 rte_errno = errno; 2175 goto error; 2176 } 2177 if (ind_tbl != hrxq->ind_table) { 2178 MLX5_ASSERT(!hrxq->standalone); 2179 mlx5_ind_table_obj_release(dev, hrxq->ind_table, 2180 hrxq->standalone); 2181 hrxq->ind_table = ind_tbl; 2182 } 2183 hrxq->hash_fields = hash_fields; 2184 memcpy(hrxq->rss_key, rss_key, rss_key_len); 2185 return 0; 2186 error: 2187 err = rte_errno; 2188 if (ind_tbl != hrxq->ind_table) { 2189 MLX5_ASSERT(!hrxq->standalone); 2190 mlx5_ind_table_obj_release(dev, ind_tbl, hrxq->standalone); 2191 } 2192 rte_errno = err; 2193 return -rte_errno; 2194 } 2195 2196 static void 2197 __mlx5_hrxq_remove(struct rte_eth_dev *dev, struct mlx5_hrxq *hrxq) 2198 { 2199 struct mlx5_priv *priv = dev->data->dev_private; 2200 2201 #ifdef HAVE_IBV_FLOW_DV_SUPPORT 2202 mlx5_glue->destroy_flow_action(hrxq->action); 2203 #endif 2204 priv->obj_ops.hrxq_destroy(hrxq); 2205 if (!hrxq->standalone) { 2206 mlx5_ind_table_obj_release(dev, hrxq->ind_table, 2207 hrxq->standalone); 2208 } 2209 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_HRXQ], hrxq->idx); 2210 } 2211 2212 /** 2213 * Release the hash Rx queue. 2214 * 2215 * @param dev 2216 * Pointer to Ethernet device. 2217 * @param hrxq 2218 * Index to Hash Rx queue to release. 2219 * 2220 * @param list 2221 * mlx5 list pointer. 2222 * @param entry 2223 * Hash queue entry pointer. 2224 */ 2225 void 2226 mlx5_hrxq_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry) 2227 { 2228 struct rte_eth_dev *dev = tool_ctx; 2229 struct mlx5_hrxq *hrxq = container_of(entry, typeof(*hrxq), entry); 2230 2231 __mlx5_hrxq_remove(dev, hrxq); 2232 } 2233 2234 static struct mlx5_hrxq * 2235 __mlx5_hrxq_create(struct rte_eth_dev *dev, 2236 struct mlx5_flow_rss_desc *rss_desc) 2237 { 2238 struct mlx5_priv *priv = dev->data->dev_private; 2239 const uint8_t *rss_key = rss_desc->key; 2240 uint32_t rss_key_len = rss_desc->key_len; 2241 bool standalone = !!rss_desc->shared_rss; 2242 const uint16_t *queues = 2243 standalone ? rss_desc->const_q : rss_desc->queue; 2244 uint32_t queues_n = rss_desc->queue_num; 2245 struct mlx5_hrxq *hrxq = NULL; 2246 uint32_t hrxq_idx = 0; 2247 struct mlx5_ind_table_obj *ind_tbl = rss_desc->ind_tbl; 2248 int ret; 2249 2250 queues_n = rss_desc->hash_fields ? queues_n : 1; 2251 if (!ind_tbl) 2252 ind_tbl = mlx5_ind_table_obj_get(dev, queues, queues_n); 2253 if (!ind_tbl) 2254 ind_tbl = mlx5_ind_table_obj_new(dev, queues, queues_n, 2255 standalone); 2256 if (!ind_tbl) 2257 return NULL; 2258 hrxq = mlx5_ipool_zmalloc(priv->sh->ipool[MLX5_IPOOL_HRXQ], &hrxq_idx); 2259 if (!hrxq) 2260 goto error; 2261 hrxq->standalone = standalone; 2262 hrxq->idx = hrxq_idx; 2263 hrxq->ind_table = ind_tbl; 2264 hrxq->rss_key_len = rss_key_len; 2265 hrxq->hash_fields = rss_desc->hash_fields; 2266 memcpy(hrxq->rss_key, rss_key, rss_key_len); 2267 ret = priv->obj_ops.hrxq_new(dev, hrxq, rss_desc->tunnel); 2268 if (ret < 0) 2269 goto error; 2270 return hrxq; 2271 error: 2272 if (!rss_desc->ind_tbl) 2273 mlx5_ind_table_obj_release(dev, ind_tbl, standalone); 2274 if (hrxq) 2275 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_HRXQ], hrxq_idx); 2276 return NULL; 2277 } 2278 2279 struct mlx5_list_entry * 2280 mlx5_hrxq_create_cb(void *tool_ctx, void *cb_ctx) 2281 { 2282 struct rte_eth_dev *dev = tool_ctx; 2283 struct mlx5_flow_cb_ctx *ctx = cb_ctx; 2284 struct mlx5_flow_rss_desc *rss_desc = ctx->data; 2285 struct mlx5_hrxq *hrxq; 2286 2287 hrxq = __mlx5_hrxq_create(dev, rss_desc); 2288 return hrxq ? &hrxq->entry : NULL; 2289 } 2290 2291 struct mlx5_list_entry * 2292 mlx5_hrxq_clone_cb(void *tool_ctx, struct mlx5_list_entry *entry, 2293 void *cb_ctx __rte_unused) 2294 { 2295 struct rte_eth_dev *dev = tool_ctx; 2296 struct mlx5_priv *priv = dev->data->dev_private; 2297 struct mlx5_hrxq *hrxq; 2298 uint32_t hrxq_idx = 0; 2299 2300 hrxq = mlx5_ipool_zmalloc(priv->sh->ipool[MLX5_IPOOL_HRXQ], &hrxq_idx); 2301 if (!hrxq) 2302 return NULL; 2303 memcpy(hrxq, entry, sizeof(*hrxq) + MLX5_RSS_HASH_KEY_LEN); 2304 hrxq->idx = hrxq_idx; 2305 return &hrxq->entry; 2306 } 2307 2308 void 2309 mlx5_hrxq_clone_free_cb(void *tool_ctx, struct mlx5_list_entry *entry) 2310 { 2311 struct rte_eth_dev *dev = tool_ctx; 2312 struct mlx5_priv *priv = dev->data->dev_private; 2313 struct mlx5_hrxq *hrxq = container_of(entry, typeof(*hrxq), entry); 2314 2315 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_HRXQ], hrxq->idx); 2316 } 2317 2318 /** 2319 * Get an Rx Hash queue. 2320 * 2321 * @param dev 2322 * Pointer to Ethernet device. 2323 * @param rss_desc 2324 * RSS configuration for the Rx hash queue. 2325 * 2326 * @return 2327 * An hash Rx queue index on success. 2328 */ 2329 uint32_t mlx5_hrxq_get(struct rte_eth_dev *dev, 2330 struct mlx5_flow_rss_desc *rss_desc) 2331 { 2332 struct mlx5_priv *priv = dev->data->dev_private; 2333 struct mlx5_hrxq *hrxq; 2334 struct mlx5_list_entry *entry; 2335 struct mlx5_flow_cb_ctx ctx = { 2336 .data = rss_desc, 2337 }; 2338 2339 if (rss_desc->shared_rss) { 2340 hrxq = __mlx5_hrxq_create(dev, rss_desc); 2341 } else { 2342 entry = mlx5_list_register(priv->hrxqs, &ctx); 2343 if (!entry) 2344 return 0; 2345 hrxq = container_of(entry, typeof(*hrxq), entry); 2346 } 2347 if (hrxq) 2348 return hrxq->idx; 2349 return 0; 2350 } 2351 2352 /** 2353 * Release the hash Rx queue. 2354 * 2355 * @param dev 2356 * Pointer to Ethernet device. 2357 * @param hrxq_idx 2358 * Index to Hash Rx queue to release. 2359 * 2360 * @return 2361 * 1 while a reference on it exists, 0 when freed. 2362 */ 2363 int mlx5_hrxq_release(struct rte_eth_dev *dev, uint32_t hrxq_idx) 2364 { 2365 struct mlx5_priv *priv = dev->data->dev_private; 2366 struct mlx5_hrxq *hrxq; 2367 2368 hrxq = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_HRXQ], hrxq_idx); 2369 if (!hrxq) 2370 return 0; 2371 if (!hrxq->standalone) 2372 return mlx5_list_unregister(priv->hrxqs, &hrxq->entry); 2373 __mlx5_hrxq_remove(dev, hrxq); 2374 return 0; 2375 } 2376 2377 /** 2378 * Create a drop Rx Hash queue. 2379 * 2380 * @param dev 2381 * Pointer to Ethernet device. 2382 * 2383 * @return 2384 * The Verbs/DevX object initialized, NULL otherwise and rte_errno is set. 2385 */ 2386 struct mlx5_hrxq * 2387 mlx5_drop_action_create(struct rte_eth_dev *dev) 2388 { 2389 struct mlx5_priv *priv = dev->data->dev_private; 2390 struct mlx5_hrxq *hrxq = NULL; 2391 int ret; 2392 2393 if (priv->drop_queue.hrxq) 2394 return priv->drop_queue.hrxq; 2395 hrxq = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*hrxq), 0, SOCKET_ID_ANY); 2396 if (!hrxq) { 2397 DRV_LOG(WARNING, 2398 "Port %u cannot allocate memory for drop queue.", 2399 dev->data->port_id); 2400 rte_errno = ENOMEM; 2401 goto error; 2402 } 2403 priv->drop_queue.hrxq = hrxq; 2404 hrxq->ind_table = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*hrxq->ind_table), 2405 0, SOCKET_ID_ANY); 2406 if (!hrxq->ind_table) { 2407 rte_errno = ENOMEM; 2408 goto error; 2409 } 2410 ret = priv->obj_ops.drop_action_create(dev); 2411 if (ret < 0) 2412 goto error; 2413 return hrxq; 2414 error: 2415 if (hrxq) { 2416 if (hrxq->ind_table) 2417 mlx5_free(hrxq->ind_table); 2418 priv->drop_queue.hrxq = NULL; 2419 mlx5_free(hrxq); 2420 } 2421 return NULL; 2422 } 2423 2424 /** 2425 * Release a drop hash Rx queue. 2426 * 2427 * @param dev 2428 * Pointer to Ethernet device. 2429 */ 2430 void 2431 mlx5_drop_action_destroy(struct rte_eth_dev *dev) 2432 { 2433 struct mlx5_priv *priv = dev->data->dev_private; 2434 struct mlx5_hrxq *hrxq = priv->drop_queue.hrxq; 2435 2436 if (!priv->drop_queue.hrxq) 2437 return; 2438 priv->obj_ops.drop_action_destroy(dev); 2439 mlx5_free(priv->drop_queue.rxq); 2440 mlx5_free(hrxq->ind_table); 2441 mlx5_free(hrxq); 2442 priv->drop_queue.rxq = NULL; 2443 priv->drop_queue.hrxq = NULL; 2444 } 2445 2446 /** 2447 * Verify the Rx Queue list is empty 2448 * 2449 * @param dev 2450 * Pointer to Ethernet device. 2451 * 2452 * @return 2453 * The number of object not released. 2454 */ 2455 uint32_t 2456 mlx5_hrxq_verify(struct rte_eth_dev *dev) 2457 { 2458 struct mlx5_priv *priv = dev->data->dev_private; 2459 2460 return mlx5_list_get_entry_num(priv->hrxqs); 2461 } 2462 2463 /** 2464 * Set the Rx queue timestamp conversion parameters 2465 * 2466 * @param[in] dev 2467 * Pointer to the Ethernet device structure. 2468 */ 2469 void 2470 mlx5_rxq_timestamp_set(struct rte_eth_dev *dev) 2471 { 2472 struct mlx5_priv *priv = dev->data->dev_private; 2473 struct mlx5_dev_ctx_shared *sh = priv->sh; 2474 struct mlx5_rxq_data *data; 2475 unsigned int i; 2476 2477 for (i = 0; i != priv->rxqs_n; ++i) { 2478 if (!(*priv->rxqs)[i]) 2479 continue; 2480 data = (*priv->rxqs)[i]; 2481 data->sh = sh; 2482 data->rt_timestamp = priv->config.rt_timestamp; 2483 } 2484 } 2485