LCOV - code coverage report
Current view: top level - drivers/net/mlx5 - mlx5_tx.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 237 0.0 %
Date: 2026-06-01 18:36:17 Functions: 0 10 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 194 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_malloc.h>
      23                 :            : 
      24                 :            : #include "mlx5_autoconf.h"
      25                 :            : #include "mlx5_defs.h"
      26                 :            : #include "mlx5.h"
      27                 :            : #include "mlx5_utils.h"
      28                 :            : #include "mlx5_rxtx.h"
      29                 :            : #include "mlx5_tx.h"
      30                 :            : 
      31                 :            : #define MLX5_TXOFF_INFO(func, olx) {mlx5_tx_burst_##func, olx},
      32                 :            : 
      33                 :            : /**
      34                 :            :  * Move QP from error state to running state and initialize indexes.
      35                 :            :  *
      36                 :            :  * @param txq_ctrl
      37                 :            :  *   Pointer to TX queue control structure.
      38                 :            :  *
      39                 :            :  * @return
      40                 :            :  *   0 on success, else -1.
      41                 :            :  */
      42                 :            : static int
      43                 :          0 : tx_recover_qp(struct mlx5_txq_ctrl *txq_ctrl)
      44                 :            : {
      45                 :          0 :         struct mlx5_mp_arg_queue_state_modify sm = {
      46                 :            :                         .is_wq = 0,
      47                 :          0 :                         .queue_id = txq_ctrl->txq.idx,
      48                 :            :         };
      49                 :            : 
      50         [ #  # ]:          0 :         if (mlx5_queue_state_modify(ETH_DEV(txq_ctrl->priv), &sm))
      51                 :            :                 return -1;
      52                 :          0 :         txq_ctrl->txq.wqe_ci = 0;
      53                 :          0 :         txq_ctrl->txq.wqe_pi = 0;
      54                 :          0 :         txq_ctrl->txq.elts_comp = 0;
      55                 :          0 :         return 0;
      56                 :            : }
      57                 :            : 
      58                 :            : /* Return 1 if the error CQE is signed otherwise, sign it and return 0. */
      59                 :            : static int
      60                 :            : check_err_cqe_seen(volatile struct mlx5_error_cqe *err_cqe)
      61                 :            : {
      62                 :            :         static const uint8_t magic[] = "seen";
      63                 :            :         int ret = 1;
      64                 :            :         unsigned int i;
      65                 :            : 
      66         [ #  # ]:          0 :         for (i = 0; i < sizeof(magic); ++i)
      67   [ #  #  #  # ]:          0 :                 if (!ret || err_cqe->rsvd1[i] != magic[i]) {
      68                 :            :                         ret = 0;
      69                 :          0 :                         err_cqe->rsvd1[i] = magic[i];
      70                 :            :                 }
      71                 :            :         return ret;
      72                 :            : }
      73                 :            : 
      74                 :            : /**
      75                 :            :  * Handle error CQE.
      76                 :            :  *
      77                 :            :  * @param txq
      78                 :            :  *   Pointer to TX queue structure.
      79                 :            :  * @param error_cqe
      80                 :            :  *   Pointer to the error CQE.
      81                 :            :  *
      82                 :            :  * @return
      83                 :            :  *   Negative value if queue recovery failed, otherwise
      84                 :            :  *   the error completion entry is handled successfully.
      85                 :            :  */
      86                 :            : static int
      87                 :          0 : mlx5_tx_error_cqe_handle(struct mlx5_txq_data *__rte_restrict txq,
      88                 :            :                          volatile struct mlx5_error_cqe *err_cqe)
      89                 :            : {
      90         [ #  # ]:          0 :         if (err_cqe->syndrome != MLX5_CQE_SYNDROME_WR_FLUSH_ERR) {
      91                 :          0 :                 const uint16_t wqe_m = ((1 << txq->wqe_n) - 1);
      92                 :            :                 struct mlx5_txq_ctrl *txq_ctrl =
      93                 :          0 :                                 container_of(txq, struct mlx5_txq_ctrl, txq);
      94                 :          0 :                 uint16_t new_wqe_pi = rte_be_to_cpu_16(err_cqe->wqe_counter);
      95                 :            :                 int seen = check_err_cqe_seen(err_cqe);
      96                 :            : 
      97         [ #  # ]:          0 :                 if (!seen && txq_ctrl->dump_file_n <
      98         [ #  # ]:          0 :                     txq_ctrl->priv->config.max_dump_files_num) {
      99                 :          0 :                         MKSTR(err_str, "Unexpected CQE error syndrome "
     100                 :            :                               "0x%02x CQN = %u SQN = %u wqe_counter = %u "
     101                 :            :                               "wq_ci = %u cq_ci = %u", err_cqe->syndrome,
     102                 :            :                               txq->cqe_s, txq->qp_num_8s >> 8,
     103                 :            :                               rte_be_to_cpu_16(err_cqe->wqe_counter),
     104                 :            :                               txq->wqe_ci, txq->cq_ci);
     105                 :          0 :                         MKSTR(name, "dpdk_mlx5_port_%u_txq_%u_index_%u_%u",
     106                 :            :                               PORT_ID(txq_ctrl->priv), txq->idx,
     107                 :            :                               txq_ctrl->dump_file_n, (uint32_t)rte_rdtsc());
     108                 :          0 :                         mlx5_dump_debug_information(name, NULL, err_str, 0);
     109                 :          0 :                         mlx5_dump_debug_information(name, "MLX5 Error CQ:",
     110                 :            :                                                     (const void *)((uintptr_t)
     111                 :          0 :                                                     txq->cqes),
     112                 :            :                                                     sizeof(struct mlx5_error_cqe) *
     113                 :          0 :                                                     (size_t)RTE_BIT32(txq->cqe_n));
     114                 :          0 :                         mlx5_dump_debug_information(name, "MLX5 Error SQ:",
     115                 :            :                                                     (const void *)((uintptr_t)
     116                 :          0 :                                                     txq->wqes),
     117                 :            :                                                     MLX5_WQE_SIZE *
     118                 :          0 :                                                     (size_t)RTE_BIT32(txq->wqe_n));
     119                 :          0 :                         txq_ctrl->dump_file_n++;
     120                 :            :                 }
     121         [ #  # ]:          0 :                 if (!seen)
     122                 :            :                         /*
     123                 :            :                          * Count errors in WQEs units.
     124                 :            :                          * Later it can be improved to count error packets,
     125                 :            :                          * for example, by SQ parsing to find how much packets
     126                 :            :                          * should be counted for each WQE.
     127                 :            :                          */
     128                 :          0 :                         txq->stats.oerrors += ((txq->wqe_ci & wqe_m) -
     129                 :          0 :                                                 new_wqe_pi) & wqe_m;
     130         [ #  # ]:          0 :                 if (tx_recover_qp(txq_ctrl)) {
     131                 :            :                         /* Recovering failed - retry later on the same WQE. */
     132                 :            :                         return -1;
     133                 :            :                 }
     134                 :            :                 /* Release all the remaining buffers. */
     135                 :          0 :                 mlx5_txq_free_elts(txq_ctrl);
     136                 :            :         }
     137                 :            :         return 0;
     138                 :            : }
     139                 :            : 
     140                 :            : /**
     141                 :            :  * Update completion queue consuming index via doorbell
     142                 :            :  * and flush the completed data buffers.
     143                 :            :  *
     144                 :            :  * @param txq
     145                 :            :  *   Pointer to TX queue structure.
     146                 :            :  * @param last_cqe
     147                 :            :  *   valid CQE pointer, if not NULL update txq->wqe_pi and flush the buffers.
     148                 :            :  */
     149                 :            : static __rte_always_inline void
     150                 :            : mlx5_tx_comp_flush(struct mlx5_txq_data *__rte_restrict txq,
     151                 :            :                    volatile struct mlx5_cqe *last_cqe)
     152                 :            : {
     153                 :          0 :         if (likely(last_cqe != NULL)) {
     154                 :            :                 uint16_t tail;
     155                 :            : 
     156                 :          0 :                 txq->wqe_pi = rte_be_to_cpu_16(last_cqe->wqe_counter);
     157                 :          0 :                 tail = txq->fcqs[(txq->cq_ci - 1) & txq->cqe_m];
     158         [ #  # ]:          0 :                 if (likely(tail != txq->elts_tail)) {
     159                 :            :                         mlx5_tx_free_elts(txq, tail);
     160                 :            :                         MLX5_ASSERT(tail == txq->elts_tail);
     161                 :            :                 }
     162                 :            :         }
     163                 :            : }
     164                 :            : 
     165                 :            : /**
     166                 :            :  * Manage TX completions. This routine checks the CQ for
     167                 :            :  * arrived CQEs, deduces the last accomplished WQE in SQ,
     168                 :            :  * updates SQ producing index and frees all completed mbufs.
     169                 :            :  *
     170                 :            :  * @param txq
     171                 :            :  *   Pointer to TX queue structure.
     172                 :            :  *
     173                 :            :  * NOTE: not inlined intentionally, it makes tx_burst
     174                 :            :  * routine smaller, simple and faster - from experiments.
     175                 :            :  */
     176                 :            : void
     177                 :          0 : mlx5_tx_handle_completion(struct mlx5_txq_data *__rte_restrict txq)
     178                 :            : {
     179                 :            :         unsigned int count = MLX5_TX_COMP_MAX_CQE;
     180                 :            :         volatile struct mlx5_cqe *last_cqe = NULL;
     181                 :            :         bool ring_doorbell = false;
     182                 :            :         int ret;
     183                 :            : 
     184                 :            :         do {
     185                 :            :                 volatile struct mlx5_cqe *cqe;
     186                 :            : 
     187                 :          0 :                 cqe = &txq->cqes[txq->cq_ci & txq->cqe_m];
     188         [ #  # ]:          0 :                 ret = check_cqe(cqe, txq->cqe_s, txq->cq_ci);
     189         [ #  # ]:          0 :                 if (unlikely(ret != MLX5_CQE_STATUS_SW_OWN)) {
     190         [ #  # ]:          0 :                         if (likely(ret != MLX5_CQE_STATUS_ERR)) {
     191                 :            :                                 /* No new CQEs in completion queue. */
     192                 :            :                                 MLX5_ASSERT(ret == MLX5_CQE_STATUS_HW_OWN);
     193                 :            :                                 break;
     194                 :            :                         }
     195                 :            :                         /*
     196                 :            :                          * Some error occurred, try to restart.
     197                 :            :                          * We have no barrier after WQE related Doorbell
     198                 :            :                          * written, make sure all writes are completed
     199                 :            :                          * here, before we might perform SQ reset.
     200                 :            :                          */
     201                 :            :                         rte_wmb();
     202                 :          0 :                         ret = mlx5_tx_error_cqe_handle
     203                 :            :                                 (txq, (volatile struct mlx5_error_cqe *)cqe);
     204         [ #  # ]:          0 :                         if (unlikely(ret < 0)) {
     205                 :            :                                 /*
     206                 :            :                                  * Some error occurred on queue error
     207                 :            :                                  * handling, we do not advance the index
     208                 :            :                                  * here, allowing to retry on next call.
     209                 :            :                                  */
     210                 :            :                                 return;
     211                 :            :                         }
     212                 :            :                         /*
     213                 :            :                          * We are going to fetch all entries with
     214                 :            :                          * MLX5_CQE_SYNDROME_WR_FLUSH_ERR status.
     215                 :            :                          * The send queue is supposed to be empty.
     216                 :            :                          */
     217                 :            :                         ring_doorbell = true;
     218                 :          0 :                         ++txq->cq_ci;
     219                 :          0 :                         txq->cq_pi = txq->cq_ci;
     220                 :            :                         last_cqe = NULL;
     221                 :          0 :                         continue;
     222                 :            :                 }
     223                 :            :                 /* Normal transmit completion. */
     224                 :            :                 MLX5_ASSERT(txq->cq_ci != txq->cq_pi);
     225                 :            : #ifdef RTE_PMD_MLX5_DEBUG
     226                 :            :                 MLX5_ASSERT((txq->fcqs[txq->cq_ci & txq->cqe_m] >> 16) ==
     227                 :            :                             cqe->wqe_counter);
     228                 :            : #endif
     229                 :            :                 if (__rte_trace_point_fp_is_enabled()) {
     230                 :            :                         uint64_t ts = rte_be_to_cpu_64(cqe->timestamp);
     231                 :            :                         uint16_t wqe_id = rte_be_to_cpu_16(cqe->wqe_counter);
     232                 :            : 
     233                 :            :                         if (txq->rt_timestamp)
     234                 :            :                                 ts = mlx5_txpp_convert_rx_ts(NULL, ts);
     235                 :            :                         rte_pmd_mlx5_trace_tx_complete(txq->port_id, txq->idx,
     236                 :            :                                                        wqe_id, ts);
     237                 :            :                 }
     238                 :            :                 ring_doorbell = true;
     239                 :          0 :                 ++txq->cq_ci;
     240                 :            :                 last_cqe = cqe;
     241                 :            :                 /*
     242                 :            :                  * We have to restrict the amount of processed CQEs
     243                 :            :                  * in one tx_burst routine call. The CQ may be large
     244                 :            :                  * and many CQEs may be updated by the NIC in one
     245                 :            :                  * transaction. Buffers freeing is time consuming,
     246                 :            :                  * multiple iterations may introduce significant latency.
     247                 :            :                  */
     248         [ #  # ]:          0 :                 if (likely(--count == 0))
     249                 :            :                         break;
     250                 :            :         } while (true);
     251         [ #  # ]:          0 :         if (likely(ring_doorbell)) {
     252                 :            :                 /* Ring doorbell to notify hardware. */
     253                 :          0 :                 rte_compiler_barrier();
     254   [ #  #  #  # ]:          0 :                 *txq->cq_db = rte_cpu_to_be_32(txq->cq_ci);
     255                 :            :                 mlx5_tx_comp_flush(txq, last_cqe);
     256                 :            :         }
     257                 :            : }
     258                 :            : 
     259                 :            : /**
     260                 :            :  * DPDK callback to check the status of a Tx descriptor.
     261                 :            :  *
     262                 :            :  * @param tx_queue
     263                 :            :  *   The Tx queue.
     264                 :            :  * @param[in] offset
     265                 :            :  *   The index of the descriptor in the ring.
     266                 :            :  *
     267                 :            :  * @return
     268                 :            :  *   The status of the Tx descriptor.
     269                 :            :  */
     270                 :            : int
     271                 :          0 : mlx5_tx_descriptor_status(void *tx_queue, uint16_t offset)
     272                 :            : {
     273                 :            :         struct mlx5_txq_data *__rte_restrict txq = tx_queue;
     274                 :            :         uint16_t used;
     275                 :            : 
     276                 :          0 :         mlx5_tx_handle_completion(txq);
     277                 :          0 :         used = txq->elts_head - txq->elts_tail;
     278         [ #  # ]:          0 :         if (offset < used)
     279                 :          0 :                 return RTE_ETH_TX_DESC_FULL;
     280                 :            :         return RTE_ETH_TX_DESC_DONE;
     281                 :            : }
     282                 :            : 
     283                 :            : /*
     284                 :            :  * Array of declared and compiled Tx burst function and corresponding
     285                 :            :  * supported offloads set. The array is used to select the Tx burst
     286                 :            :  * function for specified offloads set at Tx queue configuration time.
     287                 :            :  */
     288                 :            : static const struct {
     289                 :            :         eth_tx_burst_t func;
     290                 :            :         unsigned int olx;
     291                 :            : } txoff_func[] = {
     292                 :            : MLX5_TXOFF_INFO(full_empw,
     293                 :            :                 MLX5_TXOFF_CONFIG_MULTI | MLX5_TXOFF_CONFIG_TSO |
     294                 :            :                 MLX5_TXOFF_CONFIG_SWP | MLX5_TXOFF_CONFIG_CSUM |
     295                 :            :                 MLX5_TXOFF_CONFIG_INLINE | MLX5_TXOFF_CONFIG_VLAN |
     296                 :            :                 MLX5_TXOFF_CONFIG_METADATA | MLX5_TXOFF_CONFIG_EMPW)
     297                 :            : 
     298                 :            : MLX5_TXOFF_INFO(none_empw,
     299                 :            :                 MLX5_TXOFF_CONFIG_NONE | MLX5_TXOFF_CONFIG_EMPW)
     300                 :            : 
     301                 :            : MLX5_TXOFF_INFO(md_empw,
     302                 :            :                 MLX5_TXOFF_CONFIG_METADATA | MLX5_TXOFF_CONFIG_EMPW)
     303                 :            : 
     304                 :            : MLX5_TXOFF_INFO(mt_empw,
     305                 :            :                 MLX5_TXOFF_CONFIG_MULTI | MLX5_TXOFF_CONFIG_TSO |
     306                 :            :                 MLX5_TXOFF_CONFIG_METADATA | MLX5_TXOFF_CONFIG_EMPW)
     307                 :            : 
     308                 :            : MLX5_TXOFF_INFO(mtsc_empw,
     309                 :            :                 MLX5_TXOFF_CONFIG_MULTI | MLX5_TXOFF_CONFIG_TSO |
     310                 :            :                 MLX5_TXOFF_CONFIG_SWP | MLX5_TXOFF_CONFIG_CSUM |
     311                 :            :                 MLX5_TXOFF_CONFIG_METADATA | MLX5_TXOFF_CONFIG_EMPW)
     312                 :            : 
     313                 :            : MLX5_TXOFF_INFO(mti_empw,
     314                 :            :                 MLX5_TXOFF_CONFIG_MULTI | MLX5_TXOFF_CONFIG_TSO |
     315                 :            :                 MLX5_TXOFF_CONFIG_INLINE |
     316                 :            :                 MLX5_TXOFF_CONFIG_METADATA | MLX5_TXOFF_CONFIG_EMPW)
     317                 :            : 
     318                 :            : MLX5_TXOFF_INFO(mtv_empw,
     319                 :            :                 MLX5_TXOFF_CONFIG_MULTI | MLX5_TXOFF_CONFIG_TSO |
     320                 :            :                 MLX5_TXOFF_CONFIG_VLAN |
     321                 :            :                 MLX5_TXOFF_CONFIG_METADATA | MLX5_TXOFF_CONFIG_EMPW)
     322                 :            : 
     323                 :            : MLX5_TXOFF_INFO(mtiv_empw,
     324                 :            :                 MLX5_TXOFF_CONFIG_MULTI | MLX5_TXOFF_CONFIG_TSO |
     325                 :            :                 MLX5_TXOFF_CONFIG_INLINE | MLX5_TXOFF_CONFIG_VLAN |
     326                 :            :                 MLX5_TXOFF_CONFIG_METADATA | MLX5_TXOFF_CONFIG_EMPW)
     327                 :            : 
     328                 :            : MLX5_TXOFF_INFO(sc_empw,
     329                 :            :                 MLX5_TXOFF_CONFIG_SWP | MLX5_TXOFF_CONFIG_CSUM |
     330                 :            :                 MLX5_TXOFF_CONFIG_METADATA | MLX5_TXOFF_CONFIG_EMPW)
     331                 :            : 
     332                 :            : MLX5_TXOFF_INFO(sci_empw,
     333                 :            :                 MLX5_TXOFF_CONFIG_SWP | MLX5_TXOFF_CONFIG_CSUM |
     334                 :            :                 MLX5_TXOFF_CONFIG_INLINE |
     335                 :            :                 MLX5_TXOFF_CONFIG_METADATA | MLX5_TXOFF_CONFIG_EMPW)
     336                 :            : 
     337                 :            : MLX5_TXOFF_INFO(scv_empw,
     338                 :            :                 MLX5_TXOFF_CONFIG_SWP | MLX5_TXOFF_CONFIG_CSUM |
     339                 :            :                 MLX5_TXOFF_CONFIG_VLAN |
     340                 :            :                 MLX5_TXOFF_CONFIG_METADATA | MLX5_TXOFF_CONFIG_EMPW)
     341                 :            : 
     342                 :            : MLX5_TXOFF_INFO(sciv_empw,
     343                 :            :                 MLX5_TXOFF_CONFIG_SWP | MLX5_TXOFF_CONFIG_CSUM |
     344                 :            :                 MLX5_TXOFF_CONFIG_INLINE | MLX5_TXOFF_CONFIG_VLAN |
     345                 :            :                 MLX5_TXOFF_CONFIG_METADATA | MLX5_TXOFF_CONFIG_EMPW)
     346                 :            : 
     347                 :            : MLX5_TXOFF_INFO(i_empw,
     348                 :            :                 MLX5_TXOFF_CONFIG_INLINE |
     349                 :            :                 MLX5_TXOFF_CONFIG_METADATA | MLX5_TXOFF_CONFIG_EMPW)
     350                 :            : 
     351                 :            : MLX5_TXOFF_INFO(v_empw,
     352                 :            :                 MLX5_TXOFF_CONFIG_VLAN |
     353                 :            :                 MLX5_TXOFF_CONFIG_METADATA | MLX5_TXOFF_CONFIG_EMPW)
     354                 :            : 
     355                 :            : MLX5_TXOFF_INFO(iv_empw,
     356                 :            :                 MLX5_TXOFF_CONFIG_INLINE | MLX5_TXOFF_CONFIG_VLAN |
     357                 :            :                 MLX5_TXOFF_CONFIG_METADATA | MLX5_TXOFF_CONFIG_EMPW)
     358                 :            : 
     359                 :            : MLX5_TXOFF_INFO(full_ts_nompw,
     360                 :            :                 MLX5_TXOFF_CONFIG_FULL | MLX5_TXOFF_CONFIG_TXPP)
     361                 :            : 
     362                 :            : MLX5_TXOFF_INFO(full_ts_nompwi,
     363                 :            :                 MLX5_TXOFF_CONFIG_MULTI | MLX5_TXOFF_CONFIG_TSO |
     364                 :            :                 MLX5_TXOFF_CONFIG_SWP | MLX5_TXOFF_CONFIG_CSUM |
     365                 :            :                 MLX5_TXOFF_CONFIG_VLAN | MLX5_TXOFF_CONFIG_METADATA |
     366                 :            :                 MLX5_TXOFF_CONFIG_TXPP)
     367                 :            : 
     368                 :            : MLX5_TXOFF_INFO(full_ts,
     369                 :            :                 MLX5_TXOFF_CONFIG_FULL | MLX5_TXOFF_CONFIG_TXPP |
     370                 :            :                 MLX5_TXOFF_CONFIG_EMPW)
     371                 :            : 
     372                 :            : MLX5_TXOFF_INFO(full_ts_noi,
     373                 :            :                 MLX5_TXOFF_CONFIG_MULTI | MLX5_TXOFF_CONFIG_TSO |
     374                 :            :                 MLX5_TXOFF_CONFIG_SWP | MLX5_TXOFF_CONFIG_CSUM |
     375                 :            :                 MLX5_TXOFF_CONFIG_VLAN | MLX5_TXOFF_CONFIG_METADATA |
     376                 :            :                 MLX5_TXOFF_CONFIG_TXPP | MLX5_TXOFF_CONFIG_EMPW)
     377                 :            : 
     378                 :            : MLX5_TXOFF_INFO(none_ts,
     379                 :            :                 MLX5_TXOFF_CONFIG_NONE | MLX5_TXOFF_CONFIG_TXPP |
     380                 :            :                 MLX5_TXOFF_CONFIG_EMPW)
     381                 :            : 
     382                 :            : MLX5_TXOFF_INFO(mdi_ts,
     383                 :            :                 MLX5_TXOFF_CONFIG_INLINE | MLX5_TXOFF_CONFIG_METADATA |
     384                 :            :                 MLX5_TXOFF_CONFIG_TXPP | MLX5_TXOFF_CONFIG_EMPW)
     385                 :            : 
     386                 :            : MLX5_TXOFF_INFO(mti_ts,
     387                 :            :                 MLX5_TXOFF_CONFIG_MULTI | MLX5_TXOFF_CONFIG_TSO |
     388                 :            :                 MLX5_TXOFF_CONFIG_INLINE | MLX5_TXOFF_CONFIG_METADATA |
     389                 :            :                 MLX5_TXOFF_CONFIG_TXPP | MLX5_TXOFF_CONFIG_EMPW)
     390                 :            : 
     391                 :            : MLX5_TXOFF_INFO(mtiv_ts,
     392                 :            :                 MLX5_TXOFF_CONFIG_MULTI | MLX5_TXOFF_CONFIG_TSO |
     393                 :            :                 MLX5_TXOFF_CONFIG_INLINE | MLX5_TXOFF_CONFIG_VLAN |
     394                 :            :                 MLX5_TXOFF_CONFIG_METADATA | MLX5_TXOFF_CONFIG_TXPP |
     395                 :            :                 MLX5_TXOFF_CONFIG_EMPW)
     396                 :            : 
     397                 :            : MLX5_TXOFF_INFO(full,
     398                 :            :                 MLX5_TXOFF_CONFIG_MULTI | MLX5_TXOFF_CONFIG_TSO |
     399                 :            :                 MLX5_TXOFF_CONFIG_SWP | MLX5_TXOFF_CONFIG_CSUM |
     400                 :            :                 MLX5_TXOFF_CONFIG_INLINE | MLX5_TXOFF_CONFIG_VLAN |
     401                 :            :                 MLX5_TXOFF_CONFIG_METADATA)
     402                 :            : 
     403                 :            : MLX5_TXOFF_INFO(none,
     404                 :            :                 MLX5_TXOFF_CONFIG_NONE)
     405                 :            : 
     406                 :            : MLX5_TXOFF_INFO(md,
     407                 :            :                 MLX5_TXOFF_CONFIG_METADATA)
     408                 :            : 
     409                 :            : MLX5_TXOFF_INFO(mt,
     410                 :            :                 MLX5_TXOFF_CONFIG_MULTI | MLX5_TXOFF_CONFIG_TSO |
     411                 :            :                 MLX5_TXOFF_CONFIG_METADATA)
     412                 :            : 
     413                 :            : MLX5_TXOFF_INFO(mtsc,
     414                 :            :                 MLX5_TXOFF_CONFIG_MULTI | MLX5_TXOFF_CONFIG_TSO |
     415                 :            :                 MLX5_TXOFF_CONFIG_SWP | MLX5_TXOFF_CONFIG_CSUM |
     416                 :            :                 MLX5_TXOFF_CONFIG_METADATA)
     417                 :            : 
     418                 :            : MLX5_TXOFF_INFO(mti,
     419                 :            :                 MLX5_TXOFF_CONFIG_MULTI | MLX5_TXOFF_CONFIG_TSO |
     420                 :            :                 MLX5_TXOFF_CONFIG_INLINE |
     421                 :            :                 MLX5_TXOFF_CONFIG_METADATA)
     422                 :            : 
     423                 :            : MLX5_TXOFF_INFO(mtv,
     424                 :            :                 MLX5_TXOFF_CONFIG_MULTI | MLX5_TXOFF_CONFIG_TSO |
     425                 :            :                 MLX5_TXOFF_CONFIG_VLAN |
     426                 :            :                 MLX5_TXOFF_CONFIG_METADATA)
     427                 :            : 
     428                 :            : MLX5_TXOFF_INFO(mtiv,
     429                 :            :                 MLX5_TXOFF_CONFIG_MULTI | MLX5_TXOFF_CONFIG_TSO |
     430                 :            :                 MLX5_TXOFF_CONFIG_INLINE | MLX5_TXOFF_CONFIG_VLAN |
     431                 :            :                 MLX5_TXOFF_CONFIG_METADATA)
     432                 :            : 
     433                 :            : MLX5_TXOFF_INFO(sc,
     434                 :            :                 MLX5_TXOFF_CONFIG_SWP | MLX5_TXOFF_CONFIG_CSUM |
     435                 :            :                 MLX5_TXOFF_CONFIG_METADATA)
     436                 :            : 
     437                 :            : MLX5_TXOFF_INFO(sci,
     438                 :            :                 MLX5_TXOFF_CONFIG_SWP | MLX5_TXOFF_CONFIG_CSUM |
     439                 :            :                 MLX5_TXOFF_CONFIG_INLINE |
     440                 :            :                 MLX5_TXOFF_CONFIG_METADATA)
     441                 :            : 
     442                 :            : MLX5_TXOFF_INFO(scv,
     443                 :            :                 MLX5_TXOFF_CONFIG_SWP | MLX5_TXOFF_CONFIG_CSUM |
     444                 :            :                 MLX5_TXOFF_CONFIG_VLAN |
     445                 :            :                 MLX5_TXOFF_CONFIG_METADATA)
     446                 :            : 
     447                 :            : MLX5_TXOFF_INFO(sciv,
     448                 :            :                 MLX5_TXOFF_CONFIG_SWP | MLX5_TXOFF_CONFIG_CSUM |
     449                 :            :                 MLX5_TXOFF_CONFIG_INLINE | MLX5_TXOFF_CONFIG_VLAN |
     450                 :            :                 MLX5_TXOFF_CONFIG_METADATA)
     451                 :            : 
     452                 :            : MLX5_TXOFF_INFO(i,
     453                 :            :                 MLX5_TXOFF_CONFIG_INLINE |
     454                 :            :                 MLX5_TXOFF_CONFIG_METADATA)
     455                 :            : 
     456                 :            : MLX5_TXOFF_INFO(v,
     457                 :            :                 MLX5_TXOFF_CONFIG_VLAN |
     458                 :            :                 MLX5_TXOFF_CONFIG_METADATA)
     459                 :            : 
     460                 :            : MLX5_TXOFF_INFO(iv,
     461                 :            :                 MLX5_TXOFF_CONFIG_INLINE | MLX5_TXOFF_CONFIG_VLAN |
     462                 :            :                 MLX5_TXOFF_CONFIG_METADATA)
     463                 :            : 
     464                 :            : MLX5_TXOFF_INFO(none_mpw,
     465                 :            :                 MLX5_TXOFF_CONFIG_NONE | MLX5_TXOFF_CONFIG_EMPW |
     466                 :            :                 MLX5_TXOFF_CONFIG_MPW)
     467                 :            : 
     468                 :            : MLX5_TXOFF_INFO(mci_mpw,
     469                 :            :                 MLX5_TXOFF_CONFIG_MULTI | MLX5_TXOFF_CONFIG_CSUM |
     470                 :            :                 MLX5_TXOFF_CONFIG_INLINE | MLX5_TXOFF_CONFIG_EMPW |
     471                 :            :                 MLX5_TXOFF_CONFIG_MPW)
     472                 :            : 
     473                 :            : MLX5_TXOFF_INFO(mc_mpw,
     474                 :            :                 MLX5_TXOFF_CONFIG_MULTI | MLX5_TXOFF_CONFIG_CSUM |
     475                 :            :                 MLX5_TXOFF_CONFIG_EMPW | MLX5_TXOFF_CONFIG_MPW)
     476                 :            : 
     477                 :            : MLX5_TXOFF_INFO(i_mpw,
     478                 :            :                 MLX5_TXOFF_CONFIG_INLINE | MLX5_TXOFF_CONFIG_EMPW |
     479                 :            :                 MLX5_TXOFF_CONFIG_MPW)
     480                 :            : };
     481                 :            : 
     482                 :            : /**
     483                 :            :  * Configure the Tx function to use. The routine checks configured
     484                 :            :  * Tx offloads for the device and selects appropriate Tx burst routine.
     485                 :            :  * There are multiple Tx burst routines compiled from the same template
     486                 :            :  * in the most optimal way for the dedicated Tx offloads set.
     487                 :            :  *
     488                 :            :  * @param dev
     489                 :            :  *   Pointer to private data structure.
     490                 :            :  *
     491                 :            :  * @return
     492                 :            :  *   Pointer to selected Tx burst function.
     493                 :            :  */
     494                 :            : eth_tx_burst_t
     495                 :          0 : mlx5_select_tx_function(struct rte_eth_dev *dev)
     496                 :            : {
     497                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
     498                 :            :         struct mlx5_port_config *config = &priv->config;
     499                 :          0 :         uint64_t tx_offloads = dev->data->dev_conf.txmode.offloads;
     500                 :            :         unsigned int diff = 0, olx = 0, i, m;
     501                 :            : 
     502                 :            :         MLX5_ASSERT(priv);
     503         [ #  # ]:          0 :         if (tx_offloads & RTE_ETH_TX_OFFLOAD_MULTI_SEGS) {
     504                 :            :                 /* We should support Multi-Segment Packets. */
     505                 :            :                 olx |= MLX5_TXOFF_CONFIG_MULTI;
     506                 :            :         }
     507         [ #  # ]:          0 :         if (tx_offloads & (RTE_ETH_TX_OFFLOAD_TCP_TSO |
     508                 :            :                            RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO |
     509                 :            :                            RTE_ETH_TX_OFFLOAD_GRE_TNL_TSO |
     510                 :            :                            RTE_ETH_TX_OFFLOAD_IP_TNL_TSO |
     511                 :            :                            RTE_ETH_TX_OFFLOAD_UDP_TNL_TSO)) {
     512                 :            :                 /* We should support TCP Send Offload. */
     513                 :          0 :                 olx |= MLX5_TXOFF_CONFIG_TSO;
     514                 :            :         }
     515         [ #  # ]:          0 :         if (tx_offloads & (RTE_ETH_TX_OFFLOAD_IP_TNL_TSO |
     516                 :            :                            RTE_ETH_TX_OFFLOAD_UDP_TNL_TSO |
     517                 :            :                            RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM)) {
     518                 :            :                 /* We should support Software Parser for Tunnels. */
     519                 :          0 :                 olx |= MLX5_TXOFF_CONFIG_SWP;
     520                 :            :         }
     521         [ #  # ]:          0 :         if (tx_offloads & (RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
     522                 :            :                            RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
     523                 :            :                            RTE_ETH_TX_OFFLOAD_TCP_CKSUM |
     524                 :            :                            RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM)) {
     525                 :            :                 /* We should support IP/TCP/UDP Checksums. */
     526                 :          0 :                 olx |= MLX5_TXOFF_CONFIG_CSUM;
     527                 :            :         }
     528         [ #  # ]:          0 :         if (tx_offloads & RTE_ETH_TX_OFFLOAD_VLAN_INSERT) {
     529                 :            :                 /* We should support VLAN insertion. */
     530                 :          0 :                 olx |= MLX5_TXOFF_CONFIG_VLAN;
     531                 :            :         }
     532   [ #  #  #  # ]:          0 :         if (tx_offloads & RTE_ETH_TX_OFFLOAD_SEND_ON_TIMESTAMP &&
     533                 :          0 :             rte_mbuf_dynflag_lookup
     534         [ #  # ]:          0 :                         (RTE_MBUF_DYNFLAG_TX_TIMESTAMP_NAME, NULL) >= 0 &&
     535                 :          0 :             rte_mbuf_dynfield_lookup
     536                 :            :                         (RTE_MBUF_DYNFIELD_TIMESTAMP_NAME, NULL) >= 0) {
     537                 :            :                 /* Offload configured, dynamic entities registered. */
     538                 :          0 :                 olx |= MLX5_TXOFF_CONFIG_TXPP;
     539                 :            :         }
     540   [ #  #  #  # ]:          0 :         if (priv->txqs_n && (*priv->txqs)[0]) {
     541                 :            :                 struct mlx5_txq_data *txd = (*priv->txqs)[0];
     542                 :            : 
     543         [ #  # ]:          0 :                 if (txd->inlen_send) {
     544                 :            :                         /*
     545                 :            :                          * Check the data inline requirements. Data inline
     546                 :            :                          * is enabled on per device basis, we can check
     547                 :            :                          * the first Tx queue only.
     548                 :            :                          *
     549                 :            :                          * If device does not support VLAN insertion in WQE
     550                 :            :                          * and some queues are requested to perform VLAN
     551                 :            :                          * insertion offload than inline must be enabled.
     552                 :            :                          */
     553                 :          0 :                         olx |= MLX5_TXOFF_CONFIG_INLINE;
     554                 :            :                 }
     555                 :            :         }
     556         [ #  # ]:          0 :         if (config->mps == MLX5_MPW_ENHANCED &&
     557         [ #  # ]:          0 :             config->txq_inline_min <= 0) {
     558                 :            :                 /*
     559                 :            :                  * The NIC supports Enhanced Multi-Packet Write
     560                 :            :                  * and does not require minimal inline data.
     561                 :            :                  */
     562                 :          0 :                 olx |= MLX5_TXOFF_CONFIG_EMPW;
     563                 :            :         }
     564         [ #  # ]:          0 :         if (rte_flow_dynf_metadata_avail()) {
     565                 :            :                 /* We should support Flow metadata. */
     566                 :          0 :                 olx |= MLX5_TXOFF_CONFIG_METADATA;
     567                 :            :         }
     568         [ #  # ]:          0 :         if (config->mps == MLX5_MPW) {
     569                 :            :                 /*
     570                 :            :                  * The NIC supports Legacy Multi-Packet Write.
     571                 :            :                  * The MLX5_TXOFF_CONFIG_MPW controls the descriptor building
     572                 :            :                  * method in combination with MLX5_TXOFF_CONFIG_EMPW.
     573                 :            :                  */
     574         [ #  # ]:          0 :                 if (!(olx & (MLX5_TXOFF_CONFIG_TSO |
     575                 :            :                              MLX5_TXOFF_CONFIG_SWP |
     576                 :            :                              MLX5_TXOFF_CONFIG_VLAN |
     577                 :            :                              MLX5_TXOFF_CONFIG_METADATA)))
     578                 :          0 :                         olx |= MLX5_TXOFF_CONFIG_EMPW |
     579                 :            :                                MLX5_TXOFF_CONFIG_MPW;
     580                 :            :         }
     581                 :            :         /*
     582                 :            :          * Scan the routines table to find the minimal
     583                 :            :          * satisfying routine with requested offloads.
     584                 :            :          */
     585                 :            :         m = RTE_DIM(txoff_func);
     586         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(txoff_func); i++) {
     587                 :            :                 unsigned int tmp;
     588                 :            : 
     589                 :          0 :                 tmp = txoff_func[i].olx;
     590         [ #  # ]:          0 :                 if (tmp == olx) {
     591                 :            :                         /* Meets requested offloads exactly.*/
     592                 :            :                         m = i;
     593                 :            :                         break;
     594                 :            :                 }
     595         [ #  # ]:          0 :                 if ((tmp & olx) != olx) {
     596                 :            :                         /* Does not meet requested offloads at all. */
     597                 :          0 :                         continue;
     598                 :            :                 }
     599         [ #  # ]:          0 :                 if ((olx ^ tmp) & MLX5_TXOFF_CONFIG_MPW)
     600                 :            :                         /* Do not enable legacy MPW if not configured. */
     601                 :          0 :                         continue;
     602         [ #  # ]:          0 :                 if ((olx ^ tmp) & MLX5_TXOFF_CONFIG_EMPW)
     603                 :            :                         /* Do not enable eMPW if not configured. */
     604                 :          0 :                         continue;
     605         [ #  # ]:          0 :                 if ((olx ^ tmp) & MLX5_TXOFF_CONFIG_INLINE)
     606                 :            :                         /* Do not enable inlining if not configured. */
     607                 :          0 :                         continue;
     608         [ #  # ]:          0 :                 if ((olx ^ tmp) & MLX5_TXOFF_CONFIG_TXPP)
     609                 :            :                         /* Do not enable scheduling if not configured. */
     610                 :          0 :                         continue;
     611                 :            :                 /*
     612                 :            :                  * Some routine meets the requirements.
     613                 :            :                  * Check whether it has minimal amount
     614                 :            :                  * of not requested offloads.
     615                 :            :                  */
     616         [ #  # ]:          0 :                 tmp = rte_popcount64(tmp & ~olx);
     617         [ #  # ]:          0 :                 if (m >= RTE_DIM(txoff_func) || tmp < diff) {
     618                 :            :                         /* First or better match, save and continue. */
     619                 :            :                         m = i;
     620                 :            :                         diff = tmp;
     621                 :          0 :                         continue;
     622                 :            :                 }
     623         [ #  # ]:          0 :                 if (tmp == diff) {
     624                 :          0 :                         tmp = txoff_func[i].olx ^ txoff_func[m].olx;
     625         [ #  # ]:          0 :                         if (rte_ffs32(txoff_func[i].olx & ~tmp) <
     626         [ #  # ]:          0 :                             rte_ffs32(txoff_func[m].olx & ~tmp)) {
     627                 :            :                                 /* Lighter not requested offload. */
     628                 :            :                                 m = i;
     629                 :            :                         }
     630                 :            :                 }
     631                 :            :         }
     632         [ #  # ]:          0 :         if (m >= RTE_DIM(txoff_func)) {
     633                 :          0 :                 DRV_LOG(DEBUG, "port %u has no selected Tx function"
     634                 :            :                                " for requested offloads %04X",
     635                 :            :                                 dev->data->port_id, olx);
     636                 :          0 :                 return NULL;
     637                 :            :         }
     638                 :          0 :         DRV_LOG(DEBUG, "port %u has selected Tx function"
     639                 :            :                        " supporting offloads %04X/%04X",
     640                 :            :                         dev->data->port_id, olx, txoff_func[m].olx);
     641         [ #  # ]:          0 :         if (txoff_func[m].olx & MLX5_TXOFF_CONFIG_MULTI)
     642                 :          0 :                 DRV_LOG(DEBUG, "\tMULTI (multi segment)");
     643         [ #  # ]:          0 :         if (txoff_func[m].olx & MLX5_TXOFF_CONFIG_TSO)
     644                 :          0 :                 DRV_LOG(DEBUG, "\tTSO   (TCP send offload)");
     645         [ #  # ]:          0 :         if (txoff_func[m].olx & MLX5_TXOFF_CONFIG_SWP)
     646                 :          0 :                 DRV_LOG(DEBUG, "\tSWP   (software parser)");
     647         [ #  # ]:          0 :         if (txoff_func[m].olx & MLX5_TXOFF_CONFIG_CSUM)
     648                 :          0 :                 DRV_LOG(DEBUG, "\tCSUM  (checksum offload)");
     649         [ #  # ]:          0 :         if (txoff_func[m].olx & MLX5_TXOFF_CONFIG_INLINE)
     650                 :          0 :                 DRV_LOG(DEBUG, "\tINLIN (inline data)");
     651         [ #  # ]:          0 :         if (txoff_func[m].olx & MLX5_TXOFF_CONFIG_VLAN)
     652                 :          0 :                 DRV_LOG(DEBUG, "\tVLANI (VLAN insertion)");
     653         [ #  # ]:          0 :         if (txoff_func[m].olx & MLX5_TXOFF_CONFIG_METADATA)
     654                 :          0 :                 DRV_LOG(DEBUG, "\tMETAD (tx Flow metadata)");
     655         [ #  # ]:          0 :         if (txoff_func[m].olx & MLX5_TXOFF_CONFIG_TXPP)
     656                 :          0 :                 DRV_LOG(DEBUG, "\tMETAD (tx Scheduling)");
     657         [ #  # ]:          0 :         if (txoff_func[m].olx & MLX5_TXOFF_CONFIG_EMPW) {
     658         [ #  # ]:          0 :                 if (txoff_func[m].olx & MLX5_TXOFF_CONFIG_MPW)
     659                 :          0 :                         DRV_LOG(DEBUG, "\tMPW   (Legacy MPW)");
     660                 :            :                 else
     661                 :          0 :                         DRV_LOG(DEBUG, "\tEMPW  (Enhanced MPW)");
     662                 :            :         }
     663                 :          0 :         return txoff_func[m].func;
     664                 :            : }
     665                 :            : 
     666                 :            : /**
     667                 :            :  * DPDK callback to get the TX queue information.
     668                 :            :  *
     669                 :            :  * @param dev
     670                 :            :  *   Pointer to the device structure.
     671                 :            :  *
     672                 :            :  * @param tx_queue_id
     673                 :            :  *   Tx queue identificator.
     674                 :            :  *
     675                 :            :  * @param qinfo
     676                 :            :  *   Pointer to the TX queue information structure.
     677                 :            :  *
     678                 :            :  * @return
     679                 :            :  *   None.
     680                 :            :  */
     681                 :            : void
     682                 :          0 : mlx5_txq_info_get(struct rte_eth_dev *dev, uint16_t tx_queue_id,
     683                 :            :                   struct rte_eth_txq_info *qinfo)
     684                 :            : {
     685                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
     686                 :          0 :         struct mlx5_txq_data *txq = (*priv->txqs)[tx_queue_id];
     687                 :            :         struct mlx5_txq_ctrl *txq_ctrl =
     688                 :            :                         container_of(txq, struct mlx5_txq_ctrl, txq);
     689                 :            : 
     690         [ #  # ]:          0 :         if (!txq)
     691                 :            :                 return;
     692                 :          0 :         qinfo->nb_desc = txq->elts_s;
     693                 :          0 :         qinfo->conf.tx_thresh.pthresh = 0;
     694                 :          0 :         qinfo->conf.tx_thresh.hthresh = 0;
     695                 :          0 :         qinfo->conf.tx_thresh.wthresh = 0;
     696                 :          0 :         qinfo->conf.tx_rs_thresh = 0;
     697                 :          0 :         qinfo->conf.tx_free_thresh = 0;
     698                 :          0 :         qinfo->conf.tx_deferred_start = txq_ctrl ? 0 : 1;
     699                 :          0 :         qinfo->conf.offloads = dev->data->dev_conf.txmode.offloads;
     700                 :            : }
     701                 :            : 
     702                 :            : /**
     703                 :            :  * DPDK callback to get the TX packet burst mode information.
     704                 :            :  *
     705                 :            :  * @param dev
     706                 :            :  *   Pointer to the device structure.
     707                 :            :  *
     708                 :            :  * @param tx_queue_id
     709                 :            :  *   Tx queue identification.
     710                 :            :  *
     711                 :            :  * @param mode
     712                 :            :  *   Pointer to the burts mode information.
     713                 :            :  *
     714                 :            :  * @return
     715                 :            :  *   0 as success, -EINVAL as failure.
     716                 :            :  */
     717                 :            : int
     718                 :          0 : mlx5_tx_burst_mode_get(struct rte_eth_dev *dev,
     719                 :            :                        uint16_t tx_queue_id,
     720                 :            :                        struct rte_eth_burst_mode *mode)
     721                 :            : {
     722                 :          0 :         eth_tx_burst_t pkt_burst = dev->tx_pkt_burst;
     723                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
     724                 :          0 :         struct mlx5_txq_data *txq = (*priv->txqs)[tx_queue_id];
     725                 :            :         unsigned int i, olx;
     726                 :            : 
     727         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(txoff_func); i++) {
     728         [ #  # ]:          0 :                 if (pkt_burst == txoff_func[i].func) {
     729                 :          0 :                         olx = txoff_func[i].olx;
     730         [ #  # ]:          0 :                         snprintf(mode->info, sizeof(mode->info),
     731                 :            :                                  "%s%s%s%s%s%s%s%s%s%s",
     732         [ #  # ]:          0 :                                  (olx & MLX5_TXOFF_CONFIG_EMPW) ?
     733                 :          0 :                                  ((olx & MLX5_TXOFF_CONFIG_MPW) ?
     734         [ #  # ]:          0 :                                  "Legacy MPW" : "Enhanced MPW") : "No MPW",
     735         [ #  # ]:          0 :                                  (olx & MLX5_TXOFF_CONFIG_MULTI) ?
     736                 :            :                                  " + MULTI" : "",
     737         [ #  # ]:          0 :                                  (olx & MLX5_TXOFF_CONFIG_TSO) ?
     738                 :            :                                  " + TSO" : "",
     739         [ #  # ]:          0 :                                  (olx & MLX5_TXOFF_CONFIG_SWP) ?
     740                 :            :                                  " + SWP" : "",
     741         [ #  # ]:          0 :                                  (olx & MLX5_TXOFF_CONFIG_CSUM) ?
     742                 :            :                                  "  + CSUM" : "",
     743         [ #  # ]:          0 :                                  (olx & MLX5_TXOFF_CONFIG_INLINE) ?
     744                 :            :                                  " + INLINE" : "",
     745         [ #  # ]:          0 :                                  (olx & MLX5_TXOFF_CONFIG_VLAN) ?
     746                 :            :                                  " + VLAN" : "",
     747         [ #  # ]:          0 :                                  (olx & MLX5_TXOFF_CONFIG_METADATA) ?
     748                 :            :                                  " + METADATA" : "",
     749         [ #  # ]:          0 :                                  (olx & MLX5_TXOFF_CONFIG_TXPP) ?
     750                 :            :                                  " + TXPP" : "",
     751         [ #  # ]:          0 :                                  (txq && txq->fast_free) ?
     752                 :            :                                  " + Fast Free" : "");
     753                 :          0 :                         return 0;
     754                 :            :                 }
     755                 :            :         }
     756                 :            :         return -EINVAL;
     757                 :            : }
     758                 :            : 
     759                 :            : /**
     760                 :            :  * Dump SQ/CQ Context to a file.
     761                 :            :  *
     762                 :            :  * @param[in] port_id
     763                 :            :  *   Port ID
     764                 :            :  * @param[in] queue_id
     765                 :            :  *   Queue ID
     766                 :            :  * @param[in] filename
     767                 :            :  *   Name of file to dump the Tx Queue Context
     768                 :            :  *
     769                 :            :  * @return
     770                 :            :  *   0 for success, non-zero value depending on failure.
     771                 :            :  *
     772                 :            :  */
     773                 :            : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_mlx5_txq_dump_contexts, 24.07)
     774                 :          0 : int rte_pmd_mlx5_txq_dump_contexts(uint16_t port_id, uint16_t queue_id, const char *filename)
     775                 :            : {
     776                 :            :         struct rte_eth_dev *dev;
     777                 :            :         struct mlx5_priv *priv;
     778                 :            :         struct mlx5_txq_data *txq_data;
     779                 :            :         struct mlx5_txq_ctrl *txq_ctrl;
     780                 :            :         struct mlx5_txq_obj *txq_obj;
     781                 :            :         struct mlx5_devx_sq *sq;
     782                 :            :         struct mlx5_devx_cq *cq;
     783                 :            :         struct mlx5_devx_obj *sq_devx_obj;
     784                 :            :         struct mlx5_devx_obj *cq_devx_obj;
     785                 :            : 
     786                 :          0 :         uint32_t sq_out[MLX5_ST_SZ_DW(query_sq_out)] = {0};
     787                 :          0 :         uint32_t cq_out[MLX5_ST_SZ_DW(query_cq_out)] = {0};
     788                 :            : 
     789                 :            :         int ret;
     790                 :            :         FILE *fd;
     791                 :          0 :         MKSTR(path, "./%s", filename);
     792                 :            : 
     793         [ #  # ]:          0 :         if (!rte_eth_dev_is_valid_port(port_id))
     794                 :            :                 return -ENODEV;
     795                 :            : 
     796         [ #  # ]:          0 :         if (rte_eth_tx_queue_is_valid(port_id, queue_id) != 0)
     797                 :            :                 return -EINVAL;
     798                 :            : 
     799                 :          0 :         fd = fopen(path, "w");
     800         [ #  # ]:          0 :         if (!fd) {
     801                 :          0 :                 rte_errno = errno;
     802                 :          0 :                 return -EIO;
     803                 :            :         }
     804                 :            : 
     805                 :            :         dev = &rte_eth_devices[port_id];
     806                 :          0 :         priv = dev->data->dev_private;
     807                 :          0 :         txq_data = (*priv->txqs)[queue_id];
     808                 :          0 :         txq_ctrl = container_of(txq_data, struct mlx5_txq_ctrl, txq);
     809                 :          0 :         txq_obj = txq_ctrl->obj;
     810                 :            :         sq = &txq_obj->sq_obj;
     811                 :            :         cq = &txq_obj->cq_obj;
     812                 :          0 :         sq_devx_obj = sq->sq;
     813                 :          0 :         cq_devx_obj = cq->cq;
     814                 :            : 
     815                 :            :         do {
     816                 :          0 :                 ret = mlx5_devx_cmd_query_sq(sq_devx_obj, sq_out, sizeof(sq_out));
     817         [ #  # ]:          0 :                 if (ret)
     818                 :            :                         break;
     819                 :            : 
     820                 :            :                 /* Dump sq query output to file */
     821                 :          0 :                 MKSTR(sq_headline, "SQ DevX ID = %u Port = %u Queue index = %u ",
     822                 :            :                                         sq_devx_obj->id, port_id, queue_id);
     823                 :          0 :                 mlx5_dump_to_file(fd, NULL, sq_headline, 0);
     824                 :          0 :                 mlx5_dump_to_file(fd, "Query SQ Dump:",
     825                 :            :                                         (const void *)((uintptr_t)sq_out),
     826                 :            :                                         sizeof(sq_out));
     827                 :            : 
     828                 :          0 :                 ret = mlx5_devx_cmd_query_cq(cq_devx_obj, cq_out, sizeof(cq_out));
     829         [ #  # ]:          0 :                 if (ret)
     830                 :            :                         break;
     831                 :            : 
     832                 :            :                 /* Dump cq query output to file */
     833                 :          0 :                 MKSTR(cq_headline, "CQ DevX ID = %u Port = %u Queue index = %u ",
     834                 :            :                                                 cq_devx_obj->id, port_id, queue_id);
     835                 :          0 :                 mlx5_dump_to_file(fd, NULL, cq_headline, 0);
     836                 :          0 :                 mlx5_dump_to_file(fd, "Query CQ Dump:",
     837                 :            :                                         (const void *)((uintptr_t)cq_out),
     838                 :            :                                         sizeof(cq_out));
     839                 :            :         } while (false);
     840                 :            : 
     841                 :          0 :         fclose(fd);
     842                 :          0 :         return ret;
     843                 :            : }
     844                 :            : 
     845                 :            : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_mlx5_txq_rate_limit_query, 26.07)
     846                 :          0 : int rte_pmd_mlx5_txq_rate_limit_query(uint16_t port_id, uint16_t queue_id,
     847                 :            :                 struct rte_pmd_mlx5_txq_rate_limit_info *info)
     848                 :            : {
     849                 :            :         struct rte_eth_dev *dev;
     850                 :            :         struct mlx5_priv *priv;
     851                 :            :         struct mlx5_txq_data *txq_data;
     852                 :            :         struct mlx5_txq_ctrl *txq_ctrl;
     853                 :          0 :         uint32_t sq_out[MLX5_ST_SZ_DW(query_sq_out)] = {0};
     854                 :            :         int ret;
     855                 :            : 
     856         [ #  # ]:          0 :         if (info == NULL)
     857                 :            :                 return -EINVAL;
     858         [ #  # ]:          0 :         if (!rte_eth_dev_is_valid_port(port_id))
     859                 :            :                 return -ENODEV;
     860         [ #  # ]:          0 :         if (rte_eth_tx_queue_is_valid(port_id, queue_id) != 0)
     861                 :            :                 return -EINVAL;
     862                 :            :         dev = &rte_eth_devices[port_id];
     863                 :          0 :         priv = dev->data->dev_private;
     864                 :          0 :         txq_data = (*priv->txqs)[queue_id];
     865         [ #  # ]:          0 :         if (txq_data == NULL)
     866                 :            :                 return -EINVAL;
     867                 :          0 :         txq_ctrl = container_of(txq_data, struct mlx5_txq_ctrl, txq);
     868                 :          0 :         info->rate_mbps = txq_ctrl->rate_limit.rate_mbps;
     869                 :          0 :         info->pp_index = txq_ctrl->rate_limit.pp_id;
     870         [ #  # ]:          0 :         if (txq_ctrl->obj == NULL) {
     871                 :          0 :                 info->fw_pp_index = 0;
     872                 :          0 :                 return 0;
     873                 :            :         }
     874                 :          0 :         ret = mlx5_devx_cmd_query_sq(txq_ctrl->obj->sq_obj.sq,
     875                 :            :                                      sq_out, sizeof(sq_out));
     876         [ #  # ]:          0 :         if (ret)
     877                 :            :                 return -EIO;
     878         [ #  # ]:          0 :         info->fw_pp_index = MLX5_GET(sqc,
     879                 :            :                                      MLX5_ADDR_OF(query_sq_out, sq_out,
     880                 :            :                                                   sq_context),
     881                 :            :                                      packet_pacing_rate_limit_index);
     882                 :          0 :         return 0;
     883                 :            : }
     884                 :            : 
     885                 :            : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_mlx5_pp_rate_table_query, 26.07)
     886                 :          0 : int rte_pmd_mlx5_pp_rate_table_query(uint16_t port_id,
     887                 :            :                 struct rte_pmd_mlx5_pp_rate_table_info *info)
     888                 :            : {
     889                 :            :         struct rte_eth_dev *dev;
     890                 :            :         struct mlx5_priv *priv;
     891                 :            :         uint16_t used = 0;
     892                 :            :         uint16_t *seen;
     893                 :            :         unsigned int i;
     894                 :            : 
     895         [ #  # ]:          0 :         if (info == NULL)
     896                 :            :                 return -EINVAL;
     897         [ #  # ]:          0 :         if (!rte_eth_dev_is_valid_port(port_id))
     898                 :            :                 return -ENODEV;
     899                 :            :         dev = &rte_eth_devices[port_id];
     900                 :          0 :         priv = dev->data->dev_private;
     901         [ #  # ]:          0 :         if (!priv->sh->cdev->config.hca_attr.qos.packet_pacing) {
     902                 :          0 :                 rte_errno = ENOTSUP;
     903                 :          0 :                 return -ENOTSUP;
     904                 :            :         }
     905                 :          0 :         info->total = priv->sh->cdev->config.hca_attr.qos.packet_pacing_rate_table_size;
     906   [ #  #  #  # ]:          0 :         if (priv->txqs == NULL || priv->txqs_n == 0) {
     907                 :          0 :                 info->port_used = 0;
     908                 :          0 :                 return 0;
     909                 :            :         }
     910                 :          0 :         seen = mlx5_malloc(MLX5_MEM_SYS | MLX5_MEM_ZERO,
     911                 :          0 :                            priv->txqs_n * sizeof(*seen), 0, SOCKET_ID_ANY);
     912         [ #  # ]:          0 :         if (seen == NULL)
     913                 :            :                 return -ENOMEM;
     914                 :            :         /*
     915                 :            :          * Count unique non-zero PP indices across this port's Tx queues.
     916                 :            :          * Note: the count reflects only queues on this port; other ports
     917                 :            :          * sharing the same device may also consume rate table entries.
     918                 :            :          */
     919         [ #  # ]:          0 :         for (i = 0; i < priv->txqs_n; i++) {
     920                 :            :                 struct mlx5_txq_data *txq_data;
     921                 :            :                 struct mlx5_txq_ctrl *txq_ctrl;
     922                 :            :                 uint16_t pp_id;
     923                 :            :                 uint16_t j;
     924                 :            :                 bool dup;
     925                 :            : 
     926         [ #  # ]:          0 :                 if ((*priv->txqs)[i] == NULL)
     927                 :          0 :                         continue;
     928                 :            :                 txq_data = (*priv->txqs)[i];
     929                 :          0 :                 txq_ctrl = container_of(txq_data, struct mlx5_txq_ctrl, txq);
     930                 :          0 :                 pp_id = txq_ctrl->rate_limit.pp_id;
     931         [ #  # ]:          0 :                 if (pp_id == 0)
     932                 :          0 :                         continue;
     933                 :            :                 dup = false;
     934         [ #  # ]:          0 :                 for (j = 0; j < used; j++) {
     935         [ #  # ]:          0 :                         if (seen[j] == pp_id) {
     936                 :            :                                 dup = true;
     937                 :            :                                 break;
     938                 :            :                         }
     939                 :            :                 }
     940         [ #  # ]:          0 :                 if (!dup)
     941                 :          0 :                         seen[used++] = pp_id;
     942                 :            :         }
     943                 :          0 :         mlx5_free(seen);
     944                 :          0 :         info->port_used = used;
     945                 :          0 :         return 0;
     946                 :            : }

Generated by: LCOV version 1.14