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 dpdk_rxq 798 * Generic RX queue pointer. 799 */ 800 void 801 mlx5_rx_queue_release(void *dpdk_rxq) 802 { 803 struct mlx5_rxq_data *rxq = (struct mlx5_rxq_data *)dpdk_rxq; 804 struct mlx5_rxq_ctrl *rxq_ctrl; 805 struct mlx5_priv *priv; 806 807 if (rxq == NULL) 808 return; 809 rxq_ctrl = container_of(rxq, struct mlx5_rxq_ctrl, rxq); 810 priv = rxq_ctrl->priv; 811 if (!mlx5_rxq_releasable(ETH_DEV(priv), rxq_ctrl->rxq.idx)) 812 rte_panic("port %u Rx queue %u is still used by a flow and" 813 " cannot be removed\n", 814 PORT_ID(priv), rxq->idx); 815 mlx5_rxq_release(ETH_DEV(priv), rxq_ctrl->rxq.idx); 816 } 817 818 /** 819 * Allocate queue vector and fill epoll fd list for Rx interrupts. 820 * 821 * @param dev 822 * Pointer to Ethernet device. 823 * 824 * @return 825 * 0 on success, a negative errno value otherwise and rte_errno is set. 826 */ 827 int 828 mlx5_rx_intr_vec_enable(struct rte_eth_dev *dev) 829 { 830 struct mlx5_priv *priv = dev->data->dev_private; 831 unsigned int i; 832 unsigned int rxqs_n = priv->rxqs_n; 833 unsigned int n = RTE_MIN(rxqs_n, (uint32_t)RTE_MAX_RXTX_INTR_VEC_ID); 834 unsigned int count = 0; 835 struct rte_intr_handle *intr_handle = dev->intr_handle; 836 837 if (!dev->data->dev_conf.intr_conf.rxq) 838 return 0; 839 mlx5_rx_intr_vec_disable(dev); 840 intr_handle->intr_vec = mlx5_malloc(0, 841 n * sizeof(intr_handle->intr_vec[0]), 842 0, SOCKET_ID_ANY); 843 if (intr_handle->intr_vec == NULL) { 844 DRV_LOG(ERR, 845 "port %u failed to allocate memory for interrupt" 846 " vector, Rx interrupts will not be supported", 847 dev->data->port_id); 848 rte_errno = ENOMEM; 849 return -rte_errno; 850 } 851 intr_handle->type = RTE_INTR_HANDLE_EXT; 852 for (i = 0; i != n; ++i) { 853 /* This rxq obj must not be released in this function. */ 854 struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_rxq_get(dev, i); 855 struct mlx5_rxq_obj *rxq_obj = rxq_ctrl ? rxq_ctrl->obj : NULL; 856 int rc; 857 858 /* Skip queues that cannot request interrupts. */ 859 if (!rxq_obj || (!rxq_obj->ibv_channel && 860 !rxq_obj->devx_channel)) { 861 /* Use invalid intr_vec[] index to disable entry. */ 862 intr_handle->intr_vec[i] = 863 RTE_INTR_VEC_RXTX_OFFSET + 864 RTE_MAX_RXTX_INTR_VEC_ID; 865 /* Decrease the rxq_ctrl's refcnt */ 866 if (rxq_ctrl) 867 mlx5_rxq_release(dev, i); 868 continue; 869 } 870 if (count >= RTE_MAX_RXTX_INTR_VEC_ID) { 871 DRV_LOG(ERR, 872 "port %u too many Rx queues for interrupt" 873 " vector size (%d), Rx interrupts cannot be" 874 " enabled", 875 dev->data->port_id, RTE_MAX_RXTX_INTR_VEC_ID); 876 mlx5_rx_intr_vec_disable(dev); 877 rte_errno = ENOMEM; 878 return -rte_errno; 879 } 880 rc = mlx5_os_set_nonblock_channel_fd(rxq_obj->fd); 881 if (rc < 0) { 882 rte_errno = errno; 883 DRV_LOG(ERR, 884 "port %u failed to make Rx interrupt file" 885 " descriptor %d non-blocking for queue index" 886 " %d", 887 dev->data->port_id, rxq_obj->fd, i); 888 mlx5_rx_intr_vec_disable(dev); 889 return -rte_errno; 890 } 891 intr_handle->intr_vec[i] = RTE_INTR_VEC_RXTX_OFFSET + count; 892 intr_handle->efds[count] = rxq_obj->fd; 893 count++; 894 } 895 if (!count) 896 mlx5_rx_intr_vec_disable(dev); 897 else 898 intr_handle->nb_efd = count; 899 return 0; 900 } 901 902 /** 903 * Clean up Rx interrupts handler. 904 * 905 * @param dev 906 * Pointer to Ethernet device. 907 */ 908 void 909 mlx5_rx_intr_vec_disable(struct rte_eth_dev *dev) 910 { 911 struct mlx5_priv *priv = dev->data->dev_private; 912 struct rte_intr_handle *intr_handle = dev->intr_handle; 913 unsigned int i; 914 unsigned int rxqs_n = priv->rxqs_n; 915 unsigned int n = RTE_MIN(rxqs_n, (uint32_t)RTE_MAX_RXTX_INTR_VEC_ID); 916 917 if (!dev->data->dev_conf.intr_conf.rxq) 918 return; 919 if (!intr_handle->intr_vec) 920 goto free; 921 for (i = 0; i != n; ++i) { 922 if (intr_handle->intr_vec[i] == RTE_INTR_VEC_RXTX_OFFSET + 923 RTE_MAX_RXTX_INTR_VEC_ID) 924 continue; 925 /** 926 * Need to access directly the queue to release the reference 927 * kept in mlx5_rx_intr_vec_enable(). 928 */ 929 mlx5_rxq_release(dev, i); 930 } 931 free: 932 rte_intr_free_epoll_fd(intr_handle); 933 if (intr_handle->intr_vec) 934 mlx5_free(intr_handle->intr_vec); 935 intr_handle->nb_efd = 0; 936 intr_handle->intr_vec = NULL; 937 } 938 939 /** 940 * MLX5 CQ notification . 941 * 942 * @param rxq 943 * Pointer to receive queue structure. 944 * @param sq_n_rxq 945 * Sequence number per receive queue . 946 */ 947 static inline void 948 mlx5_arm_cq(struct mlx5_rxq_data *rxq, int sq_n_rxq) 949 { 950 int sq_n = 0; 951 uint32_t doorbell_hi; 952 uint64_t doorbell; 953 void *cq_db_reg = (char *)rxq->cq_uar + MLX5_CQ_DOORBELL; 954 955 sq_n = sq_n_rxq & MLX5_CQ_SQN_MASK; 956 doorbell_hi = sq_n << MLX5_CQ_SQN_OFFSET | (rxq->cq_ci & MLX5_CI_MASK); 957 doorbell = (uint64_t)doorbell_hi << 32; 958 doorbell |= rxq->cqn; 959 rxq->cq_db[MLX5_CQ_ARM_DB] = rte_cpu_to_be_32(doorbell_hi); 960 mlx5_uar_write64(rte_cpu_to_be_64(doorbell), 961 cq_db_reg, rxq->uar_lock_cq); 962 } 963 964 /** 965 * DPDK callback for Rx queue interrupt enable. 966 * 967 * @param dev 968 * Pointer to Ethernet device structure. 969 * @param rx_queue_id 970 * Rx queue number. 971 * 972 * @return 973 * 0 on success, a negative errno value otherwise and rte_errno is set. 974 */ 975 int 976 mlx5_rx_intr_enable(struct rte_eth_dev *dev, uint16_t rx_queue_id) 977 { 978 struct mlx5_rxq_ctrl *rxq_ctrl; 979 980 rxq_ctrl = mlx5_rxq_get(dev, rx_queue_id); 981 if (!rxq_ctrl) 982 goto error; 983 if (rxq_ctrl->irq) { 984 if (!rxq_ctrl->obj) { 985 mlx5_rxq_release(dev, rx_queue_id); 986 goto error; 987 } 988 mlx5_arm_cq(&rxq_ctrl->rxq, rxq_ctrl->rxq.cq_arm_sn); 989 } 990 mlx5_rxq_release(dev, rx_queue_id); 991 return 0; 992 error: 993 rte_errno = EINVAL; 994 return -rte_errno; 995 } 996 997 /** 998 * DPDK callback for Rx queue interrupt disable. 999 * 1000 * @param dev 1001 * Pointer to Ethernet device structure. 1002 * @param rx_queue_id 1003 * Rx queue number. 1004 * 1005 * @return 1006 * 0 on success, a negative errno value otherwise and rte_errno is set. 1007 */ 1008 int 1009 mlx5_rx_intr_disable(struct rte_eth_dev *dev, uint16_t rx_queue_id) 1010 { 1011 struct mlx5_priv *priv = dev->data->dev_private; 1012 struct mlx5_rxq_ctrl *rxq_ctrl; 1013 int ret = 0; 1014 1015 rxq_ctrl = mlx5_rxq_get(dev, rx_queue_id); 1016 if (!rxq_ctrl) { 1017 rte_errno = EINVAL; 1018 return -rte_errno; 1019 } 1020 if (!rxq_ctrl->obj) 1021 goto error; 1022 if (rxq_ctrl->irq) { 1023 ret = priv->obj_ops.rxq_event_get(rxq_ctrl->obj); 1024 if (ret < 0) 1025 goto error; 1026 rxq_ctrl->rxq.cq_arm_sn++; 1027 } 1028 mlx5_rxq_release(dev, rx_queue_id); 1029 return 0; 1030 error: 1031 /** 1032 * The ret variable may be EAGAIN which means the get_event function was 1033 * called before receiving one. 1034 */ 1035 if (ret < 0) 1036 rte_errno = errno; 1037 else 1038 rte_errno = EINVAL; 1039 ret = rte_errno; /* Save rte_errno before cleanup. */ 1040 mlx5_rxq_release(dev, rx_queue_id); 1041 if (ret != EAGAIN) 1042 DRV_LOG(WARNING, "port %u unable to disable interrupt on Rx queue %d", 1043 dev->data->port_id, rx_queue_id); 1044 rte_errno = ret; /* Restore rte_errno. */ 1045 return -rte_errno; 1046 } 1047 1048 /** 1049 * Verify the Rx queue objects list is empty 1050 * 1051 * @param dev 1052 * Pointer to Ethernet device. 1053 * 1054 * @return 1055 * The number of objects not released. 1056 */ 1057 int 1058 mlx5_rxq_obj_verify(struct rte_eth_dev *dev) 1059 { 1060 struct mlx5_priv *priv = dev->data->dev_private; 1061 int ret = 0; 1062 struct mlx5_rxq_obj *rxq_obj; 1063 1064 LIST_FOREACH(rxq_obj, &priv->rxqsobj, next) { 1065 DRV_LOG(DEBUG, "port %u Rx queue %u still referenced", 1066 dev->data->port_id, rxq_obj->rxq_ctrl->rxq.idx); 1067 ++ret; 1068 } 1069 return ret; 1070 } 1071 1072 /** 1073 * Callback function to initialize mbufs for Multi-Packet RQ. 1074 */ 1075 static inline void 1076 mlx5_mprq_buf_init(struct rte_mempool *mp, void *opaque_arg, 1077 void *_m, unsigned int i __rte_unused) 1078 { 1079 struct mlx5_mprq_buf *buf = _m; 1080 struct rte_mbuf_ext_shared_info *shinfo; 1081 unsigned int strd_n = (unsigned int)(uintptr_t)opaque_arg; 1082 unsigned int j; 1083 1084 memset(_m, 0, sizeof(*buf)); 1085 buf->mp = mp; 1086 __atomic_store_n(&buf->refcnt, 1, __ATOMIC_RELAXED); 1087 for (j = 0; j != strd_n; ++j) { 1088 shinfo = &buf->shinfos[j]; 1089 shinfo->free_cb = mlx5_mprq_buf_free_cb; 1090 shinfo->fcb_opaque = buf; 1091 } 1092 } 1093 1094 /** 1095 * Free mempool of Multi-Packet RQ. 1096 * 1097 * @param dev 1098 * Pointer to Ethernet device. 1099 * 1100 * @return 1101 * 0 on success, negative errno value on failure. 1102 */ 1103 int 1104 mlx5_mprq_free_mp(struct rte_eth_dev *dev) 1105 { 1106 struct mlx5_priv *priv = dev->data->dev_private; 1107 struct rte_mempool *mp = priv->mprq_mp; 1108 unsigned int i; 1109 1110 if (mp == NULL) 1111 return 0; 1112 DRV_LOG(DEBUG, "port %u freeing mempool (%s) for Multi-Packet RQ", 1113 dev->data->port_id, mp->name); 1114 /* 1115 * If a buffer in the pool has been externally attached to a mbuf and it 1116 * is still in use by application, destroying the Rx queue can spoil 1117 * the packet. It is unlikely to happen but if application dynamically 1118 * creates and destroys with holding Rx packets, this can happen. 1119 * 1120 * TODO: It is unavoidable for now because the mempool for Multi-Packet 1121 * RQ isn't provided by application but managed by PMD. 1122 */ 1123 if (!rte_mempool_full(mp)) { 1124 DRV_LOG(ERR, 1125 "port %u mempool for Multi-Packet RQ is still in use", 1126 dev->data->port_id); 1127 rte_errno = EBUSY; 1128 return -rte_errno; 1129 } 1130 rte_mempool_free(mp); 1131 /* Unset mempool for each Rx queue. */ 1132 for (i = 0; i != priv->rxqs_n; ++i) { 1133 struct mlx5_rxq_data *rxq = (*priv->rxqs)[i]; 1134 1135 if (rxq == NULL) 1136 continue; 1137 rxq->mprq_mp = NULL; 1138 } 1139 priv->mprq_mp = NULL; 1140 return 0; 1141 } 1142 1143 /** 1144 * Allocate a mempool for Multi-Packet RQ. All configured Rx queues share the 1145 * mempool. If already allocated, reuse it if there're enough elements. 1146 * Otherwise, resize it. 1147 * 1148 * @param dev 1149 * Pointer to Ethernet device. 1150 * 1151 * @return 1152 * 0 on success, negative errno value on failure. 1153 */ 1154 int 1155 mlx5_mprq_alloc_mp(struct rte_eth_dev *dev) 1156 { 1157 struct mlx5_priv *priv = dev->data->dev_private; 1158 struct rte_mempool *mp = priv->mprq_mp; 1159 char name[RTE_MEMPOOL_NAMESIZE]; 1160 unsigned int desc = 0; 1161 unsigned int buf_len; 1162 unsigned int obj_num; 1163 unsigned int obj_size; 1164 unsigned int strd_num_n = 0; 1165 unsigned int strd_sz_n = 0; 1166 unsigned int i; 1167 unsigned int n_ibv = 0; 1168 1169 if (!mlx5_mprq_enabled(dev)) 1170 return 0; 1171 /* Count the total number of descriptors configured. */ 1172 for (i = 0; i != priv->rxqs_n; ++i) { 1173 struct mlx5_rxq_data *rxq = (*priv->rxqs)[i]; 1174 struct mlx5_rxq_ctrl *rxq_ctrl = container_of 1175 (rxq, struct mlx5_rxq_ctrl, rxq); 1176 1177 if (rxq == NULL || rxq_ctrl->type != MLX5_RXQ_TYPE_STANDARD) 1178 continue; 1179 n_ibv++; 1180 desc += 1 << rxq->elts_n; 1181 /* Get the max number of strides. */ 1182 if (strd_num_n < rxq->strd_num_n) 1183 strd_num_n = rxq->strd_num_n; 1184 /* Get the max size of a stride. */ 1185 if (strd_sz_n < rxq->strd_sz_n) 1186 strd_sz_n = rxq->strd_sz_n; 1187 } 1188 MLX5_ASSERT(strd_num_n && strd_sz_n); 1189 buf_len = (1 << strd_num_n) * (1 << strd_sz_n); 1190 obj_size = sizeof(struct mlx5_mprq_buf) + buf_len + (1 << strd_num_n) * 1191 sizeof(struct rte_mbuf_ext_shared_info) + RTE_PKTMBUF_HEADROOM; 1192 /* 1193 * Received packets can be either memcpy'd or externally referenced. In 1194 * case that the packet is attached to an mbuf as an external buffer, as 1195 * it isn't possible to predict how the buffers will be queued by 1196 * application, there's no option to exactly pre-allocate needed buffers 1197 * in advance but to speculatively prepares enough buffers. 1198 * 1199 * In the data path, if this Mempool is depleted, PMD will try to memcpy 1200 * received packets to buffers provided by application (rxq->mp) until 1201 * this Mempool gets available again. 1202 */ 1203 desc *= 4; 1204 obj_num = desc + MLX5_MPRQ_MP_CACHE_SZ * n_ibv; 1205 /* 1206 * rte_mempool_create_empty() has sanity check to refuse large cache 1207 * size compared to the number of elements. 1208 * CACHE_FLUSHTHRESH_MULTIPLIER is defined in a C file, so using a 1209 * constant number 2 instead. 1210 */ 1211 obj_num = RTE_MAX(obj_num, MLX5_MPRQ_MP_CACHE_SZ * 2); 1212 /* Check a mempool is already allocated and if it can be resued. */ 1213 if (mp != NULL && mp->elt_size >= obj_size && mp->size >= obj_num) { 1214 DRV_LOG(DEBUG, "port %u mempool %s is being reused", 1215 dev->data->port_id, mp->name); 1216 /* Reuse. */ 1217 goto exit; 1218 } else if (mp != NULL) { 1219 DRV_LOG(DEBUG, "port %u mempool %s should be resized, freeing it", 1220 dev->data->port_id, mp->name); 1221 /* 1222 * If failed to free, which means it may be still in use, no way 1223 * but to keep using the existing one. On buffer underrun, 1224 * packets will be memcpy'd instead of external buffer 1225 * attachment. 1226 */ 1227 if (mlx5_mprq_free_mp(dev)) { 1228 if (mp->elt_size >= obj_size) 1229 goto exit; 1230 else 1231 return -rte_errno; 1232 } 1233 } 1234 snprintf(name, sizeof(name), "port-%u-mprq", dev->data->port_id); 1235 mp = rte_mempool_create(name, obj_num, obj_size, MLX5_MPRQ_MP_CACHE_SZ, 1236 0, NULL, NULL, mlx5_mprq_buf_init, 1237 (void *)((uintptr_t)1 << strd_num_n), 1238 dev->device->numa_node, 0); 1239 if (mp == NULL) { 1240 DRV_LOG(ERR, 1241 "port %u failed to allocate a mempool for" 1242 " Multi-Packet RQ, count=%u, size=%u", 1243 dev->data->port_id, obj_num, obj_size); 1244 rte_errno = ENOMEM; 1245 return -rte_errno; 1246 } 1247 priv->mprq_mp = mp; 1248 exit: 1249 /* Set mempool for each Rx queue. */ 1250 for (i = 0; i != priv->rxqs_n; ++i) { 1251 struct mlx5_rxq_data *rxq = (*priv->rxqs)[i]; 1252 struct mlx5_rxq_ctrl *rxq_ctrl = container_of 1253 (rxq, struct mlx5_rxq_ctrl, rxq); 1254 1255 if (rxq == NULL || rxq_ctrl->type != MLX5_RXQ_TYPE_STANDARD) 1256 continue; 1257 rxq->mprq_mp = mp; 1258 } 1259 DRV_LOG(INFO, "port %u Multi-Packet RQ is configured", 1260 dev->data->port_id); 1261 return 0; 1262 } 1263 1264 #define MLX5_MAX_TCP_HDR_OFFSET ((unsigned int)(sizeof(struct rte_ether_hdr) + \ 1265 sizeof(struct rte_vlan_hdr) * 2 + \ 1266 sizeof(struct rte_ipv6_hdr))) 1267 #define MAX_TCP_OPTION_SIZE 40u 1268 #define MLX5_MAX_LRO_HEADER_FIX ((unsigned int)(MLX5_MAX_TCP_HDR_OFFSET + \ 1269 sizeof(struct rte_tcp_hdr) + \ 1270 MAX_TCP_OPTION_SIZE)) 1271 1272 /** 1273 * Adjust the maximum LRO massage size. 1274 * 1275 * @param dev 1276 * Pointer to Ethernet device. 1277 * @param idx 1278 * RX queue index. 1279 * @param max_lro_size 1280 * The maximum size for LRO packet. 1281 */ 1282 static void 1283 mlx5_max_lro_msg_size_adjust(struct rte_eth_dev *dev, uint16_t idx, 1284 uint32_t max_lro_size) 1285 { 1286 struct mlx5_priv *priv = dev->data->dev_private; 1287 1288 if (priv->config.hca_attr.lro_max_msg_sz_mode == 1289 MLX5_LRO_MAX_MSG_SIZE_START_FROM_L4 && max_lro_size > 1290 MLX5_MAX_TCP_HDR_OFFSET) 1291 max_lro_size -= MLX5_MAX_TCP_HDR_OFFSET; 1292 max_lro_size = RTE_MIN(max_lro_size, MLX5_MAX_LRO_SIZE); 1293 MLX5_ASSERT(max_lro_size >= MLX5_LRO_SEG_CHUNK_SIZE); 1294 max_lro_size /= MLX5_LRO_SEG_CHUNK_SIZE; 1295 if (priv->max_lro_msg_size) 1296 priv->max_lro_msg_size = 1297 RTE_MIN((uint32_t)priv->max_lro_msg_size, max_lro_size); 1298 else 1299 priv->max_lro_msg_size = max_lro_size; 1300 DRV_LOG(DEBUG, 1301 "port %u Rx Queue %u max LRO message size adjusted to %u bytes", 1302 dev->data->port_id, idx, 1303 priv->max_lro_msg_size * MLX5_LRO_SEG_CHUNK_SIZE); 1304 } 1305 1306 /** 1307 * Create a DPDK Rx queue. 1308 * 1309 * @param dev 1310 * Pointer to Ethernet device. 1311 * @param idx 1312 * RX queue index. 1313 * @param desc 1314 * Number of descriptors to configure in queue. 1315 * @param socket 1316 * NUMA socket on which memory must be allocated. 1317 * 1318 * @return 1319 * A DPDK queue object on success, NULL otherwise and rte_errno is set. 1320 */ 1321 struct mlx5_rxq_ctrl * 1322 mlx5_rxq_new(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, 1323 unsigned int socket, const struct rte_eth_rxconf *conf, 1324 const struct rte_eth_rxseg_split *rx_seg, uint16_t n_seg) 1325 { 1326 struct mlx5_priv *priv = dev->data->dev_private; 1327 struct mlx5_rxq_ctrl *tmpl; 1328 unsigned int mb_len = rte_pktmbuf_data_room_size(rx_seg[0].mp); 1329 struct mlx5_dev_config *config = &priv->config; 1330 uint64_t offloads = conf->offloads | 1331 dev->data->dev_conf.rxmode.offloads; 1332 unsigned int lro_on_queue = !!(offloads & DEV_RX_OFFLOAD_TCP_LRO); 1333 unsigned int max_rx_pkt_len = lro_on_queue ? 1334 dev->data->dev_conf.rxmode.max_lro_pkt_size : 1335 dev->data->dev_conf.rxmode.max_rx_pkt_len; 1336 unsigned int non_scatter_min_mbuf_size = max_rx_pkt_len + 1337 RTE_PKTMBUF_HEADROOM; 1338 unsigned int max_lro_size = 0; 1339 unsigned int first_mb_free_size = mb_len - RTE_PKTMBUF_HEADROOM; 1340 const int mprq_en = mlx5_check_mprq_support(dev) > 0 && n_seg == 1 && 1341 !rx_seg[0].offset && !rx_seg[0].length; 1342 unsigned int mprq_stride_nums = config->mprq.stride_num_n ? 1343 config->mprq.stride_num_n : MLX5_MPRQ_STRIDE_NUM_N; 1344 unsigned int mprq_stride_size = non_scatter_min_mbuf_size <= 1345 (1U << config->mprq.max_stride_size_n) ? 1346 log2above(non_scatter_min_mbuf_size) : MLX5_MPRQ_STRIDE_SIZE_N; 1347 unsigned int mprq_stride_cap = (config->mprq.stride_num_n ? 1348 (1U << config->mprq.stride_num_n) : (1U << mprq_stride_nums)) * 1349 (config->mprq.stride_size_n ? 1350 (1U << config->mprq.stride_size_n) : (1U << mprq_stride_size)); 1351 /* 1352 * Always allocate extra slots, even if eventually 1353 * the vector Rx will not be used. 1354 */ 1355 uint16_t desc_n = desc + config->rx_vec_en * MLX5_VPMD_DESCS_PER_LOOP; 1356 const struct rte_eth_rxseg_split *qs_seg = rx_seg; 1357 unsigned int tail_len; 1358 1359 tmpl = mlx5_malloc(MLX5_MEM_RTE | MLX5_MEM_ZERO, 1360 sizeof(*tmpl) + desc_n * sizeof(struct rte_mbuf *) + 1361 (!!mprq_en) * 1362 (desc >> mprq_stride_nums) * sizeof(struct mlx5_mprq_buf *), 1363 0, socket); 1364 if (!tmpl) { 1365 rte_errno = ENOMEM; 1366 return NULL; 1367 } 1368 MLX5_ASSERT(n_seg && n_seg <= MLX5_MAX_RXQ_NSEG); 1369 /* 1370 * Build the array of actual buffer offsets and lengths. 1371 * Pad with the buffers from the last memory pool if 1372 * needed to handle max size packets, replace zero length 1373 * with the buffer length from the pool. 1374 */ 1375 tail_len = max_rx_pkt_len; 1376 do { 1377 struct mlx5_eth_rxseg *hw_seg = 1378 &tmpl->rxq.rxseg[tmpl->rxq.rxseg_n]; 1379 uint32_t buf_len, offset, seg_len; 1380 1381 /* 1382 * For the buffers beyond descriptions offset is zero, 1383 * the first buffer contains head room. 1384 */ 1385 buf_len = rte_pktmbuf_data_room_size(qs_seg->mp); 1386 offset = (tmpl->rxq.rxseg_n >= n_seg ? 0 : qs_seg->offset) + 1387 (tmpl->rxq.rxseg_n ? 0 : RTE_PKTMBUF_HEADROOM); 1388 /* 1389 * For the buffers beyond descriptions the length is 1390 * pool buffer length, zero lengths are replaced with 1391 * pool buffer length either. 1392 */ 1393 seg_len = tmpl->rxq.rxseg_n >= n_seg ? buf_len : 1394 qs_seg->length ? 1395 qs_seg->length : 1396 (buf_len - offset); 1397 /* Check is done in long int, now overflows. */ 1398 if (buf_len < seg_len + offset) { 1399 DRV_LOG(ERR, "port %u Rx queue %u: Split offset/length " 1400 "%u/%u can't be satisfied", 1401 dev->data->port_id, idx, 1402 qs_seg->length, qs_seg->offset); 1403 rte_errno = EINVAL; 1404 goto error; 1405 } 1406 if (seg_len > tail_len) 1407 seg_len = buf_len - offset; 1408 if (++tmpl->rxq.rxseg_n > MLX5_MAX_RXQ_NSEG) { 1409 DRV_LOG(ERR, 1410 "port %u too many SGEs (%u) needed to handle" 1411 " requested maximum packet size %u, the maximum" 1412 " supported are %u", dev->data->port_id, 1413 tmpl->rxq.rxseg_n, max_rx_pkt_len, 1414 MLX5_MAX_RXQ_NSEG); 1415 rte_errno = ENOTSUP; 1416 goto error; 1417 } 1418 /* Build the actual scattering element in the queue object. */ 1419 hw_seg->mp = qs_seg->mp; 1420 MLX5_ASSERT(offset <= UINT16_MAX); 1421 MLX5_ASSERT(seg_len <= UINT16_MAX); 1422 hw_seg->offset = (uint16_t)offset; 1423 hw_seg->length = (uint16_t)seg_len; 1424 /* 1425 * Advance the segment descriptor, the padding is the based 1426 * on the attributes of the last descriptor. 1427 */ 1428 if (tmpl->rxq.rxseg_n < n_seg) 1429 qs_seg++; 1430 tail_len -= RTE_MIN(tail_len, seg_len); 1431 } while (tail_len || !rte_is_power_of_2(tmpl->rxq.rxseg_n)); 1432 MLX5_ASSERT(tmpl->rxq.rxseg_n && 1433 tmpl->rxq.rxseg_n <= MLX5_MAX_RXQ_NSEG); 1434 if (tmpl->rxq.rxseg_n > 1 && !(offloads & DEV_RX_OFFLOAD_SCATTER)) { 1435 DRV_LOG(ERR, "port %u Rx queue %u: Scatter offload is not" 1436 " configured and no enough mbuf space(%u) to contain " 1437 "the maximum RX packet length(%u) with head-room(%u)", 1438 dev->data->port_id, idx, mb_len, max_rx_pkt_len, 1439 RTE_PKTMBUF_HEADROOM); 1440 rte_errno = ENOSPC; 1441 goto error; 1442 } 1443 tmpl->type = MLX5_RXQ_TYPE_STANDARD; 1444 if (mlx5_mr_btree_init(&tmpl->rxq.mr_ctrl.cache_bh, 1445 MLX5_MR_BTREE_CACHE_N, socket)) { 1446 /* rte_errno is already set. */ 1447 goto error; 1448 } 1449 tmpl->socket = socket; 1450 if (dev->data->dev_conf.intr_conf.rxq) 1451 tmpl->irq = 1; 1452 /* 1453 * This Rx queue can be configured as a Multi-Packet RQ if all of the 1454 * following conditions are met: 1455 * - MPRQ is enabled. 1456 * - The number of descs is more than the number of strides. 1457 * - max_rx_pkt_len plus overhead is less than the max size 1458 * of a stride or mprq_stride_size is specified by a user. 1459 * Need to make sure that there are enough strides to encap 1460 * the maximum packet size in case mprq_stride_size is set. 1461 * Otherwise, enable Rx scatter if necessary. 1462 */ 1463 if (mprq_en && desc > (1U << mprq_stride_nums) && 1464 (non_scatter_min_mbuf_size <= 1465 (1U << config->mprq.max_stride_size_n) || 1466 (config->mprq.stride_size_n && 1467 non_scatter_min_mbuf_size <= mprq_stride_cap))) { 1468 /* TODO: Rx scatter isn't supported yet. */ 1469 tmpl->rxq.sges_n = 0; 1470 /* Trim the number of descs needed. */ 1471 desc >>= mprq_stride_nums; 1472 tmpl->rxq.strd_num_n = config->mprq.stride_num_n ? 1473 config->mprq.stride_num_n : mprq_stride_nums; 1474 tmpl->rxq.strd_sz_n = config->mprq.stride_size_n ? 1475 config->mprq.stride_size_n : mprq_stride_size; 1476 tmpl->rxq.strd_shift_en = MLX5_MPRQ_TWO_BYTE_SHIFT; 1477 tmpl->rxq.strd_scatter_en = 1478 !!(offloads & DEV_RX_OFFLOAD_SCATTER); 1479 tmpl->rxq.mprq_max_memcpy_len = RTE_MIN(first_mb_free_size, 1480 config->mprq.max_memcpy_len); 1481 max_lro_size = RTE_MIN(max_rx_pkt_len, 1482 (1u << tmpl->rxq.strd_num_n) * 1483 (1u << tmpl->rxq.strd_sz_n)); 1484 DRV_LOG(DEBUG, 1485 "port %u Rx queue %u: Multi-Packet RQ is enabled" 1486 " strd_num_n = %u, strd_sz_n = %u", 1487 dev->data->port_id, idx, 1488 tmpl->rxq.strd_num_n, tmpl->rxq.strd_sz_n); 1489 } else if (tmpl->rxq.rxseg_n == 1) { 1490 MLX5_ASSERT(max_rx_pkt_len <= first_mb_free_size); 1491 tmpl->rxq.sges_n = 0; 1492 max_lro_size = max_rx_pkt_len; 1493 } else if (offloads & DEV_RX_OFFLOAD_SCATTER) { 1494 unsigned int sges_n; 1495 1496 if (lro_on_queue && first_mb_free_size < 1497 MLX5_MAX_LRO_HEADER_FIX) { 1498 DRV_LOG(ERR, "Not enough space in the first segment(%u)" 1499 " to include the max header size(%u) for LRO", 1500 first_mb_free_size, MLX5_MAX_LRO_HEADER_FIX); 1501 rte_errno = ENOTSUP; 1502 goto error; 1503 } 1504 /* 1505 * Determine the number of SGEs needed for a full packet 1506 * and round it to the next power of two. 1507 */ 1508 sges_n = log2above(tmpl->rxq.rxseg_n); 1509 if (sges_n > MLX5_MAX_LOG_RQ_SEGS) { 1510 DRV_LOG(ERR, 1511 "port %u too many SGEs (%u) needed to handle" 1512 " requested maximum packet size %u, the maximum" 1513 " supported are %u", dev->data->port_id, 1514 1 << sges_n, max_rx_pkt_len, 1515 1u << MLX5_MAX_LOG_RQ_SEGS); 1516 rte_errno = ENOTSUP; 1517 goto error; 1518 } 1519 tmpl->rxq.sges_n = sges_n; 1520 max_lro_size = max_rx_pkt_len; 1521 } 1522 if (config->mprq.enabled && !mlx5_rxq_mprq_enabled(&tmpl->rxq)) 1523 DRV_LOG(WARNING, 1524 "port %u MPRQ is requested but cannot be enabled\n" 1525 " (requested: pkt_sz = %u, desc_num = %u," 1526 " rxq_num = %u, stride_sz = %u, stride_num = %u\n" 1527 " supported: min_rxqs_num = %u," 1528 " min_stride_sz = %u, max_stride_sz = %u).", 1529 dev->data->port_id, non_scatter_min_mbuf_size, 1530 desc, priv->rxqs_n, 1531 config->mprq.stride_size_n ? 1532 (1U << config->mprq.stride_size_n) : 1533 (1U << mprq_stride_size), 1534 config->mprq.stride_num_n ? 1535 (1U << config->mprq.stride_num_n) : 1536 (1U << mprq_stride_nums), 1537 config->mprq.min_rxqs_num, 1538 (1U << config->mprq.min_stride_size_n), 1539 (1U << config->mprq.max_stride_size_n)); 1540 DRV_LOG(DEBUG, "port %u maximum number of segments per packet: %u", 1541 dev->data->port_id, 1 << tmpl->rxq.sges_n); 1542 if (desc % (1 << tmpl->rxq.sges_n)) { 1543 DRV_LOG(ERR, 1544 "port %u number of Rx queue descriptors (%u) is not a" 1545 " multiple of SGEs per packet (%u)", 1546 dev->data->port_id, 1547 desc, 1548 1 << tmpl->rxq.sges_n); 1549 rte_errno = EINVAL; 1550 goto error; 1551 } 1552 mlx5_max_lro_msg_size_adjust(dev, idx, max_lro_size); 1553 /* Toggle RX checksum offload if hardware supports it. */ 1554 tmpl->rxq.csum = !!(offloads & DEV_RX_OFFLOAD_CHECKSUM); 1555 /* Configure Rx timestamp. */ 1556 tmpl->rxq.hw_timestamp = !!(offloads & DEV_RX_OFFLOAD_TIMESTAMP); 1557 tmpl->rxq.timestamp_rx_flag = 0; 1558 if (tmpl->rxq.hw_timestamp && rte_mbuf_dyn_rx_timestamp_register( 1559 &tmpl->rxq.timestamp_offset, 1560 &tmpl->rxq.timestamp_rx_flag) != 0) { 1561 DRV_LOG(ERR, "Cannot register Rx timestamp field/flag"); 1562 goto error; 1563 } 1564 /* Configure VLAN stripping. */ 1565 tmpl->rxq.vlan_strip = !!(offloads & DEV_RX_OFFLOAD_VLAN_STRIP); 1566 /* By default, FCS (CRC) is stripped by hardware. */ 1567 tmpl->rxq.crc_present = 0; 1568 tmpl->rxq.lro = lro_on_queue; 1569 if (offloads & DEV_RX_OFFLOAD_KEEP_CRC) { 1570 if (config->hw_fcs_strip) { 1571 /* 1572 * RQs used for LRO-enabled TIRs should not be 1573 * configured to scatter the FCS. 1574 */ 1575 if (lro_on_queue) 1576 DRV_LOG(WARNING, 1577 "port %u CRC stripping has been " 1578 "disabled but will still be performed " 1579 "by hardware, because LRO is enabled", 1580 dev->data->port_id); 1581 else 1582 tmpl->rxq.crc_present = 1; 1583 } else { 1584 DRV_LOG(WARNING, 1585 "port %u CRC stripping has been disabled but will" 1586 " still be performed by hardware, make sure MLNX_OFED" 1587 " and firmware are up to date", 1588 dev->data->port_id); 1589 } 1590 } 1591 DRV_LOG(DEBUG, 1592 "port %u CRC stripping is %s, %u bytes will be subtracted from" 1593 " incoming frames to hide it", 1594 dev->data->port_id, 1595 tmpl->rxq.crc_present ? "disabled" : "enabled", 1596 tmpl->rxq.crc_present << 2); 1597 /* Save port ID. */ 1598 tmpl->rxq.rss_hash = !!priv->rss_conf.rss_hf && 1599 (!!(dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS)); 1600 tmpl->rxq.port_id = dev->data->port_id; 1601 tmpl->priv = priv; 1602 tmpl->rxq.mp = rx_seg[0].mp; 1603 tmpl->rxq.elts_n = log2above(desc); 1604 tmpl->rxq.rq_repl_thresh = 1605 MLX5_VPMD_RXQ_RPLNSH_THRESH(desc_n); 1606 tmpl->rxq.elts = 1607 (struct rte_mbuf *(*)[desc_n])(tmpl + 1); 1608 tmpl->rxq.mprq_bufs = 1609 (struct mlx5_mprq_buf *(*)[desc])(*tmpl->rxq.elts + desc_n); 1610 #ifndef RTE_ARCH_64 1611 tmpl->rxq.uar_lock_cq = &priv->sh->uar_lock_cq; 1612 #endif 1613 tmpl->rxq.idx = idx; 1614 __atomic_fetch_add(&tmpl->refcnt, 1, __ATOMIC_RELAXED); 1615 LIST_INSERT_HEAD(&priv->rxqsctrl, tmpl, next); 1616 return tmpl; 1617 error: 1618 mlx5_mr_btree_free(&tmpl->rxq.mr_ctrl.cache_bh); 1619 mlx5_free(tmpl); 1620 return NULL; 1621 } 1622 1623 /** 1624 * Create a DPDK Rx hairpin queue. 1625 * 1626 * @param dev 1627 * Pointer to Ethernet device. 1628 * @param idx 1629 * RX queue index. 1630 * @param desc 1631 * Number of descriptors to configure in queue. 1632 * @param hairpin_conf 1633 * The hairpin binding configuration. 1634 * 1635 * @return 1636 * A DPDK queue object on success, NULL otherwise and rte_errno is set. 1637 */ 1638 struct mlx5_rxq_ctrl * 1639 mlx5_rxq_hairpin_new(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, 1640 const struct rte_eth_hairpin_conf *hairpin_conf) 1641 { 1642 struct mlx5_priv *priv = dev->data->dev_private; 1643 struct mlx5_rxq_ctrl *tmpl; 1644 1645 tmpl = mlx5_malloc(MLX5_MEM_RTE | MLX5_MEM_ZERO, sizeof(*tmpl), 0, 1646 SOCKET_ID_ANY); 1647 if (!tmpl) { 1648 rte_errno = ENOMEM; 1649 return NULL; 1650 } 1651 tmpl->type = MLX5_RXQ_TYPE_HAIRPIN; 1652 tmpl->socket = SOCKET_ID_ANY; 1653 tmpl->rxq.rss_hash = 0; 1654 tmpl->rxq.port_id = dev->data->port_id; 1655 tmpl->priv = priv; 1656 tmpl->rxq.mp = NULL; 1657 tmpl->rxq.elts_n = log2above(desc); 1658 tmpl->rxq.elts = NULL; 1659 tmpl->rxq.mr_ctrl.cache_bh = (struct mlx5_mr_btree) { 0 }; 1660 tmpl->hairpin_conf = *hairpin_conf; 1661 tmpl->rxq.idx = idx; 1662 __atomic_fetch_add(&tmpl->refcnt, 1, __ATOMIC_RELAXED); 1663 LIST_INSERT_HEAD(&priv->rxqsctrl, tmpl, next); 1664 return tmpl; 1665 } 1666 1667 /** 1668 * Get a Rx queue. 1669 * 1670 * @param dev 1671 * Pointer to Ethernet device. 1672 * @param idx 1673 * RX queue index. 1674 * 1675 * @return 1676 * A pointer to the queue if it exists, NULL otherwise. 1677 */ 1678 struct mlx5_rxq_ctrl * 1679 mlx5_rxq_get(struct rte_eth_dev *dev, uint16_t idx) 1680 { 1681 struct mlx5_priv *priv = dev->data->dev_private; 1682 struct mlx5_rxq_data *rxq_data = (*priv->rxqs)[idx]; 1683 struct mlx5_rxq_ctrl *rxq_ctrl = NULL; 1684 1685 if (rxq_data) { 1686 rxq_ctrl = container_of(rxq_data, struct mlx5_rxq_ctrl, rxq); 1687 __atomic_fetch_add(&rxq_ctrl->refcnt, 1, __ATOMIC_RELAXED); 1688 } 1689 return rxq_ctrl; 1690 } 1691 1692 /** 1693 * Release a Rx queue. 1694 * 1695 * @param dev 1696 * Pointer to Ethernet device. 1697 * @param idx 1698 * RX queue index. 1699 * 1700 * @return 1701 * 1 while a reference on it exists, 0 when freed. 1702 */ 1703 int 1704 mlx5_rxq_release(struct rte_eth_dev *dev, uint16_t idx) 1705 { 1706 struct mlx5_priv *priv = dev->data->dev_private; 1707 struct mlx5_rxq_ctrl *rxq_ctrl; 1708 1709 if (priv->rxqs == NULL || (*priv->rxqs)[idx] == NULL) 1710 return 0; 1711 rxq_ctrl = container_of((*priv->rxqs)[idx], struct mlx5_rxq_ctrl, rxq); 1712 if (__atomic_sub_fetch(&rxq_ctrl->refcnt, 1, __ATOMIC_RELAXED) > 1) 1713 return 1; 1714 if (rxq_ctrl->obj) { 1715 priv->obj_ops.rxq_obj_release(rxq_ctrl->obj); 1716 LIST_REMOVE(rxq_ctrl->obj, next); 1717 mlx5_free(rxq_ctrl->obj); 1718 rxq_ctrl->obj = NULL; 1719 } 1720 if (rxq_ctrl->type == MLX5_RXQ_TYPE_STANDARD) { 1721 rxq_free_elts(rxq_ctrl); 1722 dev->data->rx_queue_state[idx] = RTE_ETH_QUEUE_STATE_STOPPED; 1723 } 1724 if (!__atomic_load_n(&rxq_ctrl->refcnt, __ATOMIC_RELAXED)) { 1725 if (rxq_ctrl->type == MLX5_RXQ_TYPE_STANDARD) 1726 mlx5_mr_btree_free(&rxq_ctrl->rxq.mr_ctrl.cache_bh); 1727 LIST_REMOVE(rxq_ctrl, next); 1728 mlx5_free(rxq_ctrl); 1729 (*priv->rxqs)[idx] = NULL; 1730 } 1731 return 0; 1732 } 1733 1734 /** 1735 * Verify the Rx Queue list is empty 1736 * 1737 * @param dev 1738 * Pointer to Ethernet device. 1739 * 1740 * @return 1741 * The number of object not released. 1742 */ 1743 int 1744 mlx5_rxq_verify(struct rte_eth_dev *dev) 1745 { 1746 struct mlx5_priv *priv = dev->data->dev_private; 1747 struct mlx5_rxq_ctrl *rxq_ctrl; 1748 int ret = 0; 1749 1750 LIST_FOREACH(rxq_ctrl, &priv->rxqsctrl, next) { 1751 DRV_LOG(DEBUG, "port %u Rx Queue %u still referenced", 1752 dev->data->port_id, rxq_ctrl->rxq.idx); 1753 ++ret; 1754 } 1755 return ret; 1756 } 1757 1758 /** 1759 * Get a Rx queue type. 1760 * 1761 * @param dev 1762 * Pointer to Ethernet device. 1763 * @param idx 1764 * Rx queue index. 1765 * 1766 * @return 1767 * The Rx queue type. 1768 */ 1769 enum mlx5_rxq_type 1770 mlx5_rxq_get_type(struct rte_eth_dev *dev, uint16_t idx) 1771 { 1772 struct mlx5_priv *priv = dev->data->dev_private; 1773 struct mlx5_rxq_ctrl *rxq_ctrl = NULL; 1774 1775 if (idx < priv->rxqs_n && (*priv->rxqs)[idx]) { 1776 rxq_ctrl = container_of((*priv->rxqs)[idx], 1777 struct mlx5_rxq_ctrl, 1778 rxq); 1779 return rxq_ctrl->type; 1780 } 1781 return MLX5_RXQ_TYPE_UNDEFINED; 1782 } 1783 1784 /* 1785 * Get a Rx hairpin queue configuration. 1786 * 1787 * @param dev 1788 * Pointer to Ethernet device. 1789 * @param idx 1790 * Rx queue index. 1791 * 1792 * @return 1793 * Pointer to the configuration if a hairpin RX queue, otherwise NULL. 1794 */ 1795 const struct rte_eth_hairpin_conf * 1796 mlx5_rxq_get_hairpin_conf(struct rte_eth_dev *dev, uint16_t idx) 1797 { 1798 struct mlx5_priv *priv = dev->data->dev_private; 1799 struct mlx5_rxq_ctrl *rxq_ctrl = NULL; 1800 1801 if (idx < priv->rxqs_n && (*priv->rxqs)[idx]) { 1802 rxq_ctrl = container_of((*priv->rxqs)[idx], 1803 struct mlx5_rxq_ctrl, 1804 rxq); 1805 if (rxq_ctrl->type == MLX5_RXQ_TYPE_HAIRPIN) 1806 return &rxq_ctrl->hairpin_conf; 1807 } 1808 return NULL; 1809 } 1810 1811 /** 1812 * Match queues listed in arguments to queues contained in indirection table 1813 * object. 1814 * 1815 * @param ind_tbl 1816 * Pointer to indirection table to match. 1817 * @param queues 1818 * Queues to match to ques in indirection table. 1819 * @param queues_n 1820 * Number of queues in the array. 1821 * 1822 * @return 1823 * 1 if all queues in indirection table match 0 othrwise. 1824 */ 1825 static int 1826 mlx5_ind_table_obj_match_queues(const struct mlx5_ind_table_obj *ind_tbl, 1827 const uint16_t *queues, uint32_t queues_n) 1828 { 1829 return (ind_tbl->queues_n == queues_n) && 1830 (!memcmp(ind_tbl->queues, queues, 1831 ind_tbl->queues_n * sizeof(ind_tbl->queues[0]))); 1832 } 1833 1834 /** 1835 * Get an indirection table. 1836 * 1837 * @param dev 1838 * Pointer to Ethernet device. 1839 * @param queues 1840 * Queues entering in the indirection table. 1841 * @param queues_n 1842 * Number of queues in the array. 1843 * 1844 * @return 1845 * An indirection table if found. 1846 */ 1847 struct mlx5_ind_table_obj * 1848 mlx5_ind_table_obj_get(struct rte_eth_dev *dev, const uint16_t *queues, 1849 uint32_t queues_n) 1850 { 1851 struct mlx5_priv *priv = dev->data->dev_private; 1852 struct mlx5_ind_table_obj *ind_tbl; 1853 1854 rte_rwlock_read_lock(&priv->ind_tbls_lock); 1855 LIST_FOREACH(ind_tbl, &priv->ind_tbls, next) { 1856 if ((ind_tbl->queues_n == queues_n) && 1857 (memcmp(ind_tbl->queues, queues, 1858 ind_tbl->queues_n * sizeof(ind_tbl->queues[0])) 1859 == 0)) { 1860 __atomic_fetch_add(&ind_tbl->refcnt, 1, 1861 __ATOMIC_RELAXED); 1862 break; 1863 } 1864 } 1865 rte_rwlock_read_unlock(&priv->ind_tbls_lock); 1866 return ind_tbl; 1867 } 1868 1869 /** 1870 * Release an indirection table. 1871 * 1872 * @param dev 1873 * Pointer to Ethernet device. 1874 * @param ind_table 1875 * Indirection table to release. 1876 * @param standalone 1877 * Indirection table for Standalone queue. 1878 * 1879 * @return 1880 * 1 while a reference on it exists, 0 when freed. 1881 */ 1882 int 1883 mlx5_ind_table_obj_release(struct rte_eth_dev *dev, 1884 struct mlx5_ind_table_obj *ind_tbl, 1885 bool standalone) 1886 { 1887 struct mlx5_priv *priv = dev->data->dev_private; 1888 unsigned int i, ret; 1889 1890 rte_rwlock_write_lock(&priv->ind_tbls_lock); 1891 ret = __atomic_sub_fetch(&ind_tbl->refcnt, 1, __ATOMIC_RELAXED); 1892 if (!ret && !standalone) 1893 LIST_REMOVE(ind_tbl, next); 1894 rte_rwlock_write_unlock(&priv->ind_tbls_lock); 1895 if (ret) 1896 return 1; 1897 priv->obj_ops.ind_table_destroy(ind_tbl); 1898 for (i = 0; i != ind_tbl->queues_n; ++i) 1899 claim_nonzero(mlx5_rxq_release(dev, ind_tbl->queues[i])); 1900 mlx5_free(ind_tbl); 1901 return 0; 1902 } 1903 1904 /** 1905 * Verify the Rx Queue list is empty 1906 * 1907 * @param dev 1908 * Pointer to Ethernet device. 1909 * 1910 * @return 1911 * The number of object not released. 1912 */ 1913 int 1914 mlx5_ind_table_obj_verify(struct rte_eth_dev *dev) 1915 { 1916 struct mlx5_priv *priv = dev->data->dev_private; 1917 struct mlx5_ind_table_obj *ind_tbl; 1918 int ret = 0; 1919 1920 rte_rwlock_read_lock(&priv->ind_tbls_lock); 1921 LIST_FOREACH(ind_tbl, &priv->ind_tbls, next) { 1922 DRV_LOG(DEBUG, 1923 "port %u indirection table obj %p still referenced", 1924 dev->data->port_id, (void *)ind_tbl); 1925 ++ret; 1926 } 1927 rte_rwlock_read_unlock(&priv->ind_tbls_lock); 1928 return ret; 1929 } 1930 1931 /** 1932 * Setup an indirection table structure fields. 1933 * 1934 * @param dev 1935 * Pointer to Ethernet device. 1936 * @param ind_table 1937 * Indirection table to modify. 1938 * 1939 * @return 1940 * 0 on success, a negative errno value otherwise and rte_errno is set. 1941 */ 1942 int 1943 mlx5_ind_table_obj_setup(struct rte_eth_dev *dev, 1944 struct mlx5_ind_table_obj *ind_tbl) 1945 { 1946 struct mlx5_priv *priv = dev->data->dev_private; 1947 uint32_t queues_n = ind_tbl->queues_n; 1948 uint16_t *queues = ind_tbl->queues; 1949 unsigned int i, j; 1950 int ret = 0, err; 1951 const unsigned int n = rte_is_power_of_2(queues_n) ? 1952 log2above(queues_n) : 1953 log2above(priv->config.ind_table_max_size); 1954 1955 for (i = 0; i != queues_n; ++i) { 1956 if (!mlx5_rxq_get(dev, queues[i])) { 1957 ret = -rte_errno; 1958 goto error; 1959 } 1960 } 1961 ret = priv->obj_ops.ind_table_new(dev, n, ind_tbl); 1962 if (ret) 1963 goto error; 1964 __atomic_fetch_add(&ind_tbl->refcnt, 1, __ATOMIC_RELAXED); 1965 return 0; 1966 error: 1967 err = rte_errno; 1968 for (j = 0; j < i; j++) 1969 mlx5_rxq_release(dev, ind_tbl->queues[j]); 1970 rte_errno = err; 1971 DRV_LOG(DEBUG, "Port %u cannot setup indirection table.", 1972 dev->data->port_id); 1973 return ret; 1974 } 1975 1976 /** 1977 * Create an indirection table. 1978 * 1979 * @param dev 1980 * Pointer to Ethernet device. 1981 * @param queues 1982 * Queues entering in the indirection table. 1983 * @param queues_n 1984 * Number of queues in the array. 1985 * @param standalone 1986 * Indirection table for Standalone queue. 1987 * 1988 * @return 1989 * The Verbs/DevX object initialized, NULL otherwise and rte_errno is set. 1990 */ 1991 static struct mlx5_ind_table_obj * 1992 mlx5_ind_table_obj_new(struct rte_eth_dev *dev, const uint16_t *queues, 1993 uint32_t queues_n, bool standalone) 1994 { 1995 struct mlx5_priv *priv = dev->data->dev_private; 1996 struct mlx5_ind_table_obj *ind_tbl; 1997 int ret; 1998 1999 ind_tbl = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*ind_tbl) + 2000 queues_n * sizeof(uint16_t), 0, SOCKET_ID_ANY); 2001 if (!ind_tbl) { 2002 rte_errno = ENOMEM; 2003 return NULL; 2004 } 2005 ind_tbl->queues_n = queues_n; 2006 ind_tbl->queues = (uint16_t *)(ind_tbl + 1); 2007 memcpy(ind_tbl->queues, queues, queues_n * sizeof(*queues)); 2008 ret = mlx5_ind_table_obj_setup(dev, ind_tbl); 2009 if (ret < 0) { 2010 mlx5_free(ind_tbl); 2011 return NULL; 2012 } 2013 if (!standalone) { 2014 rte_rwlock_write_lock(&priv->ind_tbls_lock); 2015 LIST_INSERT_HEAD(&priv->ind_tbls, ind_tbl, next); 2016 rte_rwlock_write_unlock(&priv->ind_tbls_lock); 2017 } 2018 return ind_tbl; 2019 } 2020 2021 /** 2022 * Modify an indirection table. 2023 * 2024 * @param dev 2025 * Pointer to Ethernet device. 2026 * @param ind_table 2027 * Indirection table to modify. 2028 * @param queues 2029 * Queues replacement for the indirection table. 2030 * @param queues_n 2031 * Number of queues in the array. 2032 * @param standalone 2033 * Indirection table for Standalone queue. 2034 * 2035 * @return 2036 * 0 on success, a negative errno value otherwise and rte_errno is set. 2037 */ 2038 int 2039 mlx5_ind_table_obj_modify(struct rte_eth_dev *dev, 2040 struct mlx5_ind_table_obj *ind_tbl, 2041 uint16_t *queues, const uint32_t queues_n, 2042 bool standalone) 2043 { 2044 struct mlx5_priv *priv = dev->data->dev_private; 2045 unsigned int i, j; 2046 int ret = 0, err; 2047 const unsigned int n = rte_is_power_of_2(queues_n) ? 2048 log2above(queues_n) : 2049 log2above(priv->config.ind_table_max_size); 2050 2051 MLX5_ASSERT(standalone); 2052 RTE_SET_USED(standalone); 2053 if (__atomic_load_n(&ind_tbl->refcnt, __ATOMIC_RELAXED) > 1) { 2054 /* 2055 * Modification of indirection ntables having more than 1 2056 * reference unsupported. Intended for standalone indirection 2057 * tables only. 2058 */ 2059 DRV_LOG(DEBUG, 2060 "Port %u cannot modify indirection table (refcnt> 1).", 2061 dev->data->port_id); 2062 rte_errno = EINVAL; 2063 return -rte_errno; 2064 } 2065 for (i = 0; i != queues_n; ++i) { 2066 if (!mlx5_rxq_get(dev, queues[i])) { 2067 ret = -rte_errno; 2068 goto error; 2069 } 2070 } 2071 MLX5_ASSERT(priv->obj_ops.ind_table_modify); 2072 ret = priv->obj_ops.ind_table_modify(dev, n, queues, queues_n, ind_tbl); 2073 if (ret) 2074 goto error; 2075 for (j = 0; j < ind_tbl->queues_n; j++) 2076 mlx5_rxq_release(dev, ind_tbl->queues[j]); 2077 ind_tbl->queues_n = queues_n; 2078 ind_tbl->queues = queues; 2079 return 0; 2080 error: 2081 err = rte_errno; 2082 for (j = 0; j < i; j++) 2083 mlx5_rxq_release(dev, queues[j]); 2084 rte_errno = err; 2085 DRV_LOG(DEBUG, "Port %u cannot setup indirection table.", 2086 dev->data->port_id); 2087 return ret; 2088 } 2089 2090 int 2091 mlx5_hrxq_match_cb(void *tool_ctx __rte_unused, struct mlx5_list_entry *entry, 2092 void *cb_ctx) 2093 { 2094 struct mlx5_flow_cb_ctx *ctx = cb_ctx; 2095 struct mlx5_flow_rss_desc *rss_desc = ctx->data; 2096 struct mlx5_hrxq *hrxq = container_of(entry, typeof(*hrxq), entry); 2097 2098 return (hrxq->rss_key_len != rss_desc->key_len || 2099 memcmp(hrxq->rss_key, rss_desc->key, rss_desc->key_len) || 2100 hrxq->hash_fields != rss_desc->hash_fields || 2101 hrxq->ind_table->queues_n != rss_desc->queue_num || 2102 memcmp(hrxq->ind_table->queues, rss_desc->queue, 2103 rss_desc->queue_num * sizeof(rss_desc->queue[0]))); 2104 } 2105 2106 /** 2107 * Modify an Rx Hash queue configuration. 2108 * 2109 * @param dev 2110 * Pointer to Ethernet device. 2111 * @param hrxq 2112 * Index to Hash Rx queue to modify. 2113 * @param rss_key 2114 * RSS key for the Rx hash queue. 2115 * @param rss_key_len 2116 * RSS key length. 2117 * @param hash_fields 2118 * Verbs protocol hash field to make the RSS on. 2119 * @param queues 2120 * Queues entering in hash queue. In case of empty hash_fields only the 2121 * first queue index will be taken for the indirection table. 2122 * @param queues_n 2123 * Number of queues. 2124 * 2125 * @return 2126 * 0 on success, a negative errno value otherwise and rte_errno is set. 2127 */ 2128 int 2129 mlx5_hrxq_modify(struct rte_eth_dev *dev, uint32_t hrxq_idx, 2130 const uint8_t *rss_key, uint32_t rss_key_len, 2131 uint64_t hash_fields, 2132 const uint16_t *queues, uint32_t queues_n) 2133 { 2134 int err; 2135 struct mlx5_ind_table_obj *ind_tbl = NULL; 2136 struct mlx5_priv *priv = dev->data->dev_private; 2137 struct mlx5_hrxq *hrxq = 2138 mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_HRXQ], hrxq_idx); 2139 int ret; 2140 2141 if (!hrxq) { 2142 rte_errno = EINVAL; 2143 return -rte_errno; 2144 } 2145 /* validations */ 2146 if (hrxq->rss_key_len != rss_key_len) { 2147 /* rss_key_len is fixed size 40 byte & not supposed to change */ 2148 rte_errno = EINVAL; 2149 return -rte_errno; 2150 } 2151 queues_n = hash_fields ? queues_n : 1; 2152 if (mlx5_ind_table_obj_match_queues(hrxq->ind_table, 2153 queues, queues_n)) { 2154 ind_tbl = hrxq->ind_table; 2155 } else { 2156 if (hrxq->standalone) { 2157 /* 2158 * Replacement of indirection table unsupported for 2159 * stanalone hrxq objects (used by shared RSS). 2160 */ 2161 rte_errno = ENOTSUP; 2162 return -rte_errno; 2163 } 2164 ind_tbl = mlx5_ind_table_obj_get(dev, queues, queues_n); 2165 if (!ind_tbl) 2166 ind_tbl = mlx5_ind_table_obj_new(dev, queues, queues_n, 2167 hrxq->standalone); 2168 } 2169 if (!ind_tbl) { 2170 rte_errno = ENOMEM; 2171 return -rte_errno; 2172 } 2173 MLX5_ASSERT(priv->obj_ops.hrxq_modify); 2174 ret = priv->obj_ops.hrxq_modify(dev, hrxq, rss_key, 2175 hash_fields, ind_tbl); 2176 if (ret) { 2177 rte_errno = errno; 2178 goto error; 2179 } 2180 if (ind_tbl != hrxq->ind_table) { 2181 MLX5_ASSERT(!hrxq->standalone); 2182 mlx5_ind_table_obj_release(dev, hrxq->ind_table, 2183 hrxq->standalone); 2184 hrxq->ind_table = ind_tbl; 2185 } 2186 hrxq->hash_fields = hash_fields; 2187 memcpy(hrxq->rss_key, rss_key, rss_key_len); 2188 return 0; 2189 error: 2190 err = rte_errno; 2191 if (ind_tbl != hrxq->ind_table) { 2192 MLX5_ASSERT(!hrxq->standalone); 2193 mlx5_ind_table_obj_release(dev, ind_tbl, hrxq->standalone); 2194 } 2195 rte_errno = err; 2196 return -rte_errno; 2197 } 2198 2199 static void 2200 __mlx5_hrxq_remove(struct rte_eth_dev *dev, struct mlx5_hrxq *hrxq) 2201 { 2202 struct mlx5_priv *priv = dev->data->dev_private; 2203 2204 #ifdef HAVE_IBV_FLOW_DV_SUPPORT 2205 mlx5_glue->destroy_flow_action(hrxq->action); 2206 #endif 2207 priv->obj_ops.hrxq_destroy(hrxq); 2208 if (!hrxq->standalone) { 2209 mlx5_ind_table_obj_release(dev, hrxq->ind_table, 2210 hrxq->standalone); 2211 } 2212 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_HRXQ], hrxq->idx); 2213 } 2214 2215 /** 2216 * Release the hash Rx queue. 2217 * 2218 * @param dev 2219 * Pointer to Ethernet device. 2220 * @param hrxq 2221 * Index to Hash Rx queue to release. 2222 * 2223 * @param list 2224 * mlx5 list pointer. 2225 * @param entry 2226 * Hash queue entry pointer. 2227 */ 2228 void 2229 mlx5_hrxq_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry) 2230 { 2231 struct rte_eth_dev *dev = tool_ctx; 2232 struct mlx5_hrxq *hrxq = container_of(entry, typeof(*hrxq), entry); 2233 2234 __mlx5_hrxq_remove(dev, hrxq); 2235 } 2236 2237 static struct mlx5_hrxq * 2238 __mlx5_hrxq_create(struct rte_eth_dev *dev, 2239 struct mlx5_flow_rss_desc *rss_desc) 2240 { 2241 struct mlx5_priv *priv = dev->data->dev_private; 2242 const uint8_t *rss_key = rss_desc->key; 2243 uint32_t rss_key_len = rss_desc->key_len; 2244 bool standalone = !!rss_desc->shared_rss; 2245 const uint16_t *queues = 2246 standalone ? rss_desc->const_q : rss_desc->queue; 2247 uint32_t queues_n = rss_desc->queue_num; 2248 struct mlx5_hrxq *hrxq = NULL; 2249 uint32_t hrxq_idx = 0; 2250 struct mlx5_ind_table_obj *ind_tbl = rss_desc->ind_tbl; 2251 int ret; 2252 2253 queues_n = rss_desc->hash_fields ? queues_n : 1; 2254 if (!ind_tbl) 2255 ind_tbl = mlx5_ind_table_obj_get(dev, queues, queues_n); 2256 if (!ind_tbl) 2257 ind_tbl = mlx5_ind_table_obj_new(dev, queues, queues_n, 2258 standalone); 2259 if (!ind_tbl) 2260 return NULL; 2261 hrxq = mlx5_ipool_zmalloc(priv->sh->ipool[MLX5_IPOOL_HRXQ], &hrxq_idx); 2262 if (!hrxq) 2263 goto error; 2264 hrxq->standalone = standalone; 2265 hrxq->idx = hrxq_idx; 2266 hrxq->ind_table = ind_tbl; 2267 hrxq->rss_key_len = rss_key_len; 2268 hrxq->hash_fields = rss_desc->hash_fields; 2269 memcpy(hrxq->rss_key, rss_key, rss_key_len); 2270 ret = priv->obj_ops.hrxq_new(dev, hrxq, rss_desc->tunnel); 2271 if (ret < 0) 2272 goto error; 2273 return hrxq; 2274 error: 2275 if (!rss_desc->ind_tbl) 2276 mlx5_ind_table_obj_release(dev, ind_tbl, standalone); 2277 if (hrxq) 2278 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_HRXQ], hrxq_idx); 2279 return NULL; 2280 } 2281 2282 struct mlx5_list_entry * 2283 mlx5_hrxq_create_cb(void *tool_ctx, void *cb_ctx) 2284 { 2285 struct rte_eth_dev *dev = tool_ctx; 2286 struct mlx5_flow_cb_ctx *ctx = cb_ctx; 2287 struct mlx5_flow_rss_desc *rss_desc = ctx->data; 2288 struct mlx5_hrxq *hrxq; 2289 2290 hrxq = __mlx5_hrxq_create(dev, rss_desc); 2291 return hrxq ? &hrxq->entry : NULL; 2292 } 2293 2294 struct mlx5_list_entry * 2295 mlx5_hrxq_clone_cb(void *tool_ctx, struct mlx5_list_entry *entry, 2296 void *cb_ctx __rte_unused) 2297 { 2298 struct rte_eth_dev *dev = tool_ctx; 2299 struct mlx5_priv *priv = dev->data->dev_private; 2300 struct mlx5_hrxq *hrxq; 2301 uint32_t hrxq_idx = 0; 2302 2303 hrxq = mlx5_ipool_zmalloc(priv->sh->ipool[MLX5_IPOOL_HRXQ], &hrxq_idx); 2304 if (!hrxq) 2305 return NULL; 2306 memcpy(hrxq, entry, sizeof(*hrxq) + MLX5_RSS_HASH_KEY_LEN); 2307 hrxq->idx = hrxq_idx; 2308 return &hrxq->entry; 2309 } 2310 2311 void 2312 mlx5_hrxq_clone_free_cb(void *tool_ctx, struct mlx5_list_entry *entry) 2313 { 2314 struct rte_eth_dev *dev = tool_ctx; 2315 struct mlx5_priv *priv = dev->data->dev_private; 2316 struct mlx5_hrxq *hrxq = container_of(entry, typeof(*hrxq), entry); 2317 2318 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_HRXQ], hrxq->idx); 2319 } 2320 2321 /** 2322 * Get an Rx Hash queue. 2323 * 2324 * @param dev 2325 * Pointer to Ethernet device. 2326 * @param rss_desc 2327 * RSS configuration for the Rx hash queue. 2328 * 2329 * @return 2330 * An hash Rx queue index on success. 2331 */ 2332 uint32_t mlx5_hrxq_get(struct rte_eth_dev *dev, 2333 struct mlx5_flow_rss_desc *rss_desc) 2334 { 2335 struct mlx5_priv *priv = dev->data->dev_private; 2336 struct mlx5_hrxq *hrxq; 2337 struct mlx5_list_entry *entry; 2338 struct mlx5_flow_cb_ctx ctx = { 2339 .data = rss_desc, 2340 }; 2341 2342 if (rss_desc->shared_rss) { 2343 hrxq = __mlx5_hrxq_create(dev, rss_desc); 2344 } else { 2345 entry = mlx5_list_register(priv->hrxqs, &ctx); 2346 if (!entry) 2347 return 0; 2348 hrxq = container_of(entry, typeof(*hrxq), entry); 2349 } 2350 if (hrxq) 2351 return hrxq->idx; 2352 return 0; 2353 } 2354 2355 /** 2356 * Release the hash Rx queue. 2357 * 2358 * @param dev 2359 * Pointer to Ethernet device. 2360 * @param hrxq_idx 2361 * Index to Hash Rx queue to release. 2362 * 2363 * @return 2364 * 1 while a reference on it exists, 0 when freed. 2365 */ 2366 int mlx5_hrxq_release(struct rte_eth_dev *dev, uint32_t hrxq_idx) 2367 { 2368 struct mlx5_priv *priv = dev->data->dev_private; 2369 struct mlx5_hrxq *hrxq; 2370 2371 hrxq = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_HRXQ], hrxq_idx); 2372 if (!hrxq) 2373 return 0; 2374 if (!hrxq->standalone) 2375 return mlx5_list_unregister(priv->hrxqs, &hrxq->entry); 2376 __mlx5_hrxq_remove(dev, hrxq); 2377 return 0; 2378 } 2379 2380 /** 2381 * Create a drop Rx Hash queue. 2382 * 2383 * @param dev 2384 * Pointer to Ethernet device. 2385 * 2386 * @return 2387 * The Verbs/DevX object initialized, NULL otherwise and rte_errno is set. 2388 */ 2389 struct mlx5_hrxq * 2390 mlx5_drop_action_create(struct rte_eth_dev *dev) 2391 { 2392 struct mlx5_priv *priv = dev->data->dev_private; 2393 struct mlx5_hrxq *hrxq = NULL; 2394 int ret; 2395 2396 if (priv->drop_queue.hrxq) 2397 return priv->drop_queue.hrxq; 2398 hrxq = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*hrxq), 0, SOCKET_ID_ANY); 2399 if (!hrxq) { 2400 DRV_LOG(WARNING, 2401 "Port %u cannot allocate memory for drop queue.", 2402 dev->data->port_id); 2403 rte_errno = ENOMEM; 2404 goto error; 2405 } 2406 priv->drop_queue.hrxq = hrxq; 2407 hrxq->ind_table = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*hrxq->ind_table), 2408 0, SOCKET_ID_ANY); 2409 if (!hrxq->ind_table) { 2410 rte_errno = ENOMEM; 2411 goto error; 2412 } 2413 ret = priv->obj_ops.drop_action_create(dev); 2414 if (ret < 0) 2415 goto error; 2416 return hrxq; 2417 error: 2418 if (hrxq) { 2419 if (hrxq->ind_table) 2420 mlx5_free(hrxq->ind_table); 2421 priv->drop_queue.hrxq = NULL; 2422 mlx5_free(hrxq); 2423 } 2424 return NULL; 2425 } 2426 2427 /** 2428 * Release a drop hash Rx queue. 2429 * 2430 * @param dev 2431 * Pointer to Ethernet device. 2432 */ 2433 void 2434 mlx5_drop_action_destroy(struct rte_eth_dev *dev) 2435 { 2436 struct mlx5_priv *priv = dev->data->dev_private; 2437 struct mlx5_hrxq *hrxq = priv->drop_queue.hrxq; 2438 2439 if (!priv->drop_queue.hrxq) 2440 return; 2441 priv->obj_ops.drop_action_destroy(dev); 2442 mlx5_free(priv->drop_queue.rxq); 2443 mlx5_free(hrxq->ind_table); 2444 mlx5_free(hrxq); 2445 priv->drop_queue.rxq = NULL; 2446 priv->drop_queue.hrxq = NULL; 2447 } 2448 2449 /** 2450 * Verify the Rx Queue list is empty 2451 * 2452 * @param dev 2453 * Pointer to Ethernet device. 2454 * 2455 * @return 2456 * The number of object not released. 2457 */ 2458 uint32_t 2459 mlx5_hrxq_verify(struct rte_eth_dev *dev) 2460 { 2461 struct mlx5_priv *priv = dev->data->dev_private; 2462 2463 return mlx5_list_get_entry_num(priv->hrxqs); 2464 } 2465 2466 /** 2467 * Set the Rx queue timestamp conversion parameters 2468 * 2469 * @param[in] dev 2470 * Pointer to the Ethernet device structure. 2471 */ 2472 void 2473 mlx5_rxq_timestamp_set(struct rte_eth_dev *dev) 2474 { 2475 struct mlx5_priv *priv = dev->data->dev_private; 2476 struct mlx5_dev_ctx_shared *sh = priv->sh; 2477 struct mlx5_rxq_data *data; 2478 unsigned int i; 2479 2480 for (i = 0; i != priv->rxqs_n; ++i) { 2481 if (!(*priv->rxqs)[i]) 2482 continue; 2483 data = (*priv->rxqs)[i]; 2484 data->sh = sh; 2485 data->rt_timestamp = priv->config.rt_timestamp; 2486 } 2487 } 2488