LCOV - code coverage report
Current view: top level - drivers/net/mlx5 - mlx5_rx.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 782 0.0 %
Date: 2025-08-01 17:49:26 Functions: 0 23 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 646 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright 2021 6WIND S.A.
       3                 :            :  * Copyright 2021 Mellanox Technologies, Ltd
       4                 :            :  */
       5                 :            : 
       6                 :            : #include <stdint.h>
       7                 :            : #include <string.h>
       8                 :            : #include <stdlib.h>
       9                 :            : 
      10                 :            : #include <eal_export.h>
      11                 :            : #include <rte_mbuf.h>
      12                 :            : #include <rte_mempool.h>
      13                 :            : #include <rte_prefetch.h>
      14                 :            : #include <rte_common.h>
      15                 :            : #include <rte_branch_prediction.h>
      16                 :            : #include <rte_ether.h>
      17                 :            : #include <rte_cycles.h>
      18                 :            : #include <rte_flow.h>
      19                 :            : 
      20                 :            : #include <mlx5_prm.h>
      21                 :            : #include <mlx5_common.h>
      22                 :            : #include <mlx5_common_mr.h>
      23                 :            : #include <rte_pmd_mlx5.h>
      24                 :            : 
      25                 :            : #include "mlx5_autoconf.h"
      26                 :            : #include "mlx5_defs.h"
      27                 :            : #include "mlx5.h"
      28                 :            : #include "mlx5_utils.h"
      29                 :            : #include "mlx5_rxtx.h"
      30                 :            : #include "mlx5_devx.h"
      31                 :            : #include "mlx5_rx.h"
      32                 :            : #ifdef HAVE_MLX5_MSTFLINT
      33                 :            : #include <mstflint/mtcr.h>
      34                 :            : #endif
      35                 :            : 
      36                 :            : 
      37                 :            : static __rte_always_inline uint32_t
      38                 :            : rxq_cq_to_pkt_type(struct mlx5_rxq_data *rxq, volatile struct mlx5_cqe *cqe,
      39                 :            :                    volatile struct mlx5_mini_cqe8 *mcqe);
      40                 :            : 
      41                 :            : static __rte_always_inline int
      42                 :            : mlx5_rx_poll_len(struct mlx5_rxq_data *rxq, volatile struct mlx5_cqe *cqe,
      43                 :            :                  uint16_t cqe_n, uint16_t cqe_mask,
      44                 :            :                  volatile struct mlx5_mini_cqe8 **mcqe,
      45                 :            :                  uint16_t *skip_cnt, bool mprq, uint32_t *widx);
      46                 :            : 
      47                 :            : static __rte_always_inline uint32_t
      48                 :            : rxq_cq_to_ol_flags(volatile struct mlx5_cqe *cqe);
      49                 :            : 
      50                 :            : static __rte_always_inline void
      51                 :            : rxq_cq_to_mbuf(struct mlx5_rxq_data *rxq, struct rte_mbuf *pkt,
      52                 :            :                volatile struct mlx5_cqe *cqe,
      53                 :            :                volatile struct mlx5_mini_cqe8 *mcqe);
      54                 :            : 
      55                 :            : static inline void
      56                 :            : mlx5_lro_update_tcp_hdr(struct rte_tcp_hdr *__rte_restrict tcp,
      57                 :            :                         volatile struct mlx5_cqe *__rte_restrict cqe,
      58                 :            :                         uint32_t phcsum, uint8_t l4_type);
      59                 :            : 
      60                 :            : static inline void
      61                 :            : mlx5_lro_update_hdr(uint8_t *__rte_restrict padd,
      62                 :            :                     volatile struct mlx5_cqe *__rte_restrict cqe,
      63                 :            :                     volatile struct mlx5_mini_cqe8 *mcqe,
      64                 :            :                     struct mlx5_rxq_data *rxq, uint32_t len);
      65                 :            : 
      66                 :            : 
      67                 :            : /**
      68                 :            :  * Internal function to compute the number of used descriptors in an RX queue.
      69                 :            :  *
      70                 :            :  * @param rxq
      71                 :            :  *   The Rx queue.
      72                 :            :  *
      73                 :            :  * @return
      74                 :            :  *   The number of used Rx descriptor.
      75                 :            :  */
      76                 :            : static uint32_t
      77                 :          0 : rx_queue_count(struct mlx5_rxq_data *rxq)
      78                 :            : {
      79                 :            :         struct rxq_zip *zip = &rxq->zip;
      80                 :            :         volatile struct mlx5_cqe *cqe;
      81                 :          0 :         const unsigned int cqe_n = (1 << rxq->cqe_n);
      82                 :          0 :         const unsigned int sges_n = (1 << rxq->sges_n);
      83                 :          0 :         const unsigned int elts_n = (1 << rxq->elts_n);
      84                 :          0 :         const unsigned int strd_n = RTE_BIT32(rxq->log_strd_num);
      85                 :          0 :         const unsigned int cqe_cnt = cqe_n - 1;
      86                 :            :         unsigned int cq_ci, used;
      87                 :            : 
      88                 :            :         /* if we are processing a compressed cqe */
      89         [ #  # ]:          0 :         if (zip->ai) {
      90                 :          0 :                 used = zip->cqe_cnt - zip->ai;
      91                 :          0 :                 cq_ci = zip->cq_ci;
      92                 :            :         } else {
      93                 :            :                 used = 0;
      94                 :          0 :                 cq_ci = rxq->cq_ci;
      95                 :            :         }
      96                 :          0 :         cqe = &(*rxq->cqes)[cq_ci & cqe_cnt];
      97         [ #  # ]:          0 :         while (check_cqe(cqe, cqe_n, cq_ci) != MLX5_CQE_STATUS_HW_OWN) {
      98                 :            :                 int8_t op_own;
      99                 :            :                 unsigned int n;
     100                 :            : 
     101                 :          0 :                 op_own = cqe->op_own;
     102         [ #  # ]:          0 :                 if (MLX5_CQE_FORMAT(op_own) == MLX5_COMPRESSED)
     103                 :          0 :                         n = rte_be_to_cpu_32(cqe->byte_cnt);
     104                 :            :                 else
     105                 :            :                         n = 1;
     106                 :          0 :                 cq_ci += n;
     107                 :          0 :                 used += n;
     108                 :          0 :                 cqe = &(*rxq->cqes)[cq_ci & cqe_cnt];
     109                 :            :         }
     110                 :          0 :         used = RTE_MIN(used * sges_n, elts_n * strd_n);
     111                 :          0 :         return used;
     112                 :            : }
     113                 :            : 
     114                 :            : /**
     115                 :            :  * DPDK callback to check the status of a Rx descriptor.
     116                 :            :  *
     117                 :            :  * @param rx_queue
     118                 :            :  *   The Rx queue.
     119                 :            :  * @param[in] offset
     120                 :            :  *   The index of the descriptor in the ring.
     121                 :            :  *
     122                 :            :  * @return
     123                 :            :  *   The status of the Rx descriptor.
     124                 :            :  */
     125                 :            : int
     126                 :          0 : mlx5_rx_descriptor_status(void *rx_queue, uint16_t offset)
     127                 :            : {
     128                 :            :         struct mlx5_rxq_data *rxq = rx_queue;
     129                 :            : 
     130         [ #  # ]:          0 :         if (offset >= (1 << rxq->cqe_n)) {
     131                 :          0 :                 rte_errno = EINVAL;
     132                 :          0 :                 return -rte_errno;
     133                 :            :         }
     134         [ #  # ]:          0 :         if (offset < rx_queue_count(rxq))
     135                 :          0 :                 return RTE_ETH_RX_DESC_DONE;
     136                 :            :         return RTE_ETH_RX_DESC_AVAIL;
     137                 :            : }
     138                 :            : 
     139                 :            : /* Get rxq lwm percentage according to lwm number. */
     140                 :            : static uint8_t
     141                 :            : mlx5_rxq_lwm_to_percentage(struct mlx5_rxq_priv *rxq)
     142                 :            : {
     143                 :          0 :         struct mlx5_rxq_data *rxq_data = &rxq->ctrl->rxq;
     144                 :          0 :         uint32_t wqe_cnt = 1 << (rxq_data->elts_n - rxq_data->sges_n);
     145                 :            : 
     146                 :          0 :         return rxq->lwm * 100 / wqe_cnt;
     147                 :            : }
     148                 :            : 
     149                 :            : /**
     150                 :            :  * DPDK callback to get the RX queue information.
     151                 :            :  *
     152                 :            :  * @param dev
     153                 :            :  *   Pointer to the device structure.
     154                 :            :  *
     155                 :            :  * @param rx_queue_id
     156                 :            :  *   Rx queue identificator.
     157                 :            :  *
     158                 :            :  * @param qinfo
     159                 :            :  *   Pointer to the RX queue information structure.
     160                 :            :  *
     161                 :            :  * @return
     162                 :            :  *   None.
     163                 :            :  */
     164                 :            : 
     165                 :            : void
     166                 :          0 : mlx5_rxq_info_get(struct rte_eth_dev *dev, uint16_t rx_queue_id,
     167                 :            :                   struct rte_eth_rxq_info *qinfo)
     168                 :            : {
     169                 :          0 :         struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_rxq_ctrl_get(dev, rx_queue_id);
     170                 :          0 :         struct mlx5_rxq_data *rxq = mlx5_rxq_data_get(dev, rx_queue_id);
     171                 :          0 :         struct mlx5_rxq_priv *rxq_priv = mlx5_rxq_get(dev, rx_queue_id);
     172                 :            : 
     173         [ #  # ]:          0 :         if (!rxq)
     174                 :            :                 return;
     175                 :          0 :         qinfo->mp = mlx5_rxq_mprq_enabled(rxq) ?
     176         [ #  # ]:          0 :                                         rxq->mprq_mp : rxq->mp;
     177                 :          0 :         qinfo->conf.rx_thresh.pthresh = 0;
     178                 :          0 :         qinfo->conf.rx_thresh.hthresh = 0;
     179                 :          0 :         qinfo->conf.rx_thresh.wthresh = 0;
     180                 :          0 :         qinfo->conf.rx_free_thresh = rxq->rq_repl_thresh;
     181                 :          0 :         qinfo->conf.rx_drop_en = 1;
     182   [ #  #  #  # ]:          0 :         if (rxq_ctrl == NULL || rxq_ctrl->obj == NULL)
     183                 :          0 :                 qinfo->conf.rx_deferred_start = 0;
     184                 :            :         else
     185                 :          0 :                 qinfo->conf.rx_deferred_start = 1;
     186                 :          0 :         qinfo->conf.offloads = dev->data->dev_conf.rxmode.offloads;
     187                 :          0 :         qinfo->scattered_rx = dev->data->scattered_rx;
     188         [ #  # ]:          0 :         qinfo->nb_desc = mlx5_rxq_mprq_enabled(rxq) ?
     189                 :          0 :                 RTE_BIT32(rxq->elts_n) * RTE_BIT32(rxq->log_strd_num) :
     190                 :          0 :                 RTE_BIT32(rxq->elts_n);
     191         [ #  # ]:          0 :         qinfo->avail_thresh = rxq_priv ?
     192                 :            :                 mlx5_rxq_lwm_to_percentage(rxq_priv) : 0;
     193                 :            : }
     194                 :            : 
     195                 :            : /**
     196                 :            :  * DPDK callback to get the RX packet burst mode information.
     197                 :            :  *
     198                 :            :  * @param dev
     199                 :            :  *   Pointer to the device structure.
     200                 :            :  *
     201                 :            :  * @param rx_queue_id
     202                 :            :  *   Rx queue identification.
     203                 :            :  *
     204                 :            :  * @param mode
     205                 :            :  *   Pointer to the burts mode information.
     206                 :            :  *
     207                 :            :  * @return
     208                 :            :  *   0 as success, -EINVAL as failure.
     209                 :            :  */
     210                 :            : int
     211                 :          0 : mlx5_rx_burst_mode_get(struct rte_eth_dev *dev,
     212                 :            :                        uint16_t rx_queue_id __rte_unused,
     213                 :            :                        struct rte_eth_burst_mode *mode)
     214                 :            : {
     215                 :          0 :         eth_rx_burst_t pkt_burst = dev->rx_pkt_burst;
     216                 :          0 :         struct mlx5_rxq_priv *rxq = mlx5_rxq_get(dev, rx_queue_id);
     217                 :            : 
     218         [ #  # ]:          0 :         if (!rxq) {
     219                 :          0 :                 rte_errno = EINVAL;
     220                 :          0 :                 return -rte_errno;
     221                 :            :         }
     222         [ #  # ]:          0 :         if (pkt_burst == mlx5_rx_burst) {
     223                 :          0 :                 snprintf(mode->info, sizeof(mode->info), "%s", "Scalar");
     224         [ #  # ]:          0 :         } else if (pkt_burst == mlx5_rx_burst_out_of_order) {
     225                 :          0 :                 snprintf(mode->info, sizeof(mode->info), "%s", "Scalar Out-of-Order");
     226         [ #  # ]:          0 :         } else if (pkt_burst == mlx5_rx_burst_mprq) {
     227                 :          0 :                 snprintf(mode->info, sizeof(mode->info), "%s", "Multi-Packet RQ");
     228         [ #  # ]:          0 :         } else if (pkt_burst == mlx5_rx_burst_vec) {
     229                 :            : #if defined RTE_ARCH_X86_64
     230                 :          0 :                 snprintf(mode->info, sizeof(mode->info), "%s", "Vector SSE");
     231                 :            : #elif defined RTE_ARCH_ARM64
     232                 :            :                 snprintf(mode->info, sizeof(mode->info), "%s", "Vector Neon");
     233                 :            : #elif defined RTE_ARCH_PPC_64
     234                 :            :                 snprintf(mode->info, sizeof(mode->info), "%s", "Vector AltiVec");
     235                 :            : #else
     236                 :            :                 return -EINVAL;
     237                 :            : #endif
     238         [ #  # ]:          0 :         } else if (pkt_burst == mlx5_rx_burst_mprq_vec) {
     239                 :            : #if defined RTE_ARCH_X86_64
     240                 :          0 :                 snprintf(mode->info, sizeof(mode->info), "%s", "MPRQ Vector SSE");
     241                 :            : #elif defined RTE_ARCH_ARM64
     242                 :            :                 snprintf(mode->info, sizeof(mode->info), "%s", "MPRQ Vector Neon");
     243                 :            : #elif defined RTE_ARCH_PPC_64
     244                 :            :                 snprintf(mode->info, sizeof(mode->info), "%s", "MPRQ Vector AltiVec");
     245                 :            : #else
     246                 :            :                 return -EINVAL;
     247                 :            : #endif
     248                 :            :         } else {
     249                 :            :                 return -EINVAL;
     250                 :            :         }
     251                 :            :         return 0;
     252                 :            : }
     253                 :            : 
     254                 :            : /**
     255                 :            :  * DPDK callback to get the number of used descriptors in a RX queue.
     256                 :            :  *
     257                 :            :  * @param rx_queue
     258                 :            :  *   The Rx queue pointer.
     259                 :            :  *
     260                 :            :  * @return
     261                 :            :  *   The number of used rx descriptor.
     262                 :            :  *   -EINVAL if the queue is invalid
     263                 :            :  */
     264                 :            : uint32_t
     265                 :          0 : mlx5_rx_queue_count(void *rx_queue)
     266                 :            : {
     267                 :            :         struct mlx5_rxq_data *rxq = rx_queue;
     268                 :            :         struct rte_eth_dev *dev;
     269                 :            : 
     270         [ #  # ]:          0 :         if (!rxq) {
     271                 :          0 :                 rte_errno = EINVAL;
     272                 :          0 :                 return -rte_errno;
     273                 :            :         }
     274                 :            : 
     275                 :          0 :         dev = &rte_eth_devices[rxq->port_id];
     276                 :            : 
     277   [ #  #  #  # ]:          0 :         if (dev->rx_pkt_burst == NULL ||
     278                 :            :             dev->rx_pkt_burst == rte_eth_pkt_burst_dummy) {
     279                 :          0 :                 rte_errno = ENOTSUP;
     280                 :          0 :                 return -rte_errno;
     281                 :            :         }
     282                 :            : 
     283                 :          0 :         return rx_queue_count(rxq);
     284                 :            : }
     285                 :            : 
     286                 :            : #define CLB_VAL_IDX 0
     287                 :            : #define CLB_MSK_IDX 1
     288                 :            : static int
     289                 :          0 : mlx5_monitor_callback(const uint64_t value,
     290                 :            :                 const uint64_t opaque[RTE_POWER_MONITOR_OPAQUE_SZ])
     291                 :            : {
     292                 :          0 :         const uint64_t m = opaque[CLB_MSK_IDX];
     293                 :          0 :         const uint64_t v = opaque[CLB_VAL_IDX];
     294                 :            : 
     295         [ #  # ]:          0 :         return (value & m) == v ? -1 : 0;
     296                 :            : }
     297                 :            : 
     298                 :          0 : int mlx5_get_monitor_addr(void *rx_queue, struct rte_power_monitor_cond *pmc)
     299                 :            : {
     300                 :            :         struct mlx5_rxq_data *rxq = rx_queue;
     301                 :          0 :         const unsigned int cqe_num = 1 << rxq->cqe_n;
     302                 :          0 :         const unsigned int cqe_mask = cqe_num - 1;
     303                 :          0 :         const uint16_t idx = rxq->cq_ci & cqe_num;
     304                 :          0 :         const uint8_t vic = rxq->cq_ci >> rxq->cqe_n;
     305                 :          0 :         volatile struct mlx5_cqe *cqe = &(*rxq->cqes)[rxq->cq_ci & cqe_mask];
     306                 :            : 
     307         [ #  # ]:          0 :         if (unlikely(rxq->cqes == NULL)) {
     308                 :          0 :                 rte_errno = EINVAL;
     309                 :          0 :                 return -rte_errno;
     310                 :            :         }
     311         [ #  # ]:          0 :         if (rxq->cqe_comp_layout) {
     312                 :          0 :                 pmc->addr = &cqe->validity_iteration_count;
     313                 :          0 :                 pmc->opaque[CLB_VAL_IDX] = vic;
     314                 :          0 :                 pmc->opaque[CLB_MSK_IDX] = MLX5_CQE_VIC_INIT;
     315                 :            :         } else {
     316                 :          0 :                 pmc->addr = &cqe->op_own;
     317                 :          0 :                 pmc->opaque[CLB_VAL_IDX] = !!idx;
     318                 :          0 :                 pmc->opaque[CLB_MSK_IDX] = MLX5_CQE_OWNER_MASK;
     319                 :            :         }
     320                 :          0 :         pmc->fn = mlx5_monitor_callback;
     321                 :          0 :         pmc->size = sizeof(uint8_t);
     322                 :          0 :         return 0;
     323                 :            : }
     324                 :            : 
     325                 :            : /**
     326                 :            :  * Translate RX completion flags to packet type.
     327                 :            :  *
     328                 :            :  * @param[in] rxq
     329                 :            :  *   Pointer to RX queue structure.
     330                 :            :  * @param[in] cqe
     331                 :            :  *   Pointer to CQE.
     332                 :            :  *
     333                 :            :  * @note: fix mlx5_dev_supported_ptypes_get() if any change here.
     334                 :            :  *
     335                 :            :  * @return
     336                 :            :  *   Packet type for struct rte_mbuf.
     337                 :            :  */
     338                 :            : static inline uint32_t
     339                 :            : rxq_cq_to_pkt_type(struct mlx5_rxq_data *rxq, volatile struct mlx5_cqe *cqe,
     340                 :            :                                    volatile struct mlx5_mini_cqe8 *mcqe)
     341                 :            : {
     342                 :            :         uint8_t idx;
     343                 :            :         uint8_t ptype;
     344                 :          0 :         uint8_t pinfo = (cqe->pkt_info & 0x3) << 6;
     345                 :            : 
     346                 :            :         /* Get l3/l4 header from mini-CQE in case L3/L4 format*/
     347   [ #  #  #  #  :          0 :         if (mcqe == NULL ||
                   #  # ]
     348   [ #  #  #  #  :          0 :             rxq->mcqe_format != MLX5_CQE_RESP_FORMAT_L34H_STRIDX)
                   #  # ]
     349                 :          0 :                 ptype = (cqe->hdr_type_etc & 0xfc00) >> 10;
     350                 :            :         else
     351                 :          0 :                 ptype = mcqe->hdr_type >> 2;
     352                 :            :         /*
     353                 :            :          * The index to the array should have:
     354                 :            :          * bit[1:0] = l3_hdr_type
     355                 :            :          * bit[4:2] = l4_hdr_type
     356                 :            :          * bit[5] = ip_frag
     357                 :            :          * bit[6] = tunneled
     358                 :            :          * bit[7] = outer_l3_type
     359                 :            :          */
     360                 :          0 :         idx = pinfo | ptype;
     361                 :          0 :         return mlx5_ptype_table[idx] | rxq->tunnel * !!(idx & (1 << 6));
     362                 :            : }
     363                 :            : 
     364                 :          0 : static inline void mlx5_rq_win_reset(struct mlx5_rxq_data *rxq)
     365                 :            : {
     366                 :            :         static_assert(MLX5_WINOOO_BITS == (sizeof(*rxq->rq_win_data) * CHAR_BIT),
     367                 :            :                       "Invalid out-of-order window bitwidth");
     368                 :          0 :         rxq->rq_win_idx = 0;
     369                 :          0 :         rxq->rq_win_cnt = 0;
     370   [ #  #  #  # ]:          0 :         if (rxq->rq_win_data != NULL && rxq->rq_win_idx_mask != 0)
     371                 :          0 :                 memset(rxq->rq_win_data, 0, (rxq->rq_win_idx_mask + 1) * sizeof(*rxq->rq_win_data));
     372                 :          0 : }
     373                 :            : 
     374                 :          0 : static inline int mlx5_rq_win_init(struct mlx5_rxq_data *rxq)
     375                 :            : {
     376                 :            :         struct mlx5_rxq_ctrl *ctrl = container_of(rxq, struct mlx5_rxq_ctrl, rxq);
     377                 :            :         uint32_t win_size, win_mask;
     378                 :            : 
     379                 :            :         /* Set queue size as window size */
     380                 :          0 :         win_size = 1u << rxq->elts_n;
     381                 :          0 :         win_size = RTE_MAX(win_size, MLX5_WINOOO_BITS);
     382                 :          0 :         win_size = win_size / MLX5_WINOOO_BITS;
     383                 :          0 :         win_mask = win_size - 1;
     384   [ #  #  #  # ]:          0 :         if (win_mask != rxq->rq_win_idx_mask || rxq->rq_win_data == NULL) {
     385                 :          0 :                 mlx5_free(rxq->rq_win_data);
     386                 :          0 :                 rxq->rq_win_idx_mask = 0;
     387                 :          0 :                 rxq->rq_win_data = mlx5_malloc(MLX5_MEM_RTE,
     388                 :            :                                                win_size * sizeof(*rxq->rq_win_data),
     389                 :          0 :                                                RTE_CACHE_LINE_SIZE, ctrl->socket);
     390         [ #  # ]:          0 :                 if (rxq->rq_win_data == NULL)
     391                 :            :                         return -ENOMEM;
     392                 :          0 :                 rxq->rq_win_idx_mask = (uint16_t)win_mask;
     393                 :            :         }
     394                 :          0 :         mlx5_rq_win_reset(rxq);
     395                 :          0 :         return 0;
     396                 :            : }
     397                 :            : 
     398                 :            : static inline bool mlx5_rq_win_test(struct mlx5_rxq_data *rxq)
     399                 :            : {
     400                 :          0 :         return !!rxq->rq_win_cnt;
     401                 :            : }
     402                 :            : 
     403                 :            : static inline void mlx5_rq_win_update(struct mlx5_rxq_data *rxq, uint32_t delta)
     404                 :            : {
     405                 :            :         uint32_t idx;
     406                 :            : 
     407                 :          0 :         idx = (delta / MLX5_WINOOO_BITS) + rxq->rq_win_idx;
     408                 :          0 :         idx &= rxq->rq_win_idx_mask;
     409                 :          0 :         rxq->rq_win_cnt = 1;
     410                 :          0 :         rxq->rq_win_data[idx] |= 1u << (delta % MLX5_WINOOO_BITS);
     411                 :          0 : }
     412                 :            : 
     413                 :          0 : static inline uint32_t mlx5_rq_win_advance(struct mlx5_rxq_data *rxq, uint32_t delta)
     414                 :            : {
     415                 :            :         uint32_t idx;
     416                 :            : 
     417                 :          0 :         idx = (delta / MLX5_WINOOO_BITS) + rxq->rq_win_idx;
     418                 :          0 :         idx &= rxq->rq_win_idx_mask;
     419                 :          0 :         rxq->rq_win_data[idx] |= 1u << (delta % MLX5_WINOOO_BITS);
     420                 :          0 :         ++rxq->rq_win_cnt;
     421         [ #  # ]:          0 :         if (delta >= MLX5_WINOOO_BITS)
     422                 :            :                 return 0;
     423                 :            :         delta = 0;
     424         [ #  # ]:          0 :         while (~rxq->rq_win_data[idx] == 0) {
     425                 :          0 :                 rxq->rq_win_data[idx] = 0;
     426                 :            :                 MLX5_ASSERT(rxq->rq_win_cnt >= MLX5_WINOOO_BITS);
     427                 :          0 :                 rxq->rq_win_cnt -= MLX5_WINOOO_BITS;
     428                 :          0 :                 idx = (idx + 1) & rxq->rq_win_idx_mask;
     429                 :          0 :                 rxq->rq_win_idx = idx;
     430                 :          0 :                 delta += MLX5_WINOOO_BITS;
     431                 :            :         }
     432                 :            :         return delta;
     433                 :            : }
     434                 :            : 
     435                 :            : /**
     436                 :            :  * Initialize Rx WQ and indexes.
     437                 :            :  *
     438                 :            :  * @param[in] rxq
     439                 :            :  *   Pointer to RX queue structure.
     440                 :            :  */
     441                 :            : int
     442                 :          0 : mlx5_rxq_initialize(struct mlx5_rxq_data *rxq)
     443                 :            : {
     444                 :          0 :         const unsigned int wqe_n = 1 << rxq->elts_n;
     445                 :            :         unsigned int i;
     446                 :            : 
     447         [ #  # ]:          0 :         for (i = 0; (i != wqe_n); ++i) {
     448                 :            :                 volatile struct mlx5_wqe_data_seg *scat;
     449                 :            :                 uintptr_t addr;
     450                 :            :                 uint32_t byte_count;
     451                 :            :                 uint32_t lkey;
     452                 :            : 
     453         [ #  # ]:          0 :                 if (mlx5_rxq_mprq_enabled(rxq)) {
     454                 :          0 :                         struct mlx5_mprq_buf *buf = (*rxq->mprq_bufs)[i];
     455                 :            : 
     456                 :          0 :                         scat = &((volatile struct mlx5_wqe_mprq *)
     457                 :          0 :                                 rxq->wqes)[i].dseg;
     458                 :          0 :                         addr = (uintptr_t)mlx5_mprq_buf_addr
     459                 :            :                                         (buf, (uintptr_t)RTE_BIT32(rxq->log_strd_num));
     460         [ #  # ]:          0 :                         byte_count = RTE_BIT32(rxq->log_strd_sz) *
     461                 :            :                                      RTE_BIT32(rxq->log_strd_num);
     462                 :            :                         lkey = mlx5_rx_addr2mr(rxq, addr);
     463                 :            :                 } else {
     464                 :          0 :                         struct rte_mbuf *buf = (*rxq->elts)[i];
     465                 :            : 
     466                 :          0 :                         scat = &((volatile struct mlx5_wqe_data_seg *)
     467                 :          0 :                                         rxq->wqes)[i];
     468                 :          0 :                         addr = rte_pktmbuf_mtod(buf, uintptr_t);
     469         [ #  # ]:          0 :                         byte_count = DATA_LEN(buf);
     470                 :            :                         lkey = mlx5_rx_mb2mr(rxq, buf);
     471                 :            :                 }
     472                 :            :                 /* scat->addr must be able to store a pointer. */
     473                 :            :                 MLX5_ASSERT(sizeof(scat->addr) >= sizeof(uintptr_t));
     474                 :          0 :                 *scat = (struct mlx5_wqe_data_seg){
     475         [ #  # ]:          0 :                         .addr = rte_cpu_to_be_64(addr),
     476         [ #  # ]:          0 :                         .byte_count = rte_cpu_to_be_32(byte_count),
     477                 :            :                         .lkey = lkey,
     478                 :            :                 };
     479                 :            :         }
     480                 :          0 :         rxq->consumed_strd = 0;
     481                 :            :         rxq->decompressed = 0;
     482                 :          0 :         rxq->rq_pi = 0;
     483         [ #  # ]:          0 :         rxq->zip = (struct rxq_zip){
     484                 :            :                 .ai = 0,
     485                 :            :         };
     486                 :          0 :         rxq->elts_ci = mlx5_rxq_mprq_enabled(rxq) ?
     487         [ #  # ]:          0 :                 (wqe_n >> rxq->sges_n) * RTE_BIT32(rxq->log_strd_num) : 0;
     488                 :            :         /* Update doorbell counter. */
     489                 :          0 :         rxq->rq_ci = wqe_n >> rxq->sges_n;
     490                 :          0 :         rxq->rq_ci_ooo = rxq->rq_ci;
     491         [ #  # ]:          0 :         if (mlx5_rq_win_init(rxq))
     492                 :            :                 return -ENOMEM;
     493                 :          0 :         rte_io_wmb();
     494         [ #  # ]:          0 :         *rxq->rq_db = rte_cpu_to_be_32(rxq->rq_ci);
     495                 :          0 :         return 0;
     496                 :            : }
     497                 :            : 
     498                 :            : #define MLX5_ERROR_CQE_MASK 0x40000000
     499                 :            : /* Must be negative. */
     500                 :            : #define MLX5_REGULAR_ERROR_CQE_RET (-5)
     501                 :            : #define MLX5_CRITICAL_ERROR_CQE_RET (-4)
     502                 :            : /* Must not be negative. */
     503                 :            : #define MLX5_RECOVERY_ERROR_RET 0
     504                 :            : #define MLX5_RECOVERY_IGNORE_RET 1
     505                 :            : #define MLX5_RECOVERY_COMPLETED_RET 2
     506                 :            : 
     507                 :            : /**
     508                 :            :  * Handle a Rx error.
     509                 :            :  * The function inserts the RQ state to reset when the first error CQE is
     510                 :            :  * shown, then drains the CQ by the caller function loop. When the CQ is empty,
     511                 :            :  * it moves the RQ state to ready and initializes the RQ.
     512                 :            :  * Next CQE identification and error counting are in the caller responsibility.
     513                 :            :  *
     514                 :            :  * @param[in] rxq
     515                 :            :  *   Pointer to RX queue structure.
     516                 :            :  * @param[in] vec
     517                 :            :  *   1 when called from vectorized Rx burst, need to prepare mbufs for the RQ.
     518                 :            :  *   0 when called from non-vectorized Rx burst.
     519                 :            :  * @param[in] err_n
     520                 :            :  *   Number of CQEs to check for an error.
     521                 :            :  *
     522                 :            :  * @return
     523                 :            :  *   MLX5_RECOVERY_ERROR_RET in case of recovery error,
     524                 :            :  *   MLX5_RECOVERY_IGNORE_RET in case of non-critical error syndrome,
     525                 :            :  *   MLX5_RECOVERY_COMPLETED_RET in case of recovery is completed,
     526                 :            :  *   otherwise the CQE status after ignored error syndrome or queue reset.
     527                 :            :  */
     528                 :            : int
     529                 :          0 : mlx5_rx_err_handle(struct mlx5_rxq_data *rxq, uint8_t vec,
     530                 :            :                    uint16_t err_n, uint16_t *skip_cnt)
     531                 :            : {
     532                 :          0 :         const uint16_t cqe_n = 1 << rxq->cqe_n;
     533                 :          0 :         const uint16_t cqe_mask = cqe_n - 1;
     534                 :          0 :         const uint16_t wqe_n = 1 << rxq->elts_n;
     535                 :          0 :         const uint16_t strd_n = RTE_BIT32(rxq->log_strd_num);
     536                 :            :         struct mlx5_rxq_ctrl *rxq_ctrl =
     537                 :            :                         container_of(rxq, struct mlx5_rxq_ctrl, rxq);
     538                 :            :         union {
     539                 :            :                 volatile struct mlx5_cqe *cqe;
     540                 :            :                 volatile struct mlx5_error_cqe *err_cqe;
     541                 :            :         } u = {
     542                 :          0 :                 .cqe = &(*rxq->cqes)[(rxq->cq_ci - vec) & cqe_mask],
     543                 :            :         };
     544                 :            :         struct mlx5_mp_arg_queue_state_modify sm;
     545                 :            :         bool critical_syndrome = false;
     546                 :            :         int ret, i;
     547                 :            : 
     548   [ #  #  #  #  :          0 :         switch (rxq->err_state) {
                      # ]
     549                 :          0 :         case MLX5_RXQ_ERR_STATE_IGNORE:
     550         [ #  # ]:          0 :                 ret = check_cqe(u.cqe, cqe_n, rxq->cq_ci - vec);
     551                 :            :                 if (ret != MLX5_CQE_STATUS_ERR) {
     552                 :          0 :                         rxq->err_state = MLX5_RXQ_ERR_STATE_NO_ERROR;
     553                 :          0 :                         return ret;
     554                 :            :                 }
     555                 :            :                 /* Fall-through */
     556                 :            :         case MLX5_RXQ_ERR_STATE_NO_ERROR:
     557         [ #  # ]:          0 :                 for (i = 0; i < (int)err_n; i++) {
     558                 :          0 :                         u.cqe = &(*rxq->cqes)[(rxq->cq_ci - vec - i) & cqe_mask];
     559         [ #  # ]:          0 :                         if (MLX5_CQE_OPCODE(u.cqe->op_own) == MLX5_CQE_RESP_ERR) {
     560         [ #  # ]:          0 :                                 if (u.err_cqe->syndrome == MLX5_CQE_SYNDROME_LOCAL_QP_OP_ERR ||
     561         [ #  # ]:          0 :                                     u.err_cqe->syndrome == MLX5_CQE_SYNDROME_LOCAL_PROT_ERR ||
     562         [ #  # ]:          0 :                                     u.err_cqe->syndrome == MLX5_CQE_SYNDROME_WR_FLUSH_ERR)
     563                 :            :                                         critical_syndrome = true;
     564                 :            :                                 break;
     565                 :            :                         }
     566                 :            :                 }
     567                 :            :                 if (!critical_syndrome) {
     568         [ #  # ]:          0 :                         if (rxq->err_state == MLX5_RXQ_ERR_STATE_NO_ERROR) {
     569                 :          0 :                                 *skip_cnt = 0;
     570         [ #  # ]:          0 :                                 if (i == err_n)
     571                 :          0 :                                         rxq->err_state = MLX5_RXQ_ERR_STATE_IGNORE;
     572                 :            :                         }
     573                 :          0 :                         return MLX5_RECOVERY_IGNORE_RET;
     574                 :            :                 }
     575                 :          0 :                 rxq->err_state = MLX5_RXQ_ERR_STATE_NEED_RESET;
     576                 :            :                 /* Fall-through */
     577                 :          0 :         case MLX5_RXQ_ERR_STATE_NEED_RESET:
     578                 :          0 :                 sm.is_wq = 1;
     579                 :          0 :                 sm.queue_id = rxq->idx;
     580                 :          0 :                 sm.state = IBV_WQS_RESET;
     581         [ #  # ]:          0 :                 if (mlx5_queue_state_modify(RXQ_DEV(rxq_ctrl), &sm))
     582                 :            :                         return MLX5_RECOVERY_ERROR_RET;
     583                 :          0 :                 if (rxq_ctrl->dump_file_n <
     584         [ #  # ]:          0 :                     RXQ_PORT(rxq_ctrl)->config.max_dump_files_num) {
     585                 :          0 :                         MKSTR(err_str, "Unexpected CQE error syndrome "
     586                 :            :                               "0x%02x CQN = %u RQN = %u wqe_counter = %u"
     587                 :            :                               " rq_ci = %u cq_ci = %u", u.err_cqe->syndrome,
     588                 :            :                               rxq->cqn, rxq_ctrl->wqn,
     589                 :            :                               rte_be_to_cpu_16(u.err_cqe->wqe_counter),
     590                 :            :                               rxq->rq_ci << rxq->sges_n, rxq->cq_ci);
     591                 :          0 :                         MKSTR(name, "dpdk_mlx5_port_%u_rxq_%u_%u",
     592                 :            :                               rxq->port_id, rxq->idx, (uint32_t)rte_rdtsc());
     593                 :          0 :                         mlx5_dump_debug_information(name, NULL, err_str, 0);
     594                 :          0 :                         mlx5_dump_debug_information(name, "MLX5 Error CQ:",
     595                 :            :                                                     (const void *)((uintptr_t)
     596                 :          0 :                                                                     rxq->cqes),
     597                 :            :                                                     sizeof(*u.cqe) * cqe_n);
     598                 :          0 :                         mlx5_dump_debug_information(name, "MLX5 Error RQ:",
     599                 :            :                                                     (const void *)((uintptr_t)
     600                 :          0 :                                                                     rxq->wqes),
     601                 :          0 :                                                     16 * wqe_n);
     602                 :          0 :                         rxq_ctrl->dump_file_n++;
     603                 :            :                 }
     604                 :            :                 /* Try to find the actual cq_ci in hardware for shared queue. */
     605         [ #  # ]:          0 :                 if (rxq->shared)
     606                 :          0 :                         rxq_sync_cq(rxq);
     607                 :          0 :                 rxq->err_state = MLX5_RXQ_ERR_STATE_NEED_READY;
     608                 :            :                 /* Fall-through */
     609                 :          0 :         case MLX5_RXQ_ERR_STATE_NEED_READY:
     610         [ #  # ]:          0 :                 ret = check_cqe(u.cqe, cqe_n, rxq->cq_ci);
     611                 :            :                 if (ret == MLX5_CQE_STATUS_HW_OWN) {
     612                 :          0 :                         rte_io_wmb();
     613         [ #  # ]:          0 :                         *rxq->cq_db = rte_cpu_to_be_32(rxq->cq_ci);
     614                 :          0 :                         rte_io_wmb();
     615                 :            :                         /*
     616                 :            :                          * The RQ consumer index must be zeroed while moving
     617                 :            :                          * from RESET state to RDY state.
     618                 :            :                          */
     619                 :          0 :                         *rxq->rq_db = rte_cpu_to_be_32(0);
     620                 :          0 :                         rte_io_wmb();
     621                 :          0 :                         sm.is_wq = 1;
     622                 :          0 :                         sm.queue_id = rxq->idx;
     623                 :          0 :                         sm.state = IBV_WQS_RDY;
     624         [ #  # ]:          0 :                         if (mlx5_queue_state_modify(RXQ_DEV(rxq_ctrl), &sm))
     625                 :            :                                 return MLX5_RECOVERY_ERROR_RET;
     626         [ #  # ]:          0 :                         if (vec) {
     627                 :            :                                 const uint32_t elts_n =
     628                 :            :                                         mlx5_rxq_mprq_enabled(rxq) ?
     629         [ #  # ]:          0 :                                         wqe_n * strd_n : wqe_n;
     630                 :          0 :                                 const uint32_t e_mask = elts_n - 1;
     631                 :            :                                 uint32_t elts_ci =
     632                 :            :                                         mlx5_rxq_mprq_enabled(rxq) ?
     633         [ #  # ]:          0 :                                         rxq->elts_ci : rxq->rq_ci;
     634                 :            :                                 uint32_t elt_idx;
     635                 :            :                                 struct rte_mbuf **elt;
     636                 :          0 :                                 unsigned int n = elts_n - (elts_ci -
     637                 :          0 :                                                           rxq->rq_pi);
     638                 :            : 
     639         [ #  # ]:          0 :                                 for (i = 0; i < (int)n; ++i) {
     640                 :          0 :                                         elt_idx = (elts_ci + i) & e_mask;
     641                 :          0 :                                         elt = &(*rxq->elts)[elt_idx];
     642                 :          0 :                                         *elt = rte_mbuf_raw_alloc(rxq->mp);
     643         [ #  # ]:          0 :                                         if (!*elt) {
     644         [ #  # ]:          0 :                                                 for (i--; i >= 0; --i) {
     645                 :          0 :                                                         elt_idx = (elts_ci +
     646                 :            :                                                                    i) & elts_n;
     647                 :          0 :                                                         elt = &(*rxq->elts)
     648                 :            :                                                                 [elt_idx];
     649         [ #  # ]:          0 :                                                         rte_pktmbuf_free_seg
     650                 :            :                                                                 (*elt);
     651                 :            :                                                 }
     652                 :            :                                                 return MLX5_RECOVERY_ERROR_RET;
     653                 :            :                                         }
     654                 :            :                                 }
     655         [ #  # ]:          0 :                                 for (i = 0; i < (int)elts_n; ++i) {
     656                 :          0 :                                         elt = &(*rxq->elts)[i];
     657                 :          0 :                                         DATA_LEN(*elt) =
     658                 :          0 :                                                 (uint16_t)((*elt)->buf_len -
     659                 :            :                                                 rte_pktmbuf_headroom(*elt));
     660                 :            :                                 }
     661                 :            :                                 /* Padding with a fake mbuf for vec Rx. */
     662         [ #  # ]:          0 :                                 for (i = 0; i < MLX5_VPMD_DESCS_PER_LOOP; ++i)
     663                 :          0 :                                         (*rxq->elts)[elts_n + i] =
     664                 :          0 :                                                                 &rxq->fake_mbuf;
     665                 :            :                         }
     666         [ #  # ]:          0 :                         if (mlx5_rxq_initialize(rxq))
     667                 :            :                                 return MLX5_RECOVERY_ERROR_RET;
     668                 :          0 :                         rxq->err_state = MLX5_RXQ_ERR_STATE_NO_ERROR;
     669                 :          0 :                         return MLX5_RECOVERY_COMPLETED_RET;
     670                 :            :                 }
     671                 :            :                 return ret;
     672                 :            :         default:
     673                 :            :                 return MLX5_RECOVERY_ERROR_RET;
     674                 :            :         }
     675                 :            : }
     676                 :            : 
     677                 :            : /**
     678                 :            :  * Get size of the next packet for a given CQE. For compressed CQEs, the
     679                 :            :  * consumer index is updated only once all packets of the current one have
     680                 :            :  * been processed.
     681                 :            :  *
     682                 :            :  * @param rxq
     683                 :            :  *   Pointer to RX queue.
     684                 :            :  * @param cqe
     685                 :            :  *   CQE to process.
     686                 :            :  * @param cqe_n
     687                 :            :  *   Completion queue count.
     688                 :            :  * @param cqe_mask
     689                 :            :  *   Completion queue mask.
     690                 :            :  * @param[out] mcqe
     691                 :            :  *   Store pointer to mini-CQE if compressed. Otherwise, the pointer is not
     692                 :            :  *   written.
     693                 :            :  * @param[out] skip_cnt
     694                 :            :  *   Number of packets skipped due to recoverable errors.
     695                 :            :  * @param mprq
     696                 :            :  *   Indication if it is called from MPRQ.
     697                 :            :  * @param[out] widx
     698                 :            :  *   Store WQE index from CQE to support out of order completions. NULL
     699                 :            :  *   can be specified if index is not needed
     700                 :            :  *
     701                 :            :  * @return
     702                 :            :  *   0 in case of empty CQE,
     703                 :            :  *   MLX5_REGULAR_ERROR_CQE_RET in case of error CQE,
     704                 :            :  *   MLX5_CRITICAL_ERROR_CQE_RET in case of error CQE lead to Rx queue reset,
     705                 :            :  *   otherwise the packet size in regular RxQ,
     706                 :            :  *   and striding byte count format in mprq case.
     707                 :            :  */
     708                 :            : static inline int
     709                 :            : mlx5_rx_poll_len(struct mlx5_rxq_data *rxq, volatile struct mlx5_cqe *cqe,
     710                 :            :                  uint16_t cqe_n, uint16_t cqe_mask,
     711                 :            :                  volatile struct mlx5_mini_cqe8 **mcqe,
     712                 :            :                  uint16_t *skip_cnt, bool mprq, uint32_t *widx)
     713                 :            : {
     714                 :            :         struct rxq_zip *zip = &rxq->zip;
     715                 :            :         int len = 0, ret = 0;
     716                 :            :         uint32_t idx, end;
     717                 :            : 
     718                 :            :         do {
     719                 :          0 :                 len = 0;
     720                 :            :                 /* Process compressed data in the CQE and mini arrays. */
     721   [ #  #  #  #  :          0 :                 if (zip->ai) {
                   #  # ]
     722                 :          0 :                         volatile struct mlx5_mini_cqe8 (*mc)[8] =
     723                 :            :                                 (volatile struct mlx5_mini_cqe8 (*)[8])
     724                 :          0 :                                 (uintptr_t)(&(*rxq->cqes)[zip->ca &
     725                 :            :                                                         cqe_mask].pkt_info);
     726                 :          0 :                         len = rte_be_to_cpu_32((*mc)[zip->ai & 7].byte_cnt &
     727                 :            :                                                 rxq->byte_mask);
     728                 :            :                         if (widx != NULL)
     729                 :          0 :                                 *widx = zip->wqe_idx + zip->ai;
     730                 :          0 :                         *mcqe = &(*mc)[zip->ai & 7];
     731   [ #  #  #  #  :          0 :                         if (rxq->cqe_comp_layout) {
                   #  # ]
     732                 :          0 :                                 zip->ai++;
     733   [ #  #  #  #  :          0 :                                 if (unlikely(rxq->zip.ai == rxq->zip.cqe_cnt)) {
                   #  # ]
     734                 :          0 :                                         rxq->cq_ci = zip->cq_ci;
     735                 :          0 :                                         zip->ai = 0;
     736                 :            :                                 }
     737                 :            :                         } else {
     738   [ #  #  #  #  :          0 :                                 if ((++zip->ai & 7) == 0) {
                   #  # ]
     739                 :            :                                         /* Invalidate consumed CQEs */
     740                 :            :                                         idx = zip->ca;
     741                 :          0 :                                         end = zip->na;
     742   [ #  #  #  #  :          0 :                                         while (idx != end) {
                   #  # ]
     743                 :          0 :                                                 (*rxq->cqes)[idx & cqe_mask].op_own =
     744                 :            :                                                         MLX5_CQE_INVALIDATE;
     745                 :          0 :                                                 ++idx;
     746                 :            :                                         }
     747                 :            :                                         /*
     748                 :            :                                          * Increment consumer index to skip the number
     749                 :            :                                          * of CQEs consumed. Hardware leaves holes in
     750                 :            :                                          * the CQ ring for software use.
     751                 :            :                                          */
     752                 :          0 :                                         zip->ca = zip->na;
     753                 :          0 :                                         zip->na += 8;
     754                 :            :                                 }
     755   [ #  #  #  #  :          0 :                                 if (unlikely(rxq->zip.ai == rxq->zip.cqe_cnt)) {
                   #  # ]
     756                 :            :                                         /* Invalidate the rest */
     757                 :          0 :                                         idx = zip->ca;
     758                 :          0 :                                         end = zip->cq_ci;
     759                 :            : 
     760   [ #  #  #  #  :          0 :                                         while (idx != end) {
                   #  # ]
     761                 :          0 :                                                 (*rxq->cqes)[idx & cqe_mask].op_own =
     762                 :            :                                                         MLX5_CQE_INVALIDATE;
     763                 :          0 :                                                 ++idx;
     764                 :            :                                         }
     765                 :          0 :                                         rxq->cq_ci = zip->cq_ci;
     766                 :          0 :                                         zip->ai = 0;
     767                 :            :                                 }
     768                 :            :                         }
     769                 :            :                 /*
     770                 :            :                  * No compressed data, get next CQE and verify if it is
     771                 :            :                  * compressed.
     772                 :            :                  */
     773                 :            :                 } else {
     774                 :            :                         int8_t op_own;
     775                 :            :                         uint32_t cq_ci;
     776                 :            : 
     777                 :          0 :                         ret = (rxq->cqe_comp_layout) ?
     778   [ #  #  #  #  :          0 :                                 check_cqe_iteration(cqe, rxq->cqe_n, rxq->cq_ci) :
          #  #  #  #  #  
                #  #  # ]
     779   [ #  #  #  #  :          0 :                                 check_cqe(cqe, cqe_n, rxq->cq_ci);
                   #  # ]
     780   [ #  #  #  #  :          0 :                         if (unlikely(ret != MLX5_CQE_STATUS_SW_OWN)) {
                   #  # ]
     781   [ #  #  #  #  :          0 :                                 if (unlikely(ret == MLX5_CQE_STATUS_ERR ||
          #  #  #  #  #  
                #  #  # ]
     782                 :            :                                              rxq->err_state)) {
     783                 :            :                                         /* We should try to track out-pf-order WQE */
     784                 :            :                                         if (widx != NULL)
     785                 :          0 :                                                 *widx = rte_be_to_cpu_16(cqe->wqe_counter);
     786                 :          0 :                                         ret = mlx5_rx_err_handle(rxq, 0, 1, skip_cnt);
     787   [ #  #  #  #  :          0 :                                         if (ret == MLX5_CQE_STATUS_HW_OWN)
                   #  # ]
     788                 :            :                                                 return MLX5_ERROR_CQE_MASK;
     789                 :          0 :                                         if (ret == MLX5_RECOVERY_ERROR_RET ||
     790   [ #  #  #  #  :          0 :                                                 ret == MLX5_RECOVERY_COMPLETED_RET)
                   #  # ]
     791                 :            :                                                 return MLX5_CRITICAL_ERROR_CQE_RET;
     792   [ #  #  #  # ]:          0 :                                         if (!mprq && ret == MLX5_RECOVERY_IGNORE_RET) {
     793                 :          0 :                                                 *skip_cnt = 1;
     794                 :          0 :                                                 ++rxq->cq_ci;
     795                 :          0 :                                                 return MLX5_ERROR_CQE_MASK;
     796                 :            :                                         }
     797                 :            :                                 } else {
     798                 :            :                                         return 0;
     799                 :            :                                 }
     800                 :            :                         }
     801                 :            :                         /*
     802                 :            :                          * Introduce the local variable to have queue cq_ci
     803                 :            :                          * index in queue structure always consistent with
     804                 :            :                          * actual CQE boundary (not pointing to the middle
     805                 :            :                          * of compressed CQE session).
     806                 :            :                          */
     807                 :          0 :                         cq_ci = rxq->cq_ci + !rxq->cqe_comp_layout;
     808                 :          0 :                         op_own = cqe->op_own;
     809   [ #  #  #  #  :          0 :                         if (MLX5_CQE_FORMAT(op_own) == MLX5_COMPRESSED) {
                   #  # ]
     810                 :          0 :                                 volatile struct mlx5_mini_cqe8 (*mc)[8] =
     811                 :            :                                         (volatile struct mlx5_mini_cqe8 (*)[8])
     812                 :          0 :                                         (uintptr_t)(&(*rxq->cqes)
     813                 :          0 :                                                 [cq_ci & cqe_mask].pkt_info);
     814                 :            : 
     815                 :            :                                 /* Fix endianness. */
     816   [ #  #  #  #  :          0 :                                 zip->cqe_cnt = rxq->cqe_comp_layout ?
                   #  # ]
     817                 :          0 :                                         (MLX5_CQE_NUM_MINIS(op_own) + 1U) :
     818                 :          0 :                                         rte_be_to_cpu_32(cqe->byte_cnt);
     819                 :            :                                 /*
     820                 :            :                                  * Current mini array position is the one
     821                 :            :                                  * returned by check_cqe64().
     822                 :            :                                  *
     823                 :            :                                  * If completion comprises several mini arrays,
     824                 :            :                                  * as a special case the second one is located
     825                 :            :                                  * 7 CQEs after the initial CQE instead of 8
     826                 :            :                                  * for subsequent ones.
     827                 :            :                                 */
     828                 :          0 :                                 zip->ca = cq_ci;
     829                 :          0 :                                 zip->na = zip->ca + 7;
     830                 :            :                                 if (widx != NULL) {
     831                 :          0 :                                         zip->wqe_idx = rte_be_to_cpu_16(cqe->wqe_counter);
     832                 :          0 :                                         *widx = zip->wqe_idx;
     833                 :            :                                 }
     834                 :            :                                 /* Compute the next non compressed CQE. */
     835                 :          0 :                                 zip->cq_ci = rxq->cq_ci + zip->cqe_cnt;
     836                 :            :                                 /* Get packet size to return. */
     837                 :          0 :                                 len = rte_be_to_cpu_32((*mc)[0].byte_cnt &
     838                 :            :                                                         rxq->byte_mask);
     839                 :          0 :                                 *mcqe = &(*mc)[0];
     840   [ #  #  #  #  :          0 :                                 if (rxq->cqe_comp_layout) {
                   #  # ]
     841   [ #  #  #  #  :          0 :                                         if (MLX5_CQE_NUM_MINIS(op_own))
                   #  # ]
     842                 :          0 :                                                 zip->ai = 1;
     843                 :            :                                         else
     844                 :          0 :                                                 rxq->cq_ci = zip->cq_ci;
     845                 :            :                                 } else {
     846                 :          0 :                                         zip->ai = 1;
     847                 :            :                                         /* Prefetch all to be invalidated */
     848                 :            :                                         idx = zip->ca;
     849                 :            :                                         end = zip->cq_ci;
     850   [ #  #  #  #  :          0 :                                         while (idx != end) {
                   #  # ]
     851                 :          0 :                                                 rte_prefetch0(&(*rxq->cqes)[(idx) & cqe_mask]);
     852                 :          0 :                                                 ++idx;
     853                 :            :                                         }
     854                 :            :                                 }
     855                 :            :                         } else {
     856                 :          0 :                                 ++rxq->cq_ci;
     857                 :          0 :                                 len = rte_be_to_cpu_32(cqe->byte_cnt);
     858                 :            :                                 if (widx != NULL)
     859                 :          0 :                                         *widx = rte_be_to_cpu_16(cqe->wqe_counter);
     860   [ #  #  #  #  :          0 :                                 if (rxq->cqe_comp_layout) {
                   #  # ]
     861                 :            :                                         volatile struct mlx5_cqe *next;
     862                 :            : 
     863                 :          0 :                                         next = &(*rxq->cqes)[rxq->cq_ci & cqe_mask];
     864   [ #  #  #  #  :          0 :                                         ret = check_cqe_iteration(next, rxq->cqe_n, rxq->cq_ci);
                   #  # ]
     865                 :          0 :                                         if (ret != MLX5_CQE_STATUS_SW_OWN ||
     866   [ #  #  #  #  :          0 :                                             MLX5_CQE_FORMAT(next->op_own) == MLX5_COMPRESSED)
                   #  # ]
     867   [ #  #  #  #  :          0 :                                                 rte_memcpy(&rxq->title_cqe,
                   #  # ]
     868                 :            :                                                            (const void *)(uintptr_t)cqe,
     869                 :            :                                                            sizeof(struct mlx5_cqe));
     870                 :            :                                 }
     871                 :            :                         }
     872                 :            :                 }
     873   [ #  #  #  #  :          0 :                 if (unlikely(rxq->err_state)) {
                   #  # ]
     874   [ #  #  #  #  :          0 :                         if (rxq->err_state == MLX5_RXQ_ERR_STATE_IGNORE &&
          #  #  #  #  #  
                #  #  # ]
     875                 :            :                             ret == MLX5_CQE_STATUS_SW_OWN) {
     876                 :          0 :                                 rxq->err_state = MLX5_RXQ_ERR_STATE_NO_ERROR;
     877                 :          0 :                                 return len & MLX5_ERROR_CQE_MASK;
     878                 :            :                         }
     879                 :          0 :                         cqe = &(*rxq->cqes)[rxq->cq_ci & cqe_mask];
     880                 :          0 :                         ++rxq->stats.idropped;
     881                 :          0 :                         (*skip_cnt) += mprq ? (len & MLX5_MPRQ_STRIDE_NUM_MASK) >>
     882                 :            :                                 MLX5_MPRQ_STRIDE_NUM_SHIFT : 1;
     883                 :            :                 } else {
     884                 :            :                         return len;
     885                 :            :                 }
     886                 :            :         } while (1);
     887                 :            : }
     888                 :            : 
     889                 :            : /**
     890                 :            :  * Translate RX completion flags to offload flags.
     891                 :            :  *
     892                 :            :  * @param[in] cqe
     893                 :            :  *   Pointer to CQE.
     894                 :            :  *
     895                 :            :  * @return
     896                 :            :  *   Offload flags (ol_flags) for struct rte_mbuf.
     897                 :            :  */
     898                 :            : static inline uint32_t
     899                 :            : rxq_cq_to_ol_flags(volatile struct mlx5_cqe *cqe)
     900                 :            : {
     901                 :            :         uint32_t ol_flags = 0;
     902                 :          0 :         uint16_t flags = rte_be_to_cpu_16(cqe->hdr_type_etc);
     903                 :            : 
     904                 :          0 :         ol_flags =
     905                 :          0 :                 TRANSPOSE(flags,
     906                 :            :                           MLX5_CQE_RX_L3_HDR_VALID,
     907                 :          0 :                           RTE_MBUF_F_RX_IP_CKSUM_GOOD) |
     908                 :          0 :                 TRANSPOSE(flags,
     909                 :            :                           MLX5_CQE_RX_L4_HDR_VALID,
     910                 :            :                           RTE_MBUF_F_RX_L4_CKSUM_GOOD);
     911                 :            :         return ol_flags;
     912                 :            : }
     913                 :            : 
     914                 :            : /**
     915                 :            :  * Fill in mbuf fields from RX completion flags.
     916                 :            :  * Note that pkt->ol_flags should be initialized outside of this function.
     917                 :            :  *
     918                 :            :  * @param rxq
     919                 :            :  *   Pointer to RX queue.
     920                 :            :  * @param pkt
     921                 :            :  *   mbuf to fill.
     922                 :            :  * @param cqe
     923                 :            :  *   CQE to process.
     924                 :            :  * @param rss_hash_res
     925                 :            :  *   Packet RSS Hash result.
     926                 :            :  */
     927                 :            : static inline void
     928                 :            : rxq_cq_to_mbuf(struct mlx5_rxq_data *rxq, struct rte_mbuf *pkt,
     929                 :            :                volatile struct mlx5_cqe *cqe,
     930                 :            :                volatile struct mlx5_mini_cqe8 *mcqe)
     931                 :            : {
     932                 :            :         /* Update packet information. */
     933                 :          0 :         pkt->packet_type = rxq_cq_to_pkt_type(rxq, cqe, mcqe);
     934   [ #  #  #  #  :          0 :         pkt->port = unlikely(rxq->shared) ? cqe->user_index_low : rxq->port_id;
                   #  # ]
     935                 :            : 
     936   [ #  #  #  #  :          0 :         if (rxq->rss_hash) {
                   #  # ]
     937                 :            :                 uint32_t rss_hash_res = 0;
     938                 :            : 
     939                 :            :                 /* If compressed, take hash result from mini-CQE. */
     940   [ #  #  #  #  :          0 :                 if (mcqe == NULL ||
                   #  # ]
     941   [ #  #  #  #  :          0 :                     rxq->mcqe_format != MLX5_CQE_RESP_FORMAT_HASH)
                   #  # ]
     942                 :          0 :                         rss_hash_res = rte_be_to_cpu_32(cqe->rx_hash_res);
     943                 :            :                 else
     944                 :          0 :                         rss_hash_res = rte_be_to_cpu_32(mcqe->rx_hash_result);
     945   [ #  #  #  #  :          0 :                 if (rss_hash_res) {
                   #  # ]
     946                 :          0 :                         pkt->hash.rss = rss_hash_res;
     947                 :          0 :                         pkt->ol_flags |= RTE_MBUF_F_RX_RSS_HASH;
     948                 :            :                 }
     949                 :            :         }
     950   [ #  #  #  #  :          0 :         if (rxq->mark) {
                   #  # ]
     951                 :            :                 uint32_t mark = 0;
     952                 :            : 
     953                 :            :                 /* If compressed, take flow tag from mini-CQE. */
     954   [ #  #  #  #  :          0 :                 if (mcqe == NULL ||
                   #  # ]
     955   [ #  #  #  #  :          0 :                     rxq->mcqe_format != MLX5_CQE_RESP_FORMAT_FTAG_STRIDX)
                   #  # ]
     956                 :          0 :                         mark = cqe->sop_drop_qpn;
     957                 :            :                 else
     958                 :          0 :                         mark = ((mcqe->byte_cnt_flow & 0xff) << 8) |
     959                 :          0 :                                 (mcqe->flow_tag_high << 16);
     960   [ #  #  #  #  :          0 :                 if (MLX5_FLOW_MARK_IS_VALID(mark)) {
                   #  # ]
     961                 :          0 :                         pkt->ol_flags |= RTE_MBUF_F_RX_FDIR;
     962   [ #  #  #  #  :          0 :                         if (mark != RTE_BE32(MLX5_FLOW_MARK_DEFAULT)) {
                   #  # ]
     963                 :          0 :                                 pkt->ol_flags |= rxq->mark_flag;
     964                 :          0 :                                 pkt->hash.fdir.hi = mlx5_flow_mark_get(mark);
     965                 :            :                         }
     966                 :            :                 }
     967                 :            :         }
     968   [ #  #  #  #  :          0 :         if (rxq->dynf_meta) {
                   #  # ]
     969                 :          0 :                 uint32_t meta = rte_be_to_cpu_32(cqe->flow_table_metadata) &
     970                 :          0 :                         rxq->flow_meta_port_mask;
     971                 :            : 
     972   [ #  #  #  #  :          0 :                 if (meta) {
                   #  # ]
     973                 :          0 :                         pkt->ol_flags |= rxq->flow_meta_mask;
     974                 :          0 :                         *RTE_MBUF_DYNFIELD(pkt, rxq->flow_meta_offset,
     975                 :          0 :                                                 uint32_t *) = meta;
     976                 :            :                 }
     977                 :            :         }
     978   [ #  #  #  #  :          0 :         if (rxq->csum)
                   #  # ]
     979                 :          0 :                 pkt->ol_flags |= rxq_cq_to_ol_flags(cqe);
     980   [ #  #  #  #  :          0 :         if (rxq->vlan_strip) {
                   #  # ]
     981                 :            :                 bool vlan_strip;
     982                 :            : 
     983   [ #  #  #  #  :          0 :                 if (mcqe == NULL ||
                   #  # ]
     984   [ #  #  #  #  :          0 :                     rxq->mcqe_format != MLX5_CQE_RESP_FORMAT_L34H_STRIDX)
                   #  # ]
     985                 :          0 :                         vlan_strip = cqe->hdr_type_etc &
     986                 :            :                                      RTE_BE16(MLX5_CQE_VLAN_STRIPPED);
     987                 :            :                 else
     988                 :          0 :                         vlan_strip = mcqe->hdr_type &
     989                 :            :                                      RTE_BE16(MLX5_CQE_VLAN_STRIPPED);
     990   [ #  #  #  #  :          0 :                 if (vlan_strip) {
                   #  # ]
     991                 :          0 :                         pkt->ol_flags |= RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED;
     992                 :          0 :                         pkt->vlan_tci = rte_be_to_cpu_16(cqe->vlan_info);
     993                 :            :                 }
     994                 :            :         }
     995   [ #  #  #  #  :          0 :         if (rxq->hw_timestamp) {
                   #  # ]
     996                 :          0 :                 uint64_t ts = rte_be_to_cpu_64(cqe->timestamp);
     997                 :            : 
     998   [ #  #  #  #  :          0 :                 if (rxq->rt_timestamp)
                   #  # ]
     999                 :            :                         ts = mlx5_txpp_convert_rx_ts(rxq->sh, ts);
    1000                 :          0 :                 mlx5_timestamp_set(pkt, rxq->timestamp_offset, ts);
    1001                 :          0 :                 pkt->ol_flags |= rxq->timestamp_rx_flag;
    1002                 :            :         }
    1003                 :            : }
    1004                 :            : 
    1005                 :            : /**
    1006                 :            :  * DPDK callback for RX.
    1007                 :            :  *
    1008                 :            :  * @param dpdk_rxq
    1009                 :            :  *   Generic pointer to RX queue structure.
    1010                 :            :  * @param[out] pkts
    1011                 :            :  *   Array to store received packets.
    1012                 :            :  * @param pkts_n
    1013                 :            :  *   Maximum number of packets in array.
    1014                 :            :  *
    1015                 :            :  * @return
    1016                 :            :  *   Number of packets successfully received (<= pkts_n).
    1017                 :            :  */
    1018                 :            : uint16_t
    1019                 :          0 : mlx5_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
    1020                 :            : {
    1021                 :            :         struct mlx5_rxq_data *rxq = dpdk_rxq;
    1022                 :          0 :         const uint32_t wqe_n = 1 << rxq->elts_n;
    1023                 :          0 :         const uint32_t wqe_mask = wqe_n - 1;
    1024                 :          0 :         const uint32_t cqe_n = 1 << rxq->cqe_n;
    1025                 :          0 :         const uint32_t cqe_mask = cqe_n - 1;
    1026                 :          0 :         const unsigned int sges_n = rxq->sges_n;
    1027                 :            :         struct rte_mbuf *pkt = NULL;
    1028                 :            :         struct rte_mbuf *seg = NULL;
    1029                 :          0 :         volatile struct mlx5_cqe *cqe =
    1030                 :          0 :                 &(*rxq->cqes)[rxq->cq_ci & cqe_mask];
    1031                 :            :         unsigned int i = 0;
    1032                 :          0 :         unsigned int rq_ci = rxq->rq_ci << sges_n;
    1033                 :            :         int len = 0; /* keep its value across iterations. */
    1034                 :            : 
    1035         [ #  # ]:          0 :         while (pkts_n) {
    1036                 :            :                 uint16_t skip_cnt;
    1037                 :          0 :                 unsigned int idx = rq_ci & wqe_mask;
    1038                 :          0 :                 volatile struct mlx5_wqe_data_seg *wqe =
    1039                 :          0 :                         &((volatile struct mlx5_wqe_data_seg *)rxq->wqes)[idx];
    1040                 :          0 :                 struct rte_mbuf *rep = (*rxq->elts)[idx];
    1041                 :            :                 volatile struct mlx5_mini_cqe8 *mcqe = NULL;
    1042                 :            : 
    1043         [ #  # ]:          0 :                 if (pkt)
    1044                 :          0 :                         NEXT(seg) = rep;
    1045                 :            :                 seg = rep;
    1046                 :            :                 rte_prefetch0(seg);
    1047                 :            :                 rte_prefetch0(cqe);
    1048                 :            :                 rte_prefetch0(wqe);
    1049                 :            :                 /* Allocate the buf from the same pool. */
    1050                 :          0 :                 rep = rte_mbuf_raw_alloc(seg->pool);
    1051         [ #  # ]:          0 :                 if (unlikely(rep == NULL)) {
    1052                 :          0 :                         ++rxq->stats.rx_nombuf;
    1053         [ #  # ]:          0 :                         if (!pkt) {
    1054                 :            :                                 /*
    1055                 :            :                                  * no buffers before we even started,
    1056                 :            :                                  * bail out silently.
    1057                 :            :                                  */
    1058                 :            :                                 break;
    1059                 :            :                         }
    1060         [ #  # ]:          0 :                         while (pkt != seg) {
    1061                 :            :                                 MLX5_ASSERT(pkt != (*rxq->elts)[idx]);
    1062                 :          0 :                                 rep = NEXT(pkt);
    1063                 :          0 :                                 NEXT(pkt) = NULL;
    1064         [ #  # ]:          0 :                                 NB_SEGS(pkt) = 1;
    1065                 :            :                                 rte_mbuf_raw_free(pkt);
    1066                 :            :                                 pkt = rep;
    1067                 :            :                         }
    1068                 :          0 :                         rq_ci >>= sges_n;
    1069                 :          0 :                         ++rq_ci;
    1070                 :          0 :                         rq_ci <<= sges_n;
    1071                 :          0 :                         break;
    1072                 :            :                 }
    1073         [ #  # ]:          0 :                 if (!pkt) {
    1074                 :          0 :                         cqe = &(*rxq->cqes)[rxq->cq_ci & cqe_mask];
    1075                 :          0 :                         len = mlx5_rx_poll_len(rxq, cqe, cqe_n, cqe_mask,
    1076                 :            :                                                &mcqe, &skip_cnt, false, NULL);
    1077         [ #  # ]:          0 :                         if (unlikely(len & MLX5_ERROR_CQE_MASK)) {
    1078                 :            :                                 /* We drop packets with non-critical errors */
    1079                 :            :                                 rte_mbuf_raw_free(rep);
    1080         [ #  # ]:          0 :                                 if (len == MLX5_CRITICAL_ERROR_CQE_RET) {
    1081                 :          0 :                                         rq_ci = rxq->rq_ci << sges_n;
    1082                 :          0 :                                         break;
    1083                 :            :                                 }
    1084                 :            :                                 /* Skip specified amount of error CQEs packets */
    1085                 :          0 :                                 rq_ci >>= sges_n;
    1086                 :          0 :                                 rq_ci += skip_cnt;
    1087                 :          0 :                                 rq_ci <<= sges_n;
    1088                 :            :                                 MLX5_ASSERT(!pkt);
    1089                 :          0 :                                 continue;
    1090                 :            :                         }
    1091         [ #  # ]:          0 :                         if (len == 0) {
    1092                 :            :                                 rte_mbuf_raw_free(rep);
    1093                 :            :                                 break;
    1094                 :            :                         }
    1095                 :            :                         pkt = seg;
    1096                 :            :                         MLX5_ASSERT(len >= (rxq->crc_present << 2));
    1097                 :          0 :                         pkt->ol_flags &= RTE_MBUF_F_EXTERNAL;
    1098   [ #  #  #  # ]:          0 :                         if (rxq->cqe_comp_layout && mcqe)
    1099                 :          0 :                                 cqe = &rxq->title_cqe;
    1100                 :            :                         rxq_cq_to_mbuf(rxq, pkt, cqe, mcqe);
    1101         [ #  # ]:          0 :                         if (rxq->crc_present)
    1102                 :          0 :                                 len -= RTE_ETHER_CRC_LEN;
    1103                 :          0 :                         PKT_LEN(pkt) = len;
    1104         [ #  # ]:          0 :                         if (cqe->lro_num_seg > 1) {
    1105                 :          0 :                                 mlx5_lro_update_hdr
    1106                 :          0 :                                         (rte_pktmbuf_mtod(pkt, uint8_t *), cqe,
    1107                 :            :                                          mcqe, rxq, len);
    1108                 :          0 :                                 pkt->ol_flags |= RTE_MBUF_F_RX_LRO;
    1109                 :          0 :                                 pkt->tso_segsz = len / cqe->lro_num_seg;
    1110                 :            :                         }
    1111                 :            :                 }
    1112                 :          0 :                 DATA_LEN(rep) = DATA_LEN(seg);
    1113                 :          0 :                 PKT_LEN(rep) = PKT_LEN(seg);
    1114                 :          0 :                 SET_DATA_OFF(rep, DATA_OFF(seg));
    1115                 :          0 :                 PORT(rep) = PORT(seg);
    1116                 :          0 :                 (*rxq->elts)[idx] = rep;
    1117                 :            :                 /*
    1118                 :            :                  * Fill NIC descriptor with the new buffer. The lkey and size
    1119                 :            :                  * of the buffers are already known, only the buffer address
    1120                 :            :                  * changes.
    1121                 :            :                  */
    1122                 :          0 :                 wqe->addr = rte_cpu_to_be_64(rte_pktmbuf_mtod(rep, uintptr_t));
    1123                 :            :                 /* If there's only one MR, no need to replace LKey in WQE. */
    1124         [ #  # ]:          0 :                 if (unlikely(mlx5_mr_btree_len(&rxq->mr_ctrl.cache_bh) > 1))
    1125                 :          0 :                         wqe->lkey = mlx5_rx_mb2mr(rxq, rep);
    1126         [ #  # ]:          0 :                 if (len > DATA_LEN(seg)) {
    1127                 :          0 :                         len -= DATA_LEN(seg);
    1128                 :          0 :                         ++NB_SEGS(pkt);
    1129                 :          0 :                         ++rq_ci;
    1130                 :          0 :                         continue;
    1131                 :            :                 }
    1132                 :          0 :                 DATA_LEN(seg) = len;
    1133                 :            : #ifdef MLX5_PMD_SOFT_COUNTERS
    1134                 :            :                 /* Increment bytes counter. */
    1135                 :          0 :                 rxq->stats.ibytes += PKT_LEN(pkt);
    1136                 :            : #endif
    1137                 :            :                 /* Return packet. */
    1138                 :          0 :                 *(pkts++) = pkt;
    1139                 :            :                 pkt = NULL;
    1140                 :          0 :                 --pkts_n;
    1141                 :          0 :                 ++i;
    1142                 :            :                 /* Align consumer index to the next stride. */
    1143                 :          0 :                 rq_ci >>= sges_n;
    1144                 :          0 :                 ++rq_ci;
    1145                 :          0 :                 rq_ci <<= sges_n;
    1146                 :            :         }
    1147   [ #  #  #  # ]:          0 :         if (unlikely(i == 0 && ((rq_ci >> sges_n) == rxq->rq_ci)))
    1148                 :            :                 return 0;
    1149                 :            :         /* Update the consumer index. */
    1150                 :          0 :         rxq->rq_ci = rq_ci >> sges_n;
    1151                 :          0 :         rte_io_wmb();
    1152         [ #  # ]:          0 :         *rxq->cq_db = rte_cpu_to_be_32(rxq->cq_ci);
    1153                 :          0 :         rte_io_wmb();
    1154         [ #  # ]:          0 :         *rxq->rq_db = rte_cpu_to_be_32(rxq->rq_ci);
    1155                 :            : #ifdef MLX5_PMD_SOFT_COUNTERS
    1156                 :            :         /* Increment packets counter. */
    1157                 :          0 :         rxq->stats.ipackets += i;
    1158                 :            : #endif
    1159                 :          0 :         return i;
    1160                 :            : }
    1161                 :            : 
    1162                 :            : /**
    1163                 :            :  * DPDK callback for RX with Out-of-Order completions support.
    1164                 :            :  *
    1165                 :            :  * @param dpdk_rxq
    1166                 :            :  *   Generic pointer to RX queue structure.
    1167                 :            :  * @param[out] pkts
    1168                 :            :  *   Array to store received packets.
    1169                 :            :  * @param pkts_n
    1170                 :            :  *   Maximum number of packets in array.
    1171                 :            :  *
    1172                 :            :  * @return
    1173                 :            :  *   Number of packets successfully received (<= pkts_n).
    1174                 :            :  */
    1175                 :            : uint16_t
    1176                 :          0 : mlx5_rx_burst_out_of_order(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
    1177                 :            : {
    1178                 :            :         struct mlx5_rxq_data *rxq = dpdk_rxq;
    1179                 :          0 :         const uint32_t wqe_n = 1 << rxq->elts_n;
    1180                 :          0 :         const uint32_t wqe_mask = wqe_n - 1;
    1181                 :          0 :         const uint32_t cqe_n = 1 << rxq->cqe_n;
    1182                 :          0 :         const uint32_t cqe_mask = cqe_n - 1;
    1183                 :          0 :         const unsigned int sges_n = rxq->sges_n;
    1184                 :          0 :         const uint32_t pkt_mask = wqe_mask >> sges_n;
    1185                 :            :         struct rte_mbuf *pkt = NULL;
    1186                 :            :         struct rte_mbuf *seg = NULL;
    1187                 :          0 :         volatile struct mlx5_cqe *cqe =
    1188                 :          0 :                 &(*rxq->cqes)[rxq->cq_ci & cqe_mask];
    1189                 :            :         unsigned int i = 0;
    1190                 :            :         int len = 0; /* keep its value across iterations. */
    1191                 :          0 :         const uint32_t rq_ci = rxq->rq_ci;
    1192                 :            :         uint32_t idx = 0;
    1193                 :            : 
    1194                 :            :         do {
    1195                 :            :                 volatile struct mlx5_wqe_data_seg *wqe;
    1196                 :            :                 struct rte_mbuf *rep = NULL;
    1197                 :            :                 volatile struct mlx5_mini_cqe8 *mcqe = NULL;
    1198                 :            :                 uint32_t delta;
    1199                 :            :                 uint16_t skip_cnt;
    1200                 :            : 
    1201         [ #  # ]:          0 :                 if (!pkt) {
    1202                 :          0 :                         cqe = &(*rxq->cqes)[rxq->cq_ci & cqe_mask];
    1203                 :            :                         rte_prefetch0(cqe);
    1204                 :            :                         /* Allocate from the first packet mbuf pool */
    1205                 :          0 :                         rep = (*rxq->elts)[0];
    1206                 :            :                         /* We must allocate before CQE consuming to allow retry */
    1207                 :          0 :                         rep = rte_mbuf_raw_alloc(rep->pool);
    1208         [ #  # ]:          0 :                         if (unlikely(rep == NULL)) {
    1209                 :          0 :                                 ++rxq->stats.rx_nombuf;
    1210                 :          0 :                                 break;
    1211                 :            :                         }
    1212                 :          0 :                         len = mlx5_rx_poll_len(rxq, cqe, cqe_n, cqe_mask,
    1213                 :            :                                                &mcqe, &skip_cnt, false, &idx);
    1214         [ #  # ]:          0 :                         if (unlikely(len == MLX5_CRITICAL_ERROR_CQE_RET)) {
    1215                 :            :                                 rte_mbuf_raw_free(rep);
    1216                 :          0 :                                 mlx5_rq_win_reset(rxq);
    1217                 :          0 :                                 break;
    1218                 :            :                         }
    1219         [ #  # ]:          0 :                         if (len == 0) {
    1220                 :            :                                 rte_mbuf_raw_free(rep);
    1221                 :            :                                 break;
    1222                 :            :                         }
    1223                 :          0 :                         idx &= pkt_mask;
    1224                 :          0 :                         delta = (idx - rxq->rq_ci) & pkt_mask;
    1225                 :            :                         MLX5_ASSERT(delta < ((rxq->rq_win_idx_mask + 1) * MLX5_WINOOO_BITS));
    1226         [ #  # ]:          0 :                         if (likely(!mlx5_rq_win_test(rxq))) {
    1227                 :            :                                 /* No out of order completions in sliding window */
    1228         [ #  # ]:          0 :                                 if (likely(delta == 0))
    1229                 :          0 :                                         rxq->rq_ci++;
    1230                 :            :                                 else
    1231                 :            :                                         mlx5_rq_win_update(rxq, delta);
    1232                 :            :                         } else {
    1233                 :            :                                 /* We have out of order completions */
    1234                 :          0 :                                 rxq->rq_ci += mlx5_rq_win_advance(rxq, delta);
    1235                 :            :                         }
    1236         [ #  # ]:          0 :                         if (rxq->zip.ai == 0)
    1237                 :          0 :                                 rxq->rq_ci_ooo = rxq->rq_ci;
    1238                 :          0 :                         idx <<= sges_n;
    1239                 :            :                         /* We drop packets with non-critical errors */
    1240         [ #  # ]:          0 :                         if (unlikely(len & MLX5_ERROR_CQE_MASK)) {
    1241                 :            :                                 rte_mbuf_raw_free(rep);
    1242                 :          0 :                                 continue;
    1243                 :            :                         }
    1244                 :            :                 }
    1245                 :          0 :                 wqe = &((volatile struct mlx5_wqe_data_seg *)rxq->wqes)[idx];
    1246         [ #  # ]:          0 :                 if (unlikely(pkt))
    1247                 :          0 :                         NEXT(seg) = (*rxq->elts)[idx];
    1248                 :          0 :                 seg = (*rxq->elts)[idx];
    1249                 :            :                 rte_prefetch0(seg);
    1250                 :            :                 rte_prefetch0(wqe);
    1251                 :            :                 /* Allocate the buf from the same pool. */
    1252         [ #  # ]:          0 :                 if (unlikely(rep == NULL)) {
    1253                 :          0 :                         rep = rte_mbuf_raw_alloc(seg->pool);
    1254         [ #  # ]:          0 :                         if (unlikely(rep == NULL)) {
    1255                 :          0 :                                 ++rxq->stats.rx_nombuf;
    1256         [ #  # ]:          0 :                                 if (!pkt) {
    1257                 :            :                                         /*
    1258                 :            :                                          * no buffers before we even started,
    1259                 :            :                                          * bail out silently.
    1260                 :            :                                          */
    1261                 :            :                                         break;
    1262                 :            :                                 }
    1263         [ #  # ]:          0 :                                 while (pkt != seg) {
    1264                 :            :                                         MLX5_ASSERT(pkt != (*rxq->elts)[idx]);
    1265                 :          0 :                                         rep = NEXT(pkt);
    1266                 :          0 :                                         NEXT(pkt) = NULL;
    1267         [ #  # ]:          0 :                                         NB_SEGS(pkt) = 1;
    1268                 :            :                                         rte_mbuf_raw_free(pkt);
    1269                 :            :                                         pkt = rep;
    1270                 :            :                                 }
    1271                 :            :                                 break;
    1272                 :            :                         }
    1273                 :            :                 }
    1274         [ #  # ]:          0 :                 if (!pkt) {
    1275                 :            :                         pkt = seg;
    1276                 :            :                         MLX5_ASSERT(len >= (rxq->crc_present << 2));
    1277                 :          0 :                         pkt->ol_flags &= RTE_MBUF_F_EXTERNAL;
    1278   [ #  #  #  # ]:          0 :                         if (rxq->cqe_comp_layout && mcqe)
    1279                 :          0 :                                 cqe = &rxq->title_cqe;
    1280                 :            :                         rxq_cq_to_mbuf(rxq, pkt, cqe, mcqe);
    1281         [ #  # ]:          0 :                         if (rxq->crc_present)
    1282                 :          0 :                                 len -= RTE_ETHER_CRC_LEN;
    1283                 :          0 :                         PKT_LEN(pkt) = len;
    1284         [ #  # ]:          0 :                         if (cqe->lro_num_seg > 1) {
    1285                 :          0 :                                 mlx5_lro_update_hdr
    1286                 :          0 :                                         (rte_pktmbuf_mtod(pkt, uint8_t *), cqe,
    1287                 :            :                                          mcqe, rxq, len);
    1288                 :          0 :                                 pkt->ol_flags |= RTE_MBUF_F_RX_LRO;
    1289                 :          0 :                                 pkt->tso_segsz = len / cqe->lro_num_seg;
    1290                 :            :                         }
    1291                 :            :                 }
    1292                 :          0 :                 DATA_LEN(rep) = DATA_LEN(seg);
    1293                 :          0 :                 PKT_LEN(rep) = PKT_LEN(seg);
    1294                 :          0 :                 SET_DATA_OFF(rep, DATA_OFF(seg));
    1295                 :          0 :                 PORT(rep) = PORT(seg);
    1296                 :          0 :                 (*rxq->elts)[idx] = rep;
    1297                 :            :                 /*
    1298                 :            :                  * Fill NIC descriptor with the new buffer. The lkey and size
    1299                 :            :                  * of the buffers are already known, only the buffer address
    1300                 :            :                  * changes.
    1301                 :            :                  */
    1302                 :          0 :                 wqe->addr = rte_cpu_to_be_64(rte_pktmbuf_mtod(rep, uintptr_t));
    1303                 :            :                 /* If there's only one MR, no need to replace LKey in WQE. */
    1304         [ #  # ]:          0 :                 if (unlikely(mlx5_mr_btree_len(&rxq->mr_ctrl.cache_bh) > 1))
    1305                 :          0 :                         wqe->lkey = mlx5_rx_mb2mr(rxq, rep);
    1306         [ #  # ]:          0 :                 if (len > DATA_LEN(seg)) {
    1307                 :          0 :                         len -= DATA_LEN(seg);
    1308                 :          0 :                         ++NB_SEGS(pkt);
    1309                 :          0 :                         ++idx;
    1310                 :          0 :                         idx &= wqe_mask;
    1311                 :          0 :                         continue;
    1312                 :            :                 }
    1313                 :          0 :                 DATA_LEN(seg) = len;
    1314                 :            : #ifdef MLX5_PMD_SOFT_COUNTERS
    1315                 :            :                 /* Increment bytes counter. */
    1316                 :          0 :                 rxq->stats.ibytes += PKT_LEN(pkt);
    1317                 :            : #endif
    1318                 :            :                 /* Return packet. */
    1319                 :          0 :                 *(pkts++) = pkt;
    1320                 :            :                 pkt = NULL;
    1321                 :          0 :                 ++i;
    1322         [ #  # ]:          0 :         } while (i < pkts_n);
    1323   [ #  #  #  # ]:          0 :         if (unlikely(i == 0 && rq_ci == rxq->rq_ci_ooo))
    1324                 :            :                 return 0;
    1325                 :            :         /* Update the consumer index. */
    1326                 :          0 :         rte_io_wmb();
    1327         [ #  # ]:          0 :         *rxq->cq_db = rte_cpu_to_be_32(rxq->cq_ci);
    1328                 :          0 :         rte_io_wmb();
    1329         [ #  # ]:          0 :         *rxq->rq_db = rte_cpu_to_be_32(rxq->rq_ci_ooo);
    1330                 :            : #ifdef MLX5_PMD_SOFT_COUNTERS
    1331                 :            :         /* Increment packets counter. */
    1332                 :          0 :         rxq->stats.ipackets += i;
    1333                 :            : #endif
    1334                 :          0 :         return i;
    1335                 :            : }
    1336                 :            : 
    1337                 :            : /**
    1338                 :            :  * Update LRO packet TCP header.
    1339                 :            :  * The HW LRO feature doesn't update the TCP header after coalescing the
    1340                 :            :  * TCP segments but supplies information in CQE to fill it by SW.
    1341                 :            :  *
    1342                 :            :  * @param tcp
    1343                 :            :  *   Pointer to the TCP header.
    1344                 :            :  * @param cqe
    1345                 :            :  *   Pointer to the completion entry.
    1346                 :            :  * @param phcsum
    1347                 :            :  *   The L3 pseudo-header checksum.
    1348                 :            :  */
    1349                 :            : static inline void
    1350                 :          0 : mlx5_lro_update_tcp_hdr(struct rte_tcp_hdr *__rte_restrict tcp,
    1351                 :            :                         volatile struct mlx5_cqe *__rte_restrict cqe,
    1352                 :            :                         uint32_t phcsum, uint8_t l4_type)
    1353                 :            : {
    1354                 :            :         /*
    1355                 :            :          * The HW calculates only the TCP payload checksum, need to complete
    1356                 :            :          * the TCP header checksum and the L3 pseudo-header checksum.
    1357                 :            :          */
    1358                 :          0 :         uint32_t csum = phcsum + cqe->csum;
    1359                 :            : 
    1360         [ #  # ]:          0 :         if (l4_type == MLX5_L4_HDR_TYPE_TCP_EMPTY_ACK ||
    1361                 :            :             l4_type == MLX5_L4_HDR_TYPE_TCP_WITH_ACL) {
    1362                 :          0 :                 tcp->tcp_flags |= RTE_TCP_ACK_FLAG;
    1363                 :          0 :                 tcp->recv_ack = cqe->lro_ack_seq_num;
    1364                 :          0 :                 tcp->rx_win = cqe->lro_tcp_win;
    1365                 :            :         }
    1366         [ #  # ]:          0 :         if (cqe->lro_tcppsh_abort_dupack & MLX5_CQE_LRO_PUSH_MASK)
    1367                 :          0 :                 tcp->tcp_flags |= RTE_TCP_PSH_FLAG;
    1368                 :          0 :         tcp->cksum = 0;
    1369                 :          0 :         csum += rte_raw_cksum(tcp, (tcp->data_off >> 4) * 4);
    1370                 :          0 :         csum = ((csum & 0xffff0000) >> 16) + (csum & 0xffff);
    1371                 :          0 :         csum = ((csum & 0xffff0000) >> 16) + (csum & 0xffff);
    1372                 :          0 :         csum = (~csum) & 0xffff;
    1373         [ #  # ]:          0 :         if (csum == 0)
    1374                 :            :                 csum = 0xffff;
    1375                 :          0 :         tcp->cksum = csum;
    1376                 :          0 : }
    1377                 :            : 
    1378                 :            : /**
    1379                 :            :  * Update LRO packet headers.
    1380                 :            :  * The HW LRO feature doesn't update the L3/TCP headers after coalescing the
    1381                 :            :  * TCP segments but supply information in CQE to fill it by SW.
    1382                 :            :  *
    1383                 :            :  * @param padd
    1384                 :            :  *   The packet address.
    1385                 :            :  * @param cqe
    1386                 :            :  *   Pointer to the completion entry.
    1387                 :            :  * @param len
    1388                 :            :  *   The packet length.
    1389                 :            :  */
    1390                 :            : static inline void
    1391                 :          0 : mlx5_lro_update_hdr(uint8_t *__rte_restrict padd,
    1392                 :            :                     volatile struct mlx5_cqe *__rte_restrict cqe,
    1393                 :            :                     volatile struct mlx5_mini_cqe8 *mcqe,
    1394                 :            :                     struct mlx5_rxq_data *rxq, uint32_t len)
    1395                 :            : {
    1396                 :            :         union {
    1397                 :            :                 struct rte_ether_hdr *eth;
    1398                 :            :                 struct rte_vlan_hdr *vlan;
    1399                 :            :                 struct rte_ipv4_hdr *ipv4;
    1400                 :            :                 struct rte_ipv6_hdr *ipv6;
    1401                 :            :                 struct rte_tcp_hdr *tcp;
    1402                 :            :                 uint8_t *hdr;
    1403                 :            :         } h = {
    1404                 :            :                 .hdr = padd,
    1405                 :            :         };
    1406                 :          0 :         uint16_t proto = h.eth->ether_type;
    1407                 :            :         uint32_t phcsum;
    1408                 :            :         uint8_t l4_type;
    1409                 :            : 
    1410                 :          0 :         h.eth++;
    1411                 :          0 :         while (proto == RTE_BE16(RTE_ETHER_TYPE_VLAN) ||
    1412         [ #  # ]:          0 :                proto == RTE_BE16(RTE_ETHER_TYPE_QINQ)) {
    1413                 :          0 :                 proto = h.vlan->eth_proto;
    1414                 :          0 :                 h.vlan++;
    1415                 :            :         }
    1416         [ #  # ]:          0 :         if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV4)) {
    1417                 :          0 :                 h.ipv4->time_to_live = cqe->lro_min_ttl;
    1418         [ #  # ]:          0 :                 h.ipv4->total_length = rte_cpu_to_be_16(len - (h.hdr - padd));
    1419                 :          0 :                 h.ipv4->hdr_checksum = 0;
    1420                 :          0 :                 h.ipv4->hdr_checksum = rte_ipv4_cksum(h.ipv4);
    1421                 :          0 :                 phcsum = rte_ipv4_phdr_cksum(h.ipv4, 0);
    1422                 :          0 :                 h.ipv4++;
    1423                 :            :         } else {
    1424                 :          0 :                 h.ipv6->hop_limits = cqe->lro_min_ttl;
    1425         [ #  # ]:          0 :                 h.ipv6->payload_len = rte_cpu_to_be_16(len - (h.hdr - padd) -
    1426                 :            :                                                        sizeof(*h.ipv6));
    1427                 :          0 :                 phcsum = rte_ipv6_phdr_cksum(h.ipv6, 0);
    1428                 :          0 :                 h.ipv6++;
    1429                 :            :         }
    1430         [ #  # ]:          0 :         if (mcqe == NULL ||
    1431         [ #  # ]:          0 :             rxq->mcqe_format != MLX5_CQE_RESP_FORMAT_L34H_STRIDX)
    1432                 :          0 :                 l4_type = (rte_be_to_cpu_16(cqe->hdr_type_etc) &
    1433                 :          0 :                            MLX5_CQE_L4_TYPE_MASK) >> MLX5_CQE_L4_TYPE_SHIFT;
    1434                 :            :         else
    1435                 :          0 :                 l4_type = (rte_be_to_cpu_16(mcqe->hdr_type) &
    1436                 :          0 :                            MLX5_CQE_L4_TYPE_MASK) >> MLX5_CQE_L4_TYPE_SHIFT;
    1437                 :          0 :         mlx5_lro_update_tcp_hdr(h.tcp, cqe, phcsum, l4_type);
    1438                 :          0 : }
    1439                 :            : 
    1440                 :            : void
    1441                 :          0 : mlx5_mprq_buf_free(struct mlx5_mprq_buf *buf)
    1442                 :            : {
    1443                 :          0 :         mlx5_mprq_buf_free_cb(NULL, buf);
    1444                 :          0 : }
    1445                 :            : 
    1446                 :            : /**
    1447                 :            :  * DPDK callback for RX with Multi-Packet RQ support.
    1448                 :            :  *
    1449                 :            :  * @param dpdk_rxq
    1450                 :            :  *   Generic pointer to RX queue structure.
    1451                 :            :  * @param[out] pkts
    1452                 :            :  *   Array to store received packets.
    1453                 :            :  * @param pkts_n
    1454                 :            :  *   Maximum number of packets in array.
    1455                 :            :  *
    1456                 :            :  * @return
    1457                 :            :  *   Number of packets successfully received (<= pkts_n).
    1458                 :            :  */
    1459                 :            : uint16_t
    1460                 :          0 : mlx5_rx_burst_mprq(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
    1461                 :            : {
    1462                 :            :         struct mlx5_rxq_data *rxq = dpdk_rxq;
    1463                 :          0 :         const uint32_t strd_n = RTE_BIT32(rxq->log_strd_num);
    1464                 :          0 :         const uint32_t strd_sz = RTE_BIT32(rxq->log_strd_sz);
    1465                 :          0 :         const uint32_t cqe_n = 1 << rxq->cqe_n;
    1466                 :          0 :         const uint32_t cq_mask = cqe_n - 1;
    1467                 :          0 :         const uint32_t wqe_n = 1 << rxq->elts_n;
    1468                 :          0 :         const uint32_t wq_mask = wqe_n - 1;
    1469                 :            :         volatile struct mlx5_cqe *cqe = &(*rxq->cqes)[rxq->cq_ci & cq_mask];
    1470                 :            :         unsigned int i = 0;
    1471                 :          0 :         uint32_t rq_ci = rxq->rq_ci;
    1472                 :          0 :         uint16_t consumed_strd = rxq->consumed_strd;
    1473                 :          0 :         struct mlx5_mprq_buf *buf = (*rxq->mprq_bufs)[rq_ci & wq_mask];
    1474                 :            : 
    1475         [ #  # ]:          0 :         while (i < pkts_n) {
    1476                 :            :                 struct rte_mbuf *pkt;
    1477                 :            :                 int ret;
    1478                 :            :                 uint32_t len;
    1479                 :            :                 uint16_t strd_cnt;
    1480                 :            :                 uint16_t strd_idx;
    1481                 :            :                 uint32_t byte_cnt;
    1482                 :            :                 uint16_t skip_cnt;
    1483                 :            :                 volatile struct mlx5_mini_cqe8 *mcqe = NULL;
    1484                 :            :                 enum mlx5_rqx_code rxq_code;
    1485                 :            : 
    1486         [ #  # ]:          0 :                 if (consumed_strd == strd_n) {
    1487                 :            :                         /* Replace WQE if the buffer is still in use. */
    1488         [ #  # ]:          0 :                         mprq_buf_replace(rxq, rq_ci & wq_mask);
    1489                 :            :                         /* Advance to the next WQE. */
    1490                 :            :                         consumed_strd = 0;
    1491                 :          0 :                         ++rq_ci;
    1492                 :          0 :                         buf = (*rxq->mprq_bufs)[rq_ci & wq_mask];
    1493                 :            :                 }
    1494                 :          0 :                 cqe = &(*rxq->cqes)[rxq->cq_ci & cq_mask];
    1495                 :          0 :                 ret = mlx5_rx_poll_len(rxq, cqe, cqe_n, cq_mask, &mcqe, &skip_cnt, true, NULL);
    1496         [ #  # ]:          0 :                 if (unlikely(ret & MLX5_ERROR_CQE_MASK)) {
    1497         [ #  # ]:          0 :                         if (ret == MLX5_CRITICAL_ERROR_CQE_RET) {
    1498                 :          0 :                                 rq_ci = rxq->rq_ci;
    1499                 :          0 :                                 consumed_strd = rxq->consumed_strd;
    1500                 :          0 :                                 break;
    1501                 :            :                         }
    1502                 :          0 :                         consumed_strd += skip_cnt;
    1503         [ #  # ]:          0 :                         while (consumed_strd >= strd_n) {
    1504                 :            :                                 /* Replace WQE if the buffer is still in use. */
    1505         [ #  # ]:          0 :                                 mprq_buf_replace(rxq, rq_ci & wq_mask);
    1506                 :            :                                 /* Advance to the next WQE. */
    1507                 :          0 :                                 consumed_strd -= strd_n;
    1508                 :          0 :                                 ++rq_ci;
    1509                 :          0 :                                 buf = (*rxq->mprq_bufs)[rq_ci & wq_mask];
    1510                 :            :                         }
    1511                 :          0 :                         cqe = &(*rxq->cqes)[rxq->cq_ci & cq_mask];
    1512                 :            :                 }
    1513         [ #  # ]:          0 :                 if (ret == 0)
    1514                 :            :                         break;
    1515                 :          0 :                 byte_cnt = ret;
    1516                 :          0 :                 len = (byte_cnt & MLX5_MPRQ_LEN_MASK) >> MLX5_MPRQ_LEN_SHIFT;
    1517                 :            :                 MLX5_ASSERT((int)len >= (rxq->crc_present << 2));
    1518         [ #  # ]:          0 :                 if (rxq->crc_present)
    1519                 :          0 :                         len -= RTE_ETHER_CRC_LEN;
    1520         [ #  # ]:          0 :                 if (mcqe &&
    1521         [ #  # ]:          0 :                     rxq->mcqe_format == MLX5_CQE_RESP_FORMAT_FTAG_STRIDX)
    1522                 :          0 :                         strd_cnt = (len / strd_sz) + !!(len % strd_sz);
    1523                 :            :                 else
    1524                 :          0 :                         strd_cnt = (byte_cnt & MLX5_MPRQ_STRIDE_NUM_MASK) >>
    1525                 :            :                                    MLX5_MPRQ_STRIDE_NUM_SHIFT;
    1526                 :            :                 MLX5_ASSERT(strd_cnt);
    1527                 :          0 :                 consumed_strd += strd_cnt;
    1528         [ #  # ]:          0 :                 if (byte_cnt & MLX5_MPRQ_FILLER_MASK)
    1529                 :          0 :                         continue;
    1530   [ #  #  #  # ]:          0 :                 if (rxq->cqe_comp_layout && mcqe)
    1531                 :          0 :                         cqe = &rxq->title_cqe;
    1532         [ #  # ]:          0 :                 strd_idx = rte_be_to_cpu_16(mcqe == NULL ?
    1533                 :            :                                         cqe->wqe_counter :
    1534                 :            :                                         mcqe->stride_idx);
    1535                 :            :                 MLX5_ASSERT(strd_idx < strd_n);
    1536                 :            :                 MLX5_ASSERT(!((rte_be_to_cpu_16(cqe->wqe_id) ^ rq_ci) &
    1537                 :            :                             wq_mask));
    1538                 :          0 :                 pkt = rte_pktmbuf_alloc(rxq->mp);
    1539         [ #  # ]:          0 :                 if (unlikely(pkt == NULL)) {
    1540                 :          0 :                         ++rxq->stats.rx_nombuf;
    1541                 :          0 :                         break;
    1542                 :            :                 }
    1543                 :            :                 len = (byte_cnt & MLX5_MPRQ_LEN_MASK) >> MLX5_MPRQ_LEN_SHIFT;
    1544                 :            :                 MLX5_ASSERT((int)len >= (rxq->crc_present << 2));
    1545         [ #  # ]:          0 :                 if (rxq->crc_present)
    1546                 :          0 :                         len -= RTE_ETHER_CRC_LEN;
    1547         [ #  # ]:          0 :                 rxq_code = mprq_buf_to_pkt(rxq, pkt, len, buf,
    1548                 :            :                                            strd_idx, strd_cnt);
    1549         [ #  # ]:          0 :                 if (unlikely(rxq_code != MLX5_RXQ_CODE_EXIT)) {
    1550                 :            :                         rte_pktmbuf_free_seg(pkt);
    1551         [ #  # ]:          0 :                         if (rxq_code == MLX5_RXQ_CODE_DROPPED) {
    1552                 :          0 :                                 ++rxq->stats.idropped;
    1553                 :          0 :                                 continue;
    1554                 :            :                         }
    1555         [ #  # ]:          0 :                         if (rxq_code == MLX5_RXQ_CODE_NOMBUF) {
    1556                 :          0 :                                 ++rxq->stats.rx_nombuf;
    1557                 :          0 :                                 break;
    1558                 :            :                         }
    1559                 :            :                 }
    1560                 :            :                 rxq_cq_to_mbuf(rxq, pkt, cqe, mcqe);
    1561         [ #  # ]:          0 :                 if (cqe->lro_num_seg > 1) {
    1562                 :          0 :                         mlx5_lro_update_hdr(rte_pktmbuf_mtod(pkt, uint8_t *),
    1563                 :            :                                             cqe, mcqe, rxq, len);
    1564                 :          0 :                         pkt->ol_flags |= RTE_MBUF_F_RX_LRO;
    1565                 :          0 :                         pkt->tso_segsz = len / cqe->lro_num_seg;
    1566                 :            :                 }
    1567                 :          0 :                 PKT_LEN(pkt) = len;
    1568                 :          0 :                 PORT(pkt) = rxq->port_id;
    1569                 :            : #ifdef MLX5_PMD_SOFT_COUNTERS
    1570                 :            :                 /* Increment bytes counter. */
    1571                 :          0 :                 rxq->stats.ibytes += PKT_LEN(pkt);
    1572                 :            : #endif
    1573                 :            :                 /* Return packet. */
    1574                 :          0 :                 *(pkts++) = pkt;
    1575                 :          0 :                 ++i;
    1576                 :            :         }
    1577                 :            :         /* Update the consumer indexes. */
    1578                 :          0 :         rxq->consumed_strd = consumed_strd;
    1579                 :          0 :         rte_io_wmb();
    1580         [ #  # ]:          0 :         *rxq->cq_db = rte_cpu_to_be_32(rxq->cq_ci);
    1581         [ #  # ]:          0 :         if (rq_ci != rxq->rq_ci) {
    1582                 :          0 :                 rxq->rq_ci = rq_ci;
    1583                 :          0 :                 rte_io_wmb();
    1584         [ #  # ]:          0 :                 *rxq->rq_db = rte_cpu_to_be_32(rxq->rq_ci);
    1585                 :            :         }
    1586                 :            : #ifdef MLX5_PMD_SOFT_COUNTERS
    1587                 :            :         /* Increment packets counter. */
    1588                 :          0 :         rxq->stats.ipackets += i;
    1589                 :            : #endif
    1590                 :          0 :         return i;
    1591                 :            : }
    1592                 :            : 
    1593                 :            : int
    1594                 :          0 : mlx5_rx_queue_lwm_query(struct rte_eth_dev *dev,
    1595                 :            :                         uint16_t *queue_id, uint8_t *lwm)
    1596                 :            : {
    1597                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1598                 :            :         unsigned int rxq_id, found = 0, n;
    1599                 :            :         struct mlx5_rxq_priv *rxq;
    1600                 :            : 
    1601         [ #  # ]:          0 :         if (!queue_id)
    1602                 :            :                 return -EINVAL;
    1603                 :            :         /* Query all the Rx queues of the port in a circular way. */
    1604         [ #  # ]:          0 :         for (rxq_id = *queue_id, n = 0; n < priv->rxqs_n; n++) {
    1605                 :          0 :                 rxq = mlx5_rxq_get(dev, rxq_id);
    1606   [ #  #  #  # ]:          0 :                 if (rxq && rxq->lwm_event_pending) {
    1607                 :          0 :                         pthread_mutex_lock(&priv->sh->lwm_config_lock);
    1608                 :          0 :                         rxq->lwm_event_pending = 0;
    1609                 :          0 :                         pthread_mutex_unlock(&priv->sh->lwm_config_lock);
    1610                 :          0 :                         *queue_id = rxq_id;
    1611                 :            :                         found = 1;
    1612         [ #  # ]:          0 :                         if (lwm)
    1613                 :          0 :                                 *lwm =  mlx5_rxq_lwm_to_percentage(rxq);
    1614                 :            :                         break;
    1615                 :            :                 }
    1616                 :          0 :                 rxq_id = (rxq_id + 1) % priv->rxqs_n;
    1617                 :            :         }
    1618                 :          0 :         return found;
    1619                 :            : }
    1620                 :            : 
    1621                 :            : /**
    1622                 :            :  * Rte interrupt handler for LWM event.
    1623                 :            :  * It first checks if the event arrives, if so process the callback for
    1624                 :            :  * RTE_ETH_EVENT_RX_LWM.
    1625                 :            :  *
    1626                 :            :  * @param args
    1627                 :            :  *   Generic pointer to mlx5_priv.
    1628                 :            :  */
    1629                 :            : void
    1630                 :          0 : mlx5_dev_interrupt_handler_lwm(void *args)
    1631                 :            : {
    1632                 :            :         struct mlx5_priv *priv = args;
    1633                 :            :         struct mlx5_rxq_priv *rxq;
    1634                 :            :         struct rte_eth_dev *dev;
    1635                 :          0 :         int ret, rxq_idx = 0, port_id = 0;
    1636                 :            : 
    1637                 :          0 :         ret = priv->obj_ops.rxq_event_get_lwm(priv, &rxq_idx, &port_id);
    1638         [ #  # ]:          0 :         if (unlikely(ret < 0)) {
    1639                 :          0 :                 DRV_LOG(WARNING, "Cannot get LWM event context.");
    1640                 :          0 :                 return;
    1641                 :            :         }
    1642                 :          0 :         DRV_LOG(INFO, "%s get LWM event, port_id:%d rxq_id:%d.", __func__,
    1643                 :            :                 port_id, rxq_idx);
    1644                 :          0 :         dev = &rte_eth_devices[port_id];
    1645                 :          0 :         rxq = mlx5_rxq_get(dev, rxq_idx);
    1646         [ #  # ]:          0 :         if (rxq) {
    1647                 :          0 :                 pthread_mutex_lock(&priv->sh->lwm_config_lock);
    1648                 :          0 :                 rxq->lwm_event_pending = 1;
    1649                 :          0 :                 pthread_mutex_unlock(&priv->sh->lwm_config_lock);
    1650                 :            :         }
    1651                 :          0 :         rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_RX_AVAIL_THRESH, NULL);
    1652                 :            : }
    1653                 :            : 
    1654                 :            : /**
    1655                 :            :  * DPDK callback to arm an Rx queue LWM(limit watermark) event.
    1656                 :            :  * While the Rx queue fullness reaches the LWM limit, the driver catches
    1657                 :            :  * an HW event and invokes the user event callback.
    1658                 :            :  * After the last event handling, the user needs to call this API again
    1659                 :            :  * to arm an additional event.
    1660                 :            :  *
    1661                 :            :  * @param dev
    1662                 :            :  *   Pointer to the device structure.
    1663                 :            :  * @param[in] rx_queue_id
    1664                 :            :  *   Rx queue identificator.
    1665                 :            :  * @param[in] lwm
    1666                 :            :  *   The LWM value, is defined by a percentage of the Rx queue size.
    1667                 :            :  *   [1-99] to set a new LWM (update the old value).
    1668                 :            :  *   0 to unarm the event.
    1669                 :            :  *
    1670                 :            :  * @return
    1671                 :            :  *   0 : operation success.
    1672                 :            :  *   Otherwise:
    1673                 :            :  *   - ENOMEM - not enough memory to create LWM event channel.
    1674                 :            :  *   - EINVAL - the input Rxq is not created by devx.
    1675                 :            :  *   - E2BIG  - lwm is bigger than 99.
    1676                 :            :  */
    1677                 :            : int
    1678                 :          0 : mlx5_rx_queue_lwm_set(struct rte_eth_dev *dev, uint16_t rx_queue_id,
    1679                 :            :                       uint8_t lwm)
    1680                 :            : {
    1681                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1682                 :          0 :         uint16_t port_id = PORT_ID(priv);
    1683                 :          0 :         struct mlx5_rxq_priv *rxq = mlx5_rxq_get(dev, rx_queue_id);
    1684                 :          0 :         uint16_t event_nums[1] = {MLX5_EVENT_TYPE_SRQ_LIMIT_REACHED};
    1685                 :            :         struct mlx5_rxq_data *rxq_data;
    1686                 :            :         uint32_t wqe_cnt;
    1687                 :            :         uint64_t cookie;
    1688                 :            :         int ret = 0;
    1689                 :            : 
    1690         [ #  # ]:          0 :         if (!rxq) {
    1691                 :          0 :                 rte_errno = EINVAL;
    1692                 :          0 :                 return -rte_errno;
    1693                 :            :         }
    1694                 :          0 :         rxq_data = &rxq->ctrl->rxq;
    1695                 :            :         /* Ensure the Rq is created by devx. */
    1696         [ #  # ]:          0 :         if (priv->obj_ops.rxq_obj_new != devx_obj_ops.rxq_obj_new) {
    1697                 :          0 :                 rte_errno = EINVAL;
    1698                 :          0 :                 return -rte_errno;
    1699                 :            :         }
    1700         [ #  # ]:          0 :         if (lwm > 99) {
    1701                 :          0 :                 DRV_LOG(WARNING, "Too big LWM configuration.");
    1702                 :          0 :                 rte_errno = E2BIG;
    1703                 :          0 :                 return -rte_errno;
    1704                 :            :         }
    1705                 :            :         /* Start config LWM. */
    1706                 :          0 :         pthread_mutex_lock(&priv->sh->lwm_config_lock);
    1707   [ #  #  #  # ]:          0 :         if (rxq->lwm == 0 && lwm == 0) {
    1708                 :            :                 /* Both old/new values are 0, do nothing. */
    1709                 :            :                 ret = 0;
    1710                 :          0 :                 goto end;
    1711                 :            :         }
    1712                 :          0 :         wqe_cnt = 1 << (rxq_data->elts_n - rxq_data->sges_n);
    1713         [ #  # ]:          0 :         if (lwm) {
    1714         [ #  # ]:          0 :                 if (!priv->sh->devx_channel_lwm) {
    1715                 :          0 :                         ret = mlx5_lwm_setup(priv);
    1716         [ #  # ]:          0 :                         if (ret) {
    1717                 :          0 :                                 DRV_LOG(WARNING,
    1718                 :            :                                         "Failed to create shared_lwm.");
    1719                 :          0 :                                 rte_errno = ENOMEM;
    1720                 :            :                                 ret = -rte_errno;
    1721                 :          0 :                                 goto end;
    1722                 :            :                         }
    1723                 :            :                 }
    1724         [ #  # ]:          0 :                 if (!rxq->lwm_devx_subscribed) {
    1725                 :          0 :                         cookie = ((uint32_t)
    1726                 :          0 :                                   (port_id << LWM_COOKIE_PORTID_OFFSET)) |
    1727                 :          0 :                                 (rx_queue_id << LWM_COOKIE_RXQID_OFFSET);
    1728                 :          0 :                         ret = mlx5_os_devx_subscribe_devx_event
    1729                 :          0 :                                 (priv->sh->devx_channel_lwm,
    1730                 :          0 :                                  rxq->devx_rq.rq->obj,
    1731                 :            :                                  sizeof(event_nums),
    1732                 :            :                                  event_nums,
    1733                 :            :                                  cookie);
    1734         [ #  # ]:          0 :                         if (ret) {
    1735         [ #  # ]:          0 :                                 rte_errno = rte_errno ? rte_errno : EINVAL;
    1736                 :          0 :                                 ret = -rte_errno;
    1737                 :          0 :                                 goto end;
    1738                 :            :                         }
    1739                 :          0 :                         rxq->lwm_devx_subscribed = 1;
    1740                 :            :                 }
    1741                 :            :         }
    1742                 :            :         /* Save LWM to rxq and send modify_rq devx command. */
    1743                 :          0 :         rxq->lwm = lwm * wqe_cnt / 100;
    1744                 :            :         /* Prevent integer division loss when switch lwm number to percentage. */
    1745   [ #  #  #  # ]:          0 :         if (lwm && (lwm * wqe_cnt % 100)) {
    1746         [ #  # ]:          0 :                 rxq->lwm = ((uint32_t)(rxq->lwm + 1) >= wqe_cnt) ?
    1747                 :            :                         rxq->lwm : (rxq->lwm + 1);
    1748                 :            :         }
    1749   [ #  #  #  # ]:          0 :         if (lwm && !rxq->lwm) {
    1750                 :            :                 /* With mprq, wqe_cnt may be < 100. */
    1751                 :          0 :                 DRV_LOG(WARNING, "Too small LWM configuration.");
    1752                 :          0 :                 rte_errno = EINVAL;
    1753                 :            :                 ret = -rte_errno;
    1754                 :          0 :                 goto end;
    1755                 :            :         }
    1756                 :          0 :         ret = mlx5_devx_modify_rq(rxq, MLX5_RXQ_MOD_RDY2RDY);
    1757                 :          0 : end:
    1758                 :          0 :         pthread_mutex_unlock(&priv->sh->lwm_config_lock);
    1759                 :          0 :         return ret;
    1760                 :            : }
    1761                 :            : 
    1762                 :            : /**
    1763                 :            :  * Mlx5 access register function to configure host shaper.
    1764                 :            :  * It calls API in libmtcr_ul to access QSHR(Qos Shaper Host Register)
    1765                 :            :  * in firmware.
    1766                 :            :  *
    1767                 :            :  * @param dev
    1768                 :            :  *   Pointer to rte_eth_dev.
    1769                 :            :  * @param lwm_triggered
    1770                 :            :  *   Flag to enable/disable lwm_triggered bit in QSHR.
    1771                 :            :  * @param rate
    1772                 :            :  *   Host shaper rate, unit is 100Mbps, set to 0 means disable the shaper.
    1773                 :            :  * @return
    1774                 :            :  *   0 : operation success.
    1775                 :            :  *   Otherwise:
    1776                 :            :  *   - ENOENT - no ibdev interface.
    1777                 :            :  *   - EBUSY  - the register access unit is busy.
    1778                 :            :  *   - EIO    - the register access command meets IO error.
    1779                 :            :  */
    1780                 :            : static int
    1781                 :            : mlxreg_host_shaper_config(struct rte_eth_dev *dev,
    1782                 :            :                           bool lwm_triggered, uint8_t rate)
    1783                 :            : {
    1784                 :            : #ifdef HAVE_MLX5_MSTFLINT
    1785                 :            :         struct mlx5_priv *priv = dev->data->dev_private;
    1786                 :            :         uint32_t data[MLX5_ST_SZ_DW(register_qshr)] = {0};
    1787                 :            :         int rc, retry_count = 3;
    1788                 :            :         mfile *mf = NULL;
    1789                 :            :         int status;
    1790                 :            :         void *ptr;
    1791                 :            : 
    1792                 :            :         mf = mopen(priv->sh->ibdev_name);
    1793                 :            :         if (!mf) {
    1794                 :            :                 DRV_LOG(WARNING, "mopen failed\n");
    1795                 :            :                 rte_errno = ENOENT;
    1796                 :            :                 return -rte_errno;
    1797                 :            :         }
    1798                 :            :         MLX5_SET(register_qshr, data, connected_host, 1);
    1799                 :            :         MLX5_SET(register_qshr, data, fast_response, lwm_triggered ? 1 : 0);
    1800                 :            :         MLX5_SET(register_qshr, data, local_port, 1);
    1801                 :            :         ptr = MLX5_ADDR_OF(register_qshr, data, global_config);
    1802                 :            :         MLX5_SET(ets_global_config_register, ptr, rate_limit_update, 1);
    1803                 :            :         MLX5_SET(ets_global_config_register, ptr, max_bw_units,
    1804                 :            :                  rate ? ETS_GLOBAL_CONFIG_BW_UNIT_HUNDREDS_MBPS :
    1805                 :            :                  ETS_GLOBAL_CONFIG_BW_UNIT_DISABLED);
    1806                 :            :         MLX5_SET(ets_global_config_register, ptr, max_bw_value, rate);
    1807                 :            :         do {
    1808                 :            :                 rc = maccess_reg(mf,
    1809                 :            :                                  MLX5_QSHR_REGISTER_ID,
    1810                 :            :                                  MACCESS_REG_METHOD_SET,
    1811                 :            :                                  (u_int32_t *)&data[0],
    1812                 :            :                                  sizeof(data),
    1813                 :            :                                  sizeof(data),
    1814                 :            :                                  sizeof(data),
    1815                 :            :                                  &status);
    1816                 :            :                 if ((rc != ME_ICMD_STATUS_IFC_BUSY &&
    1817                 :            :                      status != ME_REG_ACCESS_BAD_PARAM) ||
    1818                 :            :                     !(mf->flags & MDEVS_REM)) {
    1819                 :            :                         break;
    1820                 :            :                 }
    1821                 :            :                 DRV_LOG(WARNING, "%s retry.", __func__);
    1822                 :            :                 usleep(10000);
    1823                 :            :         } while (retry_count-- > 0);
    1824                 :            :         mclose(mf);
    1825                 :            :         rte_errno = (rc == ME_REG_ACCESS_DEV_BUSY) ? EBUSY : EIO;
    1826                 :            :         return rc ? -rte_errno : 0;
    1827                 :            : #else
    1828                 :            :         (void)dev;
    1829                 :            :         (void)lwm_triggered;
    1830                 :            :         (void)rate;
    1831                 :            :         return -1;
    1832                 :            : #endif
    1833                 :            : }
    1834                 :            : 
    1835                 :            : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_mlx5_host_shaper_config, 22.07)
    1836                 :          0 : int rte_pmd_mlx5_host_shaper_config(int port_id, uint8_t rate,
    1837                 :            :                                     uint32_t flags)
    1838                 :            : {
    1839                 :            :         struct rte_eth_dev *dev = &rte_eth_devices[port_id];
    1840                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1841                 :            :         bool lwm_triggered =
    1842                 :          0 :              !!(flags & RTE_BIT32(RTE_PMD_MLX5_HOST_SHAPER_FLAG_AVAIL_THRESH_TRIGGERED));
    1843                 :            : 
    1844         [ #  # ]:          0 :         if (!lwm_triggered) {
    1845                 :          0 :                 priv->sh->host_shaper_rate = rate;
    1846                 :            :         } else {
    1847      [ #  #  # ]:          0 :                 switch (rate) {
    1848                 :          0 :                 case 0:
    1849                 :            :                 /* Rate 0 means disable lwm_triggered. */
    1850                 :          0 :                         priv->sh->lwm_triggered = 0;
    1851                 :          0 :                         break;
    1852                 :          0 :                 case 1:
    1853                 :            :                 /* Rate 1 means enable lwm_triggered. */
    1854                 :          0 :                         priv->sh->lwm_triggered = 1;
    1855                 :          0 :                         break;
    1856                 :            :                 default:
    1857                 :            :                         return -ENOTSUP;
    1858                 :            :                 }
    1859                 :            :         }
    1860                 :          0 :         return mlxreg_host_shaper_config(dev, priv->sh->lwm_triggered,
    1861                 :            :                                          priv->sh->host_shaper_rate);
    1862                 :            : }
    1863                 :            : 
    1864                 :            : /**
    1865                 :            :  * Dump RQ/CQ Context to a file.
    1866                 :            :  *
    1867                 :            :  * @param[in] port_id
    1868                 :            :  *   Port ID
    1869                 :            :  * @param[in] queue_id
    1870                 :            :  *   Queue ID
    1871                 :            :  * @param[in] filename
    1872                 :            :  *   Name of file to dump the Rx Queue Context
    1873                 :            :  *
    1874                 :            :  * @return
    1875                 :            :  *   0 for Success, non-zero value depending on failure type
    1876                 :            :  */
    1877                 :            : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_mlx5_rxq_dump_contexts, 24.07)
    1878                 :          0 : int rte_pmd_mlx5_rxq_dump_contexts(uint16_t port_id, uint16_t queue_id, const char *filename)
    1879                 :            : {
    1880                 :            :         struct rte_eth_dev *dev;
    1881                 :            :         struct mlx5_rxq_priv *rxq;
    1882                 :            :         struct mlx5_rxq_ctrl *rxq_ctrl;
    1883                 :            :         struct mlx5_rxq_obj *rxq_obj;
    1884                 :            :         struct mlx5_devx_rq *rq;
    1885                 :            :         struct mlx5_devx_cq *cq;
    1886                 :            :         struct mlx5_devx_obj *rq_devx_obj;
    1887                 :            :         struct mlx5_devx_obj *cq_devx_obj;
    1888                 :            : 
    1889                 :          0 :         uint32_t rq_out[MLX5_ST_SZ_DW(query_rq_out)] = {0};
    1890                 :          0 :         uint32_t cq_out[MLX5_ST_SZ_DW(query_cq_out)] = {0};
    1891                 :            : 
    1892                 :            :         int ret;
    1893                 :            :         FILE *fd;
    1894                 :          0 :         MKSTR(path, "./%s", filename);
    1895                 :            : 
    1896         [ #  # ]:          0 :         if (!rte_eth_dev_is_valid_port(port_id))
    1897                 :            :                 return -ENODEV;
    1898                 :            : 
    1899         [ #  # ]:          0 :         if (rte_eth_rx_queue_is_valid(port_id, queue_id))
    1900                 :            :                 return -EINVAL;
    1901                 :            : 
    1902                 :          0 :         fd = fopen(path, "w");
    1903         [ #  # ]:          0 :         if (!fd) {
    1904                 :          0 :                 rte_errno = errno;
    1905                 :          0 :                 return -EIO;
    1906                 :            :         }
    1907                 :            : 
    1908                 :          0 :         dev = &rte_eth_devices[port_id];
    1909                 :          0 :         rxq = mlx5_rxq_ref(dev, queue_id);
    1910                 :          0 :         rxq_ctrl = rxq->ctrl;
    1911                 :          0 :         rxq_obj = rxq_ctrl->obj;
    1912                 :            :         rq = &rxq->devx_rq;
    1913                 :            :         cq = &rxq_obj->cq_obj;
    1914                 :          0 :         rq_devx_obj = rq->rq;
    1915                 :          0 :         cq_devx_obj = cq->cq;
    1916                 :            : 
    1917                 :            :         do {
    1918                 :          0 :                 ret = mlx5_devx_cmd_query_rq(rq_devx_obj, rq_out, sizeof(rq_out));
    1919         [ #  # ]:          0 :                 if (ret)
    1920                 :            :                         break;
    1921                 :            : 
    1922                 :            :                 /* Dump rq query output to file */
    1923                 :          0 :                 MKSTR(rq_headline, "RQ DevX ID = %u Port = %u Queue index = %u ",
    1924                 :            :                                         rq_devx_obj->id, port_id, queue_id);
    1925                 :          0 :                 mlx5_dump_to_file(fd, NULL, rq_headline, 0);
    1926                 :          0 :                 mlx5_dump_to_file(fd, "Query RQ Dump:",
    1927                 :            :                                         (const void *)((uintptr_t)rq_out),
    1928                 :            :                                         sizeof(rq_out));
    1929                 :            : 
    1930                 :          0 :                 ret = mlx5_devx_cmd_query_cq(cq_devx_obj, cq_out, sizeof(cq_out));
    1931         [ #  # ]:          0 :                 if (ret)
    1932                 :            :                         break;
    1933                 :            : 
    1934                 :            :                 /* Dump cq query output to file */
    1935                 :          0 :                 MKSTR(cq_headline, "CQ DevX ID = %u Port = %u Queue index = %u ",
    1936                 :            :                                         cq_devx_obj->id, port_id, queue_id);
    1937                 :          0 :                 mlx5_dump_to_file(fd, NULL, cq_headline, 0);
    1938                 :          0 :                 mlx5_dump_to_file(fd, "Query CQ Dump:",
    1939                 :            :                                         (const void *)((uintptr_t)cq_out),
    1940                 :            :                                         sizeof(cq_out));
    1941                 :            :         } while (false);
    1942                 :            : 
    1943                 :          0 :         fclose(fd);
    1944                 :          0 :         return ret;
    1945                 :            : }

Generated by: LCOV version 1.14