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

Generated by: LCOV version 1.14