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

Generated by: LCOV version 1.14