LCOV - code coverage report
Current view: top level - drivers/net/intel/common - tx.h (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 88 0.0 %
Date: 2026-04-01 20:02:27 Functions: 0 2 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 218 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2024 Intel Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #ifndef _COMMON_INTEL_TX_H_
       6                 :            : #define _COMMON_INTEL_TX_H_
       7                 :            : 
       8                 :            : #include <stdint.h>
       9                 :            : #include <rte_mbuf.h>
      10                 :            : #include <rte_ethdev.h>
      11                 :            : #include <rte_vect.h>
      12                 :            : 
      13                 :            : /* Common TX Descriptor QW1 Field Definitions */
      14                 :            : #define CI_TXD_QW1_DTYPE_S      0
      15                 :            : #define CI_TXD_QW1_DTYPE_M      (0xFUL << CI_TXD_QW1_DTYPE_S)
      16                 :            : #define CI_TXD_QW1_CMD_S        4
      17                 :            : #define CI_TXD_QW1_CMD_M        (0xFFFUL << CI_TXD_QW1_CMD_S)
      18                 :            : #define CI_TXD_QW1_OFFSET_S     16
      19                 :            : #define CI_TXD_QW1_OFFSET_M     (0x3FFFFULL << CI_TXD_QW1_OFFSET_S)
      20                 :            : #define CI_TXD_QW1_TX_BUF_SZ_S  34
      21                 :            : #define CI_TXD_QW1_TX_BUF_SZ_M  (0x3FFFULL << CI_TXD_QW1_TX_BUF_SZ_S)
      22                 :            : #define CI_TXD_QW1_L2TAG1_S     48
      23                 :            : #define CI_TXD_QW1_L2TAG1_M     (0xFFFFULL << CI_TXD_QW1_L2TAG1_S)
      24                 :            : 
      25                 :            : /* Common Descriptor Types */
      26                 :            : #define CI_TX_DESC_DTYPE_DATA           0x0
      27                 :            : #define CI_TX_DESC_DTYPE_CTX            0x1
      28                 :            : #define CI_TX_DESC_DTYPE_DESC_DONE      0xF
      29                 :            : 
      30                 :            : /* Common TX Descriptor Command Flags */
      31                 :            : #define CI_TX_DESC_CMD_EOP              0x0001
      32                 :            : #define CI_TX_DESC_CMD_RS               0x0002
      33                 :            : #define CI_TX_DESC_CMD_ICRC             0x0004
      34                 :            : #define CI_TX_DESC_CMD_IL2TAG1          0x0008
      35                 :            : #define CI_TX_DESC_CMD_DUMMY            0x0010
      36                 :            : #define CI_TX_DESC_CMD_IIPT_IPV6        0x0020
      37                 :            : #define CI_TX_DESC_CMD_IIPT_IPV4        0x0040
      38                 :            : #define CI_TX_DESC_CMD_IIPT_IPV4_CSUM   0x0060
      39                 :            : #define CI_TX_DESC_CMD_L4T_EOFT_TCP     0x0100
      40                 :            : #define CI_TX_DESC_CMD_L4T_EOFT_SCTP    0x0200
      41                 :            : #define CI_TX_DESC_CMD_L4T_EOFT_UDP     0x0300
      42                 :            : 
      43                 :            : /* Common TX Context Descriptor Commands */
      44                 :            : #define CI_TX_CTX_DESC_TSO              0x01
      45                 :            : #define CI_TX_CTX_DESC_TSYN             0x02
      46                 :            : #define CI_TX_CTX_DESC_IL2TAG2          0x04
      47                 :            : 
      48                 :            : /**
      49                 :            :  * L2TAG1 Field Source Selection
      50                 :            :  * Specifies which mbuf VLAN field to use for the L2TAG1 field in data descriptors.
      51                 :            :  * Context descriptor VLAN handling (L2TAG2) is managed by driver-specific callbacks.
      52                 :            :  */
      53                 :            : enum ci_tx_l2tag1_field {
      54                 :            :         /** For VLAN (not QinQ), use L2Tag1 field in data desc */
      55                 :            :         CI_VLAN_IN_L2TAG1,
      56                 :            : 
      57                 :            :         /** For VLAN (not QinQ), use L2Tag2 field in ctx desc.
      58                 :            :          * NOTE: When set, drivers must set the VLAN tag in the context
      59                 :            :          * descriptor callback function, rather than relying on the
      60                 :            :          * common Tx code to insert it.
      61                 :            :          */
      62                 :            :         CI_VLAN_IN_L2TAG2,
      63                 :            : };
      64                 :            : 
      65                 :            : /* Common TX Descriptor Length Field Shifts */
      66                 :            : #define CI_TX_DESC_LEN_MACLEN_S         0  /* 7 BITS */
      67                 :            : #define CI_TX_DESC_LEN_IPLEN_S          7  /* 7 BITS */
      68                 :            : #define CI_TX_DESC_LEN_L4_LEN_S         14 /* 4 BITS */
      69                 :            : 
      70                 :            : /* Common maximum data per TX descriptor */
      71                 :            : #define CI_MAX_DATA_PER_TXD     (CI_TXD_QW1_TX_BUF_SZ_M >> CI_TXD_QW1_TX_BUF_SZ_S)
      72                 :            : 
      73                 :            : /* Common TX maximum burst size for chunked transmission in simple paths */
      74                 :            : #define CI_TX_MAX_BURST 32
      75                 :            : 
      76                 :            : /* Common TX maximum free buffer size for batched bulk freeing */
      77                 :            : #define CI_TX_MAX_FREE_BUF_SZ 64
      78                 :            : 
      79                 :            : /* Common TX descriptor command flags for simple transmit */
      80                 :            : #define CI_TX_DESC_CMD_DEFAULT (CI_TX_DESC_CMD_ICRC | CI_TX_DESC_CMD_EOP)
      81                 :            : 
      82                 :            : /* Checksum offload mask to identify packets requesting offload */
      83                 :            : #define CI_TX_CKSUM_OFFLOAD_MASK (RTE_MBUF_F_TX_IP_CKSUM |               \
      84                 :            :                                    RTE_MBUF_F_TX_L4_MASK |               \
      85                 :            :                                    RTE_MBUF_F_TX_TCP_SEG |               \
      86                 :            :                                    RTE_MBUF_F_TX_UDP_SEG |               \
      87                 :            :                                    RTE_MBUF_F_TX_OUTER_IP_CKSUM |        \
      88                 :            :                                    RTE_MBUF_F_TX_OUTER_UDP_CKSUM)
      89                 :            : 
      90                 :            : /**
      91                 :            :  * Common TX offload union for Intel drivers.
      92                 :            :  * Supports both basic offloads (l2_len, l3_len, l4_len, tso_segsz) and
      93                 :            :  * extended offloads (outer_l2_len, outer_l3_len) for tunneling support.
      94                 :            :  */
      95                 :            : union ci_tx_offload {
      96                 :            :         uint64_t data;
      97                 :            :         struct {
      98                 :            :                 uint64_t l2_len:7;        /**< L2 (MAC) Header Length. */
      99                 :            :                 uint64_t l3_len:9;        /**< L3 (IP) Header Length. */
     100                 :            :                 uint64_t l4_len:8;        /**< L4 Header Length. */
     101                 :            :                 uint64_t tso_segsz:16;    /**< TCP TSO segment size */
     102                 :            :                 uint64_t outer_l2_len:8;  /**< outer L2 Header Length */
     103                 :            :                 uint64_t outer_l3_len:16; /**< outer L3 Header Length */
     104                 :            :         };
     105                 :            : };
     106                 :            : 
     107                 :            : /*
     108                 :            :  * Structure of a 16-byte Tx descriptor common across i40e, ice, iavf and idpf drivers
     109                 :            :  */
     110                 :            : struct ci_tx_desc {
     111                 :            :         uint64_t buffer_addr; /* Address of descriptor's data buf */
     112                 :            :         uint64_t cmd_type_offset_bsz;
     113                 :            : };
     114                 :            : 
     115                 :            : /* forward declaration of the common intel (ci) queue structure */
     116                 :            : struct ci_tx_queue;
     117                 :            : 
     118                 :            : /**
     119                 :            :  * Structure associated with each descriptor of the TX ring of a TX queue.
     120                 :            :  */
     121                 :            : struct ci_tx_entry {
     122                 :            :         struct rte_mbuf *mbuf; /* mbuf associated with TX desc, if any. */
     123                 :            :         uint16_t next_id; /* Index of next descriptor in ring. */
     124                 :            : };
     125                 :            : 
     126                 :            : /**
     127                 :            :  * Structure associated with each descriptor of the TX ring of a TX queue in vector Tx.
     128                 :            :  */
     129                 :            : struct ci_tx_entry_vec {
     130                 :            :         struct rte_mbuf *mbuf; /* mbuf associated with TX desc, if any. */
     131                 :            : };
     132                 :            : 
     133                 :            : typedef void (*ice_tx_release_mbufs_t)(struct ci_tx_queue *txq);
     134                 :            : 
     135                 :            : struct ci_tx_queue {
     136                 :            :         union { /* TX ring virtual address */
     137                 :            :                 volatile struct ci_tx_desc *ci_tx_ring;
     138                 :            :                 volatile union ixgbe_adv_tx_desc *ixgbe_tx_ring;
     139                 :            :         };
     140                 :            :         volatile uint8_t *qtx_tail;               /* register address of tail */
     141                 :            :         union {
     142                 :            :                 struct ci_tx_entry *sw_ring; /* virtual address of SW ring */
     143                 :            :                 struct ci_tx_entry_vec *sw_ring_vec;
     144                 :            :         };
     145                 :            :         /* Scalar TX path: Array tracking last_id at each RS threshold boundary */
     146                 :            :         uint16_t *rs_last_id;
     147                 :            :         uint16_t nb_tx_desc;           /* number of TX descriptors */
     148                 :            :         uint16_t tx_tail; /* current value of tail register */
     149                 :            :         /* index to last TX descriptor to have been cleaned */
     150                 :            :         uint16_t last_desc_cleaned;
     151                 :            :         /* Total number of TX descriptors ready to be allocated. */
     152                 :            :         uint16_t nb_tx_free;
     153                 :            :         /* Start freeing TX buffers if there are less free descriptors than
     154                 :            :          * this value.
     155                 :            :          */
     156                 :            :         uint16_t tx_free_thresh;
     157                 :            :         /* Number of TX descriptors to use before RS bit is set. */
     158                 :            :         uint16_t tx_rs_thresh;
     159                 :            :         /* Scalar TX path: log2 of tx_rs_thresh for efficient bit operations */
     160                 :            :         uint8_t log2_rs_thresh;
     161                 :            :         uint16_t port_id;  /* Device port identifier. */
     162                 :            :         uint16_t queue_id; /* TX queue index. */
     163                 :            :         uint16_t reg_idx;
     164                 :            :         uint16_t tx_next_dd;
     165                 :            :         uint16_t tx_next_rs;
     166                 :            :         /* Mempool pointer for fast release of mbufs.
     167                 :            :          * NULL if disabled, UINTPTR_MAX if enabled and not yet known.
     168                 :            :          * Set at first use (if enabled and not yet known).
     169                 :            :          */
     170                 :            :         struct rte_mempool *fast_free_mp;
     171                 :            :         uint64_t offloads;
     172                 :            :         uint64_t mbuf_errors;
     173                 :            :         rte_iova_t tx_ring_dma;        /* TX ring DMA address */
     174                 :            :         bool tx_deferred_start; /* don't start this queue in dev start */
     175                 :            :         bool q_set;             /* indicate if tx queue has been configured */
     176                 :            :         bool use_vec_entry;     /* use sw_ring_vec (true for vector and simple paths) */
     177                 :            :         union {                  /* the VSI this queue belongs to */
     178                 :            :                 struct i40e_vsi *i40e_vsi;
     179                 :            :                 struct iavf_vsi *iavf_vsi;
     180                 :            :                 struct ice_vsi *ice_vsi;
     181                 :            :         };
     182                 :            :         const struct rte_memzone *mz;
     183                 :            : 
     184                 :            :         union {
     185                 :            :                 struct { /* ICE driver specific values */
     186                 :            :                         struct ice_txtime *tsq; /* Tx Time based queue */
     187                 :            :                         uint32_t q_teid; /* TX schedule node id. */
     188                 :            :                 };
     189                 :            :                 struct { /* I40E driver specific values */
     190                 :            :                         uint8_t dcb_tc;
     191                 :            :                 };
     192                 :            :                 struct { /* iavf driver specific values */
     193                 :            :                         uint16_t ipsec_crypto_pkt_md_offset;
     194                 :            : #define IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG1 BIT(0)
     195                 :            : #define IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG2 BIT(1)
     196                 :            :                         uint8_t vlan_flag;
     197                 :            :                         uint8_t tc;
     198                 :            :                         bool use_ctx;  /* with ctx info, each pkt needs two descriptors */
     199                 :            :                 };
     200                 :            :                 struct { /* ixgbe specific values */
     201                 :            :                         const struct ixgbe_txq_ops *ops;
     202                 :            :                         struct ixgbe_advctx_info *ctx_cache;
     203                 :            :                         uint32_t ctx_curr;
     204                 :            :                         uint8_t pthresh;   /**< Prefetch threshold register. */
     205                 :            :                         uint8_t hthresh;   /**< Host threshold register. */
     206                 :            :                         uint8_t wthresh;   /**< Write-back threshold reg. */
     207                 :            :                         uint8_t using_ipsec;  /**< indicates that IPsec TX feature is in use */
     208                 :            :                         uint8_t is_vf;   /**< indicates that this is a VF queue */
     209                 :            :                         uint8_t vf_ctx_initialized; /**< VF context descriptors initialized */
     210                 :            :                 };
     211                 :            :                 struct { /* idpf specific values */
     212                 :            :                                 volatile union {
     213                 :            :                                                 struct idpf_flex_tx_sched_desc *desc_ring;
     214                 :            :                                                 struct idpf_splitq_tx_compl_desc *compl_ring;
     215                 :            :                                 };
     216                 :            :                                 struct ci_tx_queue *complq;
     217                 :            :                                 void **txqs;   /*only valid for split queue mode*/
     218                 :            :                                 uint32_t tx_start_qid;
     219                 :            :                                 uint32_t latch_idx; /* Tx timestamp latch index */
     220                 :            :                                 uint16_t sw_nb_desc;
     221                 :            :                                 uint16_t sw_tail;
     222                 :            :                                 uint16_t rs_compl_count;
     223                 :            :                                 uint8_t expected_gen_id;
     224                 :            :                 };
     225                 :            :         };
     226                 :            : };
     227                 :            : 
     228                 :            : struct ci_tx_path_features {
     229                 :            :         uint32_t tx_offloads;
     230                 :            :         enum rte_vect_max_simd simd_width;
     231                 :            :         bool simple_tx;
     232                 :            :         bool ctx_desc;
     233                 :            :         bool disabled;
     234                 :            :         bool single_queue;
     235                 :            : };
     236                 :            : 
     237                 :            : struct ci_tx_path_info {
     238                 :            :         eth_tx_burst_t pkt_burst;
     239                 :            :         const char *info;
     240                 :            :         struct ci_tx_path_features features;
     241                 :            :         eth_tx_prep_t pkt_prep;
     242                 :            : };
     243                 :            : 
     244                 :            : static __rte_always_inline void
     245                 :            : ci_tx_backlog_entry(struct ci_tx_entry *txep, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
     246                 :            : {
     247                 :            :         for (uint16_t i = 0; i < (int)nb_pkts; ++i)
     248                 :            :                 txep[i].mbuf = tx_pkts[i];
     249                 :            : }
     250                 :            : 
     251                 :            : static __rte_always_inline void
     252                 :            : ci_tx_backlog_entry_vec(struct ci_tx_entry_vec *txep, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
     253                 :            : {
     254   [ #  #  #  #  :          0 :         for (uint16_t i = 0; i < nb_pkts; ++i)
             #  #  #  # ]
     255                 :          0 :                 txep[i].mbuf = tx_pkts[i];
     256                 :            : }
     257                 :            : 
     258                 :            : #define IETH_VPMD_TX_MAX_FREE_BUF 64
     259                 :            : 
     260                 :            : typedef int (*ci_desc_done_fn)(struct ci_tx_queue *txq, uint16_t idx);
     261                 :            : 
     262                 :            : static __rte_always_inline int
     263                 :            : ci_tx_free_bufs_vec(struct ci_tx_queue *txq, ci_desc_done_fn desc_done, bool ctx_descs)
     264                 :            : {
     265                 :            :         int nb_free = 0;
     266                 :            :         struct rte_mbuf *free[IETH_VPMD_TX_MAX_FREE_BUF];
     267                 :            :         struct rte_mbuf *m;
     268                 :            : 
     269                 :            :         /* check DD bits on threshold descriptor */
     270   [ #  #  #  #  :          0 :         if (!desc_done(txq, txq->tx_next_dd))
             #  #  #  # ]
     271                 :            :                 return 0;
     272                 :            : 
     273                 :          0 :         const uint32_t n = txq->tx_rs_thresh >> ctx_descs;
     274                 :            : 
     275                 :            :         /* first buffer to free from S/W ring is at index
     276                 :            :          * tx_next_dd - (tx_rs_thresh - 1)
     277                 :            :          */
     278                 :          0 :         struct ci_tx_entry_vec *txep = txq->sw_ring_vec;
     279                 :          0 :         txep += (txq->tx_next_dd >> ctx_descs) - (n - 1);
     280                 :            : 
     281                 :            :         /* is fast-free enabled? */
     282                 :            :         struct rte_mempool *mp =
     283                 :          0 :                         likely(txq->fast_free_mp != (void *)UINTPTR_MAX) ?
     284   [ #  #  #  #  :          0 :                         txq->fast_free_mp :
             #  #  #  # ]
     285                 :          0 :                         (txq->fast_free_mp = txep[0].mbuf->pool);
     286                 :            : 
     287   [ #  #  #  #  :          0 :         if (mp != NULL && (n & 31) == 0) {
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     288                 :            :                 void **cache_objs;
     289                 :            :                 struct rte_mempool_cache *cache = rte_mempool_default_cache(mp, rte_lcore_id());
     290                 :            : 
     291   [ #  #  #  #  :          0 :                 if (cache == NULL)
             #  #  #  # ]
     292                 :          0 :                         goto normal;
     293                 :            : 
     294                 :          0 :                 cache_objs = &cache->objs[cache->len];
     295                 :            : 
     296   [ #  #  #  #  :          0 :                 if (n > RTE_MEMPOOL_CACHE_MAX_SIZE) {
             #  #  #  # ]
     297                 :            :                         rte_mempool_ops_enqueue_bulk(mp, (void *)txep, n);
     298                 :          0 :                         goto done;
     299                 :            :                 }
     300                 :            : 
     301                 :            :                 /* The cache follows the following algorithm
     302                 :            :                  *   1. Add the objects to the cache
     303                 :            :                  *   2. Anything greater than the cache min value (if it
     304                 :            :                  *   crosses the cache flush threshold) is flushed to the ring.
     305                 :            :                  */
     306                 :            :                 /* Add elements back into the cache */
     307                 :            :                 uint32_t copied = 0;
     308                 :            :                 /* n is multiple of 32 */
     309   [ #  #  #  #  :          0 :                 while (copied < n) {
             #  #  #  # ]
     310                 :          0 :                         memcpy(&cache_objs[copied], &txep[copied], 32 * sizeof(void *));
     311                 :          0 :                         copied += 32;
     312                 :            :                 }
     313                 :          0 :                 cache->len += n;
     314                 :            : 
     315   [ #  #  #  #  :          0 :                 if (cache->len >= cache->flushthresh) {
             #  #  #  # ]
     316                 :          0 :                         rte_mempool_ops_enqueue_bulk(mp, &cache->objs[cache->size],
     317                 :          0 :                                         cache->len - cache->size);
     318                 :          0 :                         cache->len = cache->size;
     319                 :            :                 }
     320                 :          0 :                 goto done;
     321                 :            :         }
     322                 :            : 
     323                 :          0 : normal:
     324   [ #  #  #  #  :          0 :         m = rte_pktmbuf_prefree_seg(txep[0].mbuf);
             #  #  #  # ]
     325   [ #  #  #  #  :          0 :         if (likely(m)) {
             #  #  #  # ]
     326                 :          0 :                 free[0] = m;
     327                 :            :                 nb_free = 1;
     328   [ #  #  #  #  :          0 :                 for (uint32_t i = 1; i < n; i++) {
             #  #  #  # ]
     329   [ #  #  #  #  :          0 :                         m = rte_pktmbuf_prefree_seg(txep[i].mbuf);
             #  #  #  # ]
     330   [ #  #  #  #  :          0 :                         if (likely(m)) {
             #  #  #  # ]
     331   [ #  #  #  #  :          0 :                                 if (likely(m->pool == free[0]->pool)) {
             #  #  #  # ]
     332                 :          0 :                                         free[nb_free++] = m;
     333                 :            :                                 } else {
     334   [ #  #  #  #  :          0 :                                         rte_mbuf_raw_free_bulk(free[0]->pool, free, nb_free);
             #  #  #  # ]
     335                 :          0 :                                         free[0] = m;
     336                 :            :                                         nb_free = 1;
     337                 :            :                                 }
     338                 :            :                         }
     339                 :            :                 }
     340   [ #  #  #  #  :          0 :                 rte_mbuf_raw_free_bulk(free[0]->pool, free, nb_free);
             #  #  #  # ]
     341                 :            :         } else {
     342   [ #  #  #  #  :          0 :                 for (uint32_t i = 1; i < n; i++) {
             #  #  #  # ]
     343   [ #  #  #  #  :          0 :                         m = rte_pktmbuf_prefree_seg(txep[i].mbuf);
             #  #  #  # ]
     344                 :            :                         if (m)
     345   [ #  #  #  #  :          0 :                                 rte_mempool_put(m->pool, m);
             #  #  #  # ]
     346                 :            :                 }
     347                 :            :         }
     348                 :            : 
     349                 :          0 : done:
     350                 :            :         /* buffers were freed, update counters */
     351                 :          0 :         txq->nb_tx_free = (uint16_t)(txq->nb_tx_free + txq->tx_rs_thresh);
     352                 :          0 :         txq->tx_next_dd = (uint16_t)(txq->tx_next_dd + txq->tx_rs_thresh);
     353   [ #  #  #  #  :          0 :         if (txq->tx_next_dd >= txq->nb_tx_desc)
             #  #  #  # ]
     354                 :          0 :                 txq->tx_next_dd = (uint16_t)(txq->tx_rs_thresh - 1);
     355                 :            : 
     356         [ #  # ]:          0 :         return txq->tx_rs_thresh;
     357                 :            : }
     358                 :            : 
     359                 :            : static inline void
     360                 :          0 : ci_txq_release_all_mbufs(struct ci_tx_queue *txq, bool use_ctx)
     361                 :            : {
     362   [ #  #  #  # ]:          0 :         if (unlikely(!txq || !txq->sw_ring))
     363                 :            :                 return;
     364                 :            : 
     365         [ #  # ]:          0 :         if (!txq->use_vec_entry) {
     366                 :            :                 /* Regular scalar path uses sw_ring with ci_tx_entry */
     367         [ #  # ]:          0 :                 for (uint16_t i = 0; i < txq->nb_tx_desc; i++) {
     368         [ #  # ]:          0 :                         if (txq->sw_ring[i].mbuf != NULL) {
     369                 :            :                                 rte_pktmbuf_free_seg(txq->sw_ring[i].mbuf);
     370                 :          0 :                                 txq->sw_ring[i].mbuf = NULL;
     371                 :            :                         }
     372                 :            :                 }
     373                 :            :                 return;
     374                 :            :         }
     375                 :            : 
     376                 :            :         /**
     377                 :            :          *  Vector and simple paths use sw_ring_vec (ci_tx_entry_vec).
     378                 :            :          *  vPMD tx will not set sw_ring's mbuf to NULL after free,
     379                 :            :          *  so determining buffers to free is a little more complex.
     380                 :            :          */
     381                 :          0 :         const uint16_t start = (txq->tx_next_dd - txq->tx_rs_thresh + 1) >> use_ctx;
     382                 :          0 :         const uint16_t nb_desc = txq->nb_tx_desc >> use_ctx;
     383                 :          0 :         const uint16_t end = txq->tx_tail >> use_ctx;
     384                 :            : 
     385                 :            :         uint16_t i = start;
     386         [ #  # ]:          0 :         if (end < i) {
     387         [ #  # ]:          0 :                 for (; i < nb_desc; i++)
     388                 :          0 :                         rte_pktmbuf_free_seg(txq->sw_ring_vec[i].mbuf);
     389                 :            :                 i = 0;
     390                 :            :         }
     391         [ #  # ]:          0 :         for (; i < end; i++)
     392                 :          0 :                 rte_pktmbuf_free_seg(txq->sw_ring_vec[i].mbuf);
     393                 :          0 :         memset(txq->sw_ring_vec, 0, sizeof(txq->sw_ring_vec[0]) * nb_desc);
     394                 :            : }
     395                 :            : 
     396                 :            : /**
     397                 :            :  * Select the best matching Tx path based on features
     398                 :            :  *
     399                 :            :  * @param req_features
     400                 :            :  *   The requested features for the Tx path
     401                 :            :  * @param infos
     402                 :            :  *   Array of information about the available Tx paths
     403                 :            :  * @param num_paths
     404                 :            :  *   Number of available paths in the infos array
     405                 :            :  * @param default_path
     406                 :            :  *   Index of the default path to use if no suitable path is found
     407                 :            :  *
     408                 :            :  * @return
     409                 :            :  *   The packet burst function index that best matches the requested features,
     410                 :            :  *   or default_path if no suitable path is found
     411                 :            :  */
     412                 :            : static inline int
     413                 :          0 : ci_tx_path_select(const struct ci_tx_path_features *req_features,
     414                 :            :                         const struct ci_tx_path_info *infos,
     415                 :            :                         size_t num_paths,
     416                 :            :                         int default_path)
     417                 :            : {
     418                 :            :         int idx = default_path;
     419                 :            :         const struct ci_tx_path_features *chosen_path_features = NULL;
     420                 :            : 
     421         [ #  # ]:          0 :         for (unsigned int i = 0; i < num_paths; i++) {
     422                 :          0 :                 const struct ci_tx_path_features *path_features = &infos[i].features;
     423                 :            : 
     424                 :            :                 /* Do not select a path with a NULL pkt_burst function. */
     425         [ #  # ]:          0 :                 if (infos[i].pkt_burst == NULL)
     426                 :          0 :                         continue;
     427                 :            : 
     428                 :            :                 /* Do not select a disabled tx path. */
     429         [ #  # ]:          0 :                 if (path_features->disabled)
     430                 :          0 :                         continue;
     431                 :            : 
     432                 :            :                 /* Do not use a simple tx path if not requested. */
     433   [ #  #  #  # ]:          0 :                 if (path_features->simple_tx && !req_features->simple_tx)
     434                 :          0 :                         continue;
     435                 :            : 
     436                 :            :                 /* If a context descriptor is requested, ensure the path supports it. */
     437   [ #  #  #  # ]:          0 :                 if (!path_features->ctx_desc && req_features->ctx_desc)
     438                 :          0 :                         continue;
     439                 :            : 
     440                 :            :                 /* If requested, ensure the path supports single queue TX. */
     441         [ #  # ]:          0 :                 if (path_features->single_queue != req_features->single_queue)
     442                 :          0 :                         continue;
     443                 :            : 
     444                 :            :                 /* Ensure the path supports the requested TX offloads. */
     445         [ #  # ]:          0 :                 if ((path_features->tx_offloads & req_features->tx_offloads) !=
     446                 :            :                                 req_features->tx_offloads)
     447                 :          0 :                         continue;
     448                 :            : 
     449                 :            :                 /* Ensure the path's SIMD width is compatible with the requested width. */
     450         [ #  # ]:          0 :                 if (path_features->simd_width > req_features->simd_width)
     451                 :          0 :                         continue;
     452                 :            : 
     453                 :            :                 /* Do not select the path if it is less suitable than the chosen path. */
     454         [ #  # ]:          0 :                 if (chosen_path_features != NULL) {
     455                 :            :                         /* Do not select paths with lower SIMD width than the chosen path. */
     456         [ #  # ]:          0 :                         if (path_features->simd_width < chosen_path_features->simd_width)
     457                 :          0 :                                 continue;
     458                 :            :                         /* Do not select paths with more offloads enabled than the chosen path if
     459                 :            :                          * the SIMD widths are the same.
     460                 :            :                          */
     461         [ #  # ]:          0 :                         if (path_features->simd_width == chosen_path_features->simd_width &&
     462                 :            :                                         rte_popcount32(path_features->tx_offloads) >
     463         [ #  # ]:          0 :                                         rte_popcount32(chosen_path_features->tx_offloads))
     464                 :          0 :                                 continue;
     465                 :            : 
     466                 :            :                         /* Don't use a context descriptor unless necessary */
     467   [ #  #  #  # ]:          0 :                         if (path_features->ctx_desc && !chosen_path_features->ctx_desc)
     468                 :          0 :                                 continue;
     469                 :            :                 }
     470                 :            : 
     471                 :            :                 /* Finally, select the path since it has met all the requirements. */
     472                 :          0 :                 idx = i;
     473                 :          0 :                 chosen_path_features = &infos[idx].features;
     474                 :            :         }
     475                 :            : 
     476                 :          0 :         return idx;
     477                 :            : }
     478                 :            : 
     479                 :            : /* include the scalar functions at the end, so they can use the common definitions.
     480                 :            :  * This is done so drivers can use all functions just by including tx.h
     481                 :            :  */
     482                 :            : #include "tx_scalar.h"
     483                 :            : 
     484                 :            : #endif /* _COMMON_INTEL_TX_H_ */

Generated by: LCOV version 1.14